💾 Archived View for thingvellir.net › rutentoy › protocol.gmi captured on 2023-04-26 at 13:09:15. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-04-19)

➡️ Next capture (2024-07-08)

-=-=-=-=-=-=-

Rutentoy Protocol

This is a work-in-progress net protocol spec for a yet-unimplemented video game.

The Rutentoy protocol can work over TCP, UDP, SCTP, or WebSocket.

The DNS SRV service name for this protocol is 'rutentoy'.

The opcode numbers before the packet names in this document are hexadecimal.

TCP packets may combine multiple game packets.

UDP packets must be sent individually and have a maximum size of 1050 bytes.

Types

All integers are two's-compliment when signed and are in big-endian byte order.

Text strings are encoded as UTF-8 without a BOM or null terminator.

Object positions are encoded as signed 24-8 fixed point.

Object rotations are encoded as unsigned 0-16 fixed point, representing fractions of one turn. 0-65536 should be scaled to 0-2π.

Structure fields are not aligned and do not contain padding. They are not intended to be read directly into program memory.

Structure fields named 'cookie' refer to ephemeral identifiers, not semi-permanent client data as the term is used for the Web. This document does not specify a specific algorithm for determining cookie values.

All packets are prefixed with a single opcode byte, followed by an unsigned 16 bit integer representing the length of the following packet data. This is to allow partial implementations and protocol extensions.

Over unreliable transports such as UDP, the packet is also prefixed with a monotonically increasing unsigned 64-bit integer, starting with zero and increasing for every sent packet. If a gap in this sequence is detected, a packet is known to have been dropped.

Server Info Sequence

Login Sequence

00 Disconnect

Sent by either the client or the server to announce the network socket is about to be closed. Usually prefixed with the "LEAVE ..." Client IPC message to describe why the disconnect happened. The server may optionally announce a client disconnecting by sending a 'player has left' message to the System channel.

struct 00_disconnect {}

sizeof(00_disconnect) = 0

01 Ping

Sent by the server to check for both the network latency and responsiveness of a client. The client should echo this packet back to the server when recieved.

struct 01_ping {
    cookie: u32,
}

sizeof(01_ping) = 4

02 Object Create

Sent by the server to create a movable object on the client. How the server determines the value of the 'oid' field is implementation-defined.

The following list is a list of model IDs that a client must support rendering:

struct 02_create {
    oid: u32,        // unique object id
    model: u16,      // model id
    model_meta: u16, // extra metadata for the model
}

sizeof(02_create) = 8

03 Object Move

Sent by the client every 40 milliseconds with the entity field set to zero.

The server sends this to a client with the entity field set to zero to teleport them.

The server sends this to a client with the entity field set to a nonzero value to update the position and rotation of another object model.

struct 03_move {
    oid: u32,   // unique object id, see 02 Object Create
    x: i32,     // signed 26-6 position fixed-point
    y: i32,
    z: i32,
    yaw: u16,   // unsigned 0-16 angle fixed-point
    pitch: u16,
}

sizeof(03_move) = 20

04 Object Delete

The server sends this to a client to remove an object model.

If sent with the entity field set to zero, the client displays an intermission screen until it is sent another 02 Object Create packet with the 'oid' field set to zero.

When a client receives this packet with the 'oid' field set to zero, world data and objects are cleared to avoid incongruencies with possible future data.

struct 04_delete {
    oid: u32, // unique object id
}

sizeof(04_delete) = 4

04 Object Texture Chunk

Sent by the client to give the server a custom player-specified model texture.

The server or client must not abuse this packet to create animated textures.

The maximum texture size is 128x128. Textures must be have power-of-two dimensions. The image data is encoded as two unsigned, little-endian, 16 bit integers for the width and height of the image, followed by ARGB image data bytes.

struct 04_texture {
    oid: u32,          // unique object id
    chunk_num: u16,    // which chunk is being sent, in case of out-of-order
    cookie: u32,       // unique identifier for this specific texture
    data_len: u16,     // how many bytes in the 1024-byte chunk is used,
                       // 16th bit indicates final chunk
    data: [1024]u8,    // a 1024-byte chunk of data
}

sizeof(04_texture) = 1036

05 Object Metadata

Sent by the server to update an object's details.

Required Supported 'meta_type' Values

Animation IDs

Some animation IDs will only work with certain models. Animations with (Overlay) next to their name should be layered on top of the current (Stance) animation.

Model Equipment Slot IDs

struct 06_object_meta {
    oid: u32,          // unique object id
    meta_data: u32,    // 32 arbitrary bits of data, depends on meta_type
    meta_type: u8,     // what detail should be changed
}

sizeof(06_object_meta) = 9

07 Interact

Sent by the client to indicate the player is interacting with a block, item, or object.

When a player fully breaks a block with an effective tool, the block is immediately placed into their inventory. If no item slots are available in the player's inventory, the item appears at the center of the broken block's position.

Interaction Types

struct 07_interact {
    oid: u32,          // targeted object, 0 if none
    block_x: i32,      // targeted block position
    block_y: i32,
    block_z: i32,
    item: u16,         // F000 interaction type, 0FFF used item ID
}

sizeof(07_interact) = 18

08 GUI Open

Sent by the server to open a GUI screen on the client. Sent by the client to notify a GUI screen being closed.

Modes

struct 08_gui_open {
    mode: u16,         // which gui to open
    cookie: u16,       // a client-unique identifier for the opened gui,
                       // set to 0 when using mode 1
}

sizeof(08_gui_open) = 4

09 GUI Interact

Sent by the client to move a container's items between slots or other containers.

Modes

struct 09_gui_interact {
    mode: u8,
    send_slot: u8,
    recv_slot: u8,
    send_cookie: u16,
    recv_cookie: u16,
}

sizeof(09_gui_interact) = 7

0A GUI Items

TODO

struct 0a_gui_items {}

sizeof(0a_gui_items) = ??

0B Text

A text message sent to the server, or a text message sent from the server to display on the client. The only ASCII control character allowed is 0A LINEFEED. Implementations must not assume that non-UTF-8 data will be transferred losslessly.

Minimal implementations may opt to only display ASCII or UTF-8 encoded Latin-1 characters.

Channels

The channel field describes where the message should be displayed.

The following is a list of defined values:

struct 0b_message {
    channel: u8,       // 8th bit final chunk marker, 7 bits of msg channel
    chunk_num: u16,    // which chunk is being sent, in case of out-of-order
    cookie: u24,       // a unique identifier for the whole message
                       // so multiple message chunks can be sent in parallel
    msg: [64]u8,       // a chunk of plain utf-8 text, padded with
                       // 00 bytes if the chunk is < 64 bytes long
}

sizeof(0b_message) = 68

10 World Chunk

Sends the block data for a 8x8x8 world chunk. The data field contains an uncompressed block ID array and metadata array.

The lower metadata nibble contains a lightmap value for artificial lights. The upper metadata nibble contains the third nibble of the block ID.

The server can send this to replace an already loaded chunk rather than sending multiple 11 Set Block packets.

Clients may assume that unsent chunks are empty and filled with air.

struct 10_chunk {
    x: i21, // chunk coordinate, these three fields are packed into 8 bytes
    y: i19,
    z: i21,
    blocks: [512]u8,
    meta: [512]u8,
}

sizeof(10_chunk) = 1030

11 Set Block

Sent by the client or the server to update a single block in a chunk.

The client should only directly send this packet if the server allows it with the 'Set Blocks Instantly' permission in the 20 Gamemode Settings packet.

struct 11_block {
    x: i32,
    y: i32,
    z: i32,
    block: u16, // only bits 1-12 are used
}

sizeof(11_block) = 14

12 World Effect

Sent by the server to create a special effect. Supporting this packet and its effects is optional. Clients not implementing this packet should still read this packet and ignore its contents.

Modes

Weather Effects

struct 12_world_effect {
    mode: u8,
    data1: u32, // may be signed or unsigned, depending on the value of 'mode'
    data2: u32,
    data3: u32,
    data4: u32,
}

sizeof(12_world_effect) = 17

20 Gamemode Settings

Sent by the server to allow various cheats or gamemode tweaks on the client. The server should not implicitly assume the client will obey these settings.

Flags

struct 20_gamemode {
    flags: u16,
    walk_speed: u16,  // unsigned 8.8 fixed point multiplier
    jump_height: u16, // ditto
    gravity: u16,     // ditto
}

sizeof(20_gamemode) = 8

Block IDs

A list of defined block IDs and their names. The IDs are written in hexadecimal. IDs not present on this list should be rendered on the client with a texture that makes it obvious the ID is unused.

This particular encoding for block IDs allows for better compression by storing two most significant nibbles of the block ID in one byte array, and the third least significant nibble and a lightmap value in a second byte array.

Item IDs

A list of defined item IDs and their names. The ID is written in hexadecimal. Items that use the meta field will describe how they use it.