Multiplayer & Networking

Client-Server Architecture

Each client is connected to the server. The server receives information and then sends it to clients when needed. This allows you to see other players moving around for example.

KrunkScript separates logic into two execution contexts:

The server should always have authority over important game state. Never trust the client for authoritative logic like scoring, health, or item ownership.

Sending Data

To send information from the client to the server:

# client-side: send network message to server
GAME.NETWORK.send(
    "test", # str message key
    {a: 1}  # obj data to send
);

The server has multiple ways to send data to clients:

# server-side: send network message to specific client
GAME.NETWORK.send(
    "test",            # str message key
    {a: 1},            # obj data to send
    (str) player.id    # str player id to send data to
);

# server-side: send network message to all clients
GAME.NETWORK.broadcast(
    "test", # str message key
    {a: 1}  # obj data to send
);

Receiving Data

Both the client and server scripts have built-in hooks that receive network messages.

Server-side - receives data from clients. The playerID tells you who sent it:

public action onNetworkMessage(str id, obj data, str playerID) {
    # id is the unique id of the network message
    # data contains custom data from the client
    # playerID is the unique ID of the player that sent it
    if (id == "test") {
        GAME.log((num) data.x); # access property
    };
}

Client-side - receives data from the server:

public action onNetworkMessage(str id, obj data) {
    # id is the unique id of the network message
    # data contains custom data from the server
    if (id == "test") {
        GAME.log((num) data.x); # access property
    };
}

Rate Limiting

Network messages are rate limited. You can detect if you have hit the limit:

# server-side: check for success
if (GAME.NETWORK.broadcast("hi there", {a: 1})) {
    # message was sent
} else {
    # message was rate limited
}

Network Performance

It is important to consider networking performance when sending data. The more frequently you send data, the higher the impact on performance. Send as little data as possible:

# BAD: too much data
GAME.NETWORK.send("myNetworkMessage", {
    valueName: "test",
    longNumber: 1020.925827
});

# GOOD: minimal data with short keys
GAME.NETWORK.send("1", {
    t: "test",
    n: Math.round(1020.925827) # round value
});

In short: less data sent less frequently is better for your performance.

Syncing Objects

When synchronizing an object's position in a multiplayer environment, the server should have authority. For example, to have a cube that moves for all players:

  1. Update the object position on the server
  2. Broadcast position changes to clients at a fixed rate
  3. On the client, apply the received position

Network Limits

LimitValue
Message ID length10 characters
Data size2000 bytes
Broadcast (server to all)10 msg/sec
Send (server to client)20 msg/sec per user
Send (client to server)40 msg/sec

If you run into issues with these limitations, restructure your data and logic to send less data less frequently.