💾 Archived View for thingvellir.net › rutentoy › protocol.gmi captured on 2023-01-29 at 15:49:03. Gemini links have been rewritten to link to archived content
View Raw
More Information
⬅️ Previous capture (2023-01-29)
➡️ Next capture (2023-03-20)
-=-=-=-=-=-=-
Rutentoy Protocol
This is a work-in-progress net protocol spec for a yet-unimplemented video game.
The Rutentoy protocol uses either the SCTP or TCP transport protocol, on port 29778 by default. Other transport protocols such as UDP or WebSocket may also be used, though their encodings for reliable transport and packet ordering are out-of-scope for this specification.
The opcode numbers before the packet names are hexadecimal.
References
QOI Format (36KB application/pdf)
xxHash (14KB text/markdown)
Types
All integers are two's-compliment when signed and are in little-endian byte order.
Text strings are encoded as UTF-8 without a BOM.
Object positions are encoded as signed 24-8 fixed point.
Object rotations are encoded as unsigned 0-16 fixed point, representing fractions of 1 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 message-specific identifiers, not permanent client data as the term is used for the Web.
Server Info Sequence
- C: Opens socket
- C→S: Message (Client IPC) "INFO"
- S→C: Message (Client IPC) "INFO (number of total player slots);(number of occupied player slots);(timezone offset);(message-of-the-day text);(optional extra text);"
- S: Closes socket
Login Sequence
- C: Opens socket
- C→S: Message (Client IPC) "LOGIN (username) [passkey, may contain spaces]"
- (Optional) Client-to-Server Texture Exchange Sequence, see below
- S→C: World Chunk
- S→C: Object Create (eid 0)
- S→C: Object Move (eid 0)
- C: Ready for Play
Client-to-Server Texture Exchange Sequence
If the server has the player's texture cached:
- C→S: Message (Client IPC) "HASTEX (hex xxHash32 digest of player's texture)"
- S→C: Message (Client IPC) "HAVETEX 1"
If the server doesn't have the player's texture cached:
- C→S: Message (Client IPC) "HASTEX (hex xxHash32 digest of player's texture)"
- S→C: Message (Client IPC) "HAVETEX 0"
- C→S: Object Texture Chunk (eid 0)
Server-to-Client Texture Exchange Sequence
If the client already has the requested texture:
- S→C: Message (Client IPC) "HASTEX (hex xxHash32 digest of texture)"
- C→S: Message (Client IPC) "HAVETEX 1"
If the client doesn't have the requested texture:
- S→C: Message (Client IPC) "HASTEX (hex xxHash32 digest of texture)"
- C→S: Message (Client IPC) "HAVETEX 0"
- S→C: Object Texture Chunk
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 {
opcode: u8 = 0x00,
}
sizeof(00_disconnect) = 1
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 {
opcode: u8 = 0x01,
cookie: u32,
}
sizeof(01_ping) = 5
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:
- 0:0, Humanoid: A biped with two arms and a head. The default appearance of this model should be generic, not visibly gendered, and should have a non-human skin tone such as gray, blue, or bright yellow. The client may optionally support utilising unused portions of the player model texture for implementation-specific extensions.
- 1:Varies, Block/Item: The object appears as a full-size block or item, separated from static world blocks.
struct 02_create {
opcode: u8 = 0x03,
oid: u32, // unique object id
model: u16, // model id
model_meta: u16, // extra metadata for the model
}
sizeof(02_create) = 9
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 {
opcode: u8 = 0x02,
oid: u32, // unique object id, see 02 Object Create
x: i32, // signed 24-8 position fixed-point
y: i32,
z: i32,
yaw: u16, // unsigned 0-16 angle fixed-point
pitch: u16,
}
sizeof(03_move) = 21
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 {
opcode: u8 = 0x04,
oid: u32, // unique object id
}
sizeof(04_delete) = 5
04 Object Texture Chunk
Sent by the client to give the server a custom player-specified model texture. The server or client may optionally cache textures on disk. The server may implement a minimum time limit between each texture sent by the client.
The 'data_len' field being set to less than 1024 indicates the packet is the final chunk for the texture being sent.
The server or client must not abuse this packet to create animated textures.
The textures are sent ad-hoc to avoid relying on a centralised texture server. The maximum texture size is 128x128. Textures must be have power-of-two dimensions. The image data is QOI encoded, which also includes a header containing the image dimensions.
struct 04_texture {
opcode: u8 = 0x05,
oid: u32, // unique object id
cookie: u32, // unique identifier for this specific texture
data_len: u16, // how many bytes in the 1024-byte chunk is used
data: [1024]u8, // a 1024-byte chunk of QOI data
}
sizeof(04_texture) = 1035
05 Object Metadata
Sent by the server to update an object model's details.
Required Supported 'meta_type' Values
- 0, Color: The 'meta_data' field contains three bytes for an RGB color tint and a byte for glow intensity, 0 being no glow and 255 being full brightness at all times. The client may optionally ignore the glow byte and always draw objects with normal lighting.
- 1, Animate: The 'meta_data' field contains an animation ID. Some animations are temporary and some change a model's posture or animation mode.
- 2, Equipment: The 'meta_data' field contains an item or block ID, and a 4-bit number describing where the equipment should be shown on the model. An item/block ID of 0 removes the equipment from the specified area on the model. The client may send this to the server.
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.
- 0, Idle/Stand (Stance): The object stands up normally and moves in a walking motion when moving. For non-humanoid models, the object does not move at all. This is the default animation.
- 1, Crouch (Stance): The object crouches down and moves in a walking motion when moving.
- 2, Punch Right (Overlay): The object swings its right arm in a punching motion.
- 3, Punch Left (Overlay): The object swings its left arm in a punching motion.
- 4, Swing Right (Overlay): The object swings its right arm as if swinging a weapon or tool.
- 5, Swing Left (Overlay): The object swings its left arm as if swinging a weapon or tool.
- 6, Death (Stance): The object falls down and optionally disappears.
- 7, Item (Stance): The object becomes smaller and either slowly shines or slowly spins floating above the ground. This is intended for use with the 1 Block/Item model, although the client may optionally support this on other models as well.
- 8, Aim Weapon Start (Overlay): The object holds its arms out as if holding a pulled bow or sling.
- 9, Aim Weapon End (Overlay): The 6 Aim Weapon Start animation ends.
- 10, Hurt (Overlay): The object moves as if it was just hit by an attack.
Model Equipment Slot IDs
- 0 Head
- 1 Chest
- 3 Legs
- 4 Boots
- 5 Right Hand
- 6 Left Hand
- 7 Left Hip
- 8 Right Hip
- 9 Back Holster 1
- A Back Holster 2
- B Backpack
- C-F Unused
struct 06_object_meta {
opcode: u8 = 0x06,
oid: u32, // unique object id
meta_type: u8, // what detail should be changed
meta_data: u32, // 32 arbitrary bits of data, depends on meta_type
}
sizeof(06_object_meta) = 10
07 Interact
Sent by the client to indicate the player is interacting with a block, item, or object.
Interaction Types
- 0 Use Block
- 1 Use Object
- 2 Use Item in Right Hand
- 3 Use Item in Left Hand
- 4 Use Item in Right Hand on Object
- 5 Use Item in Left Hand on Object
- 6 Use Item in Right Hand on Block
- 7 Use Item in Left Hand on Block
- 8 Swing Item in Right Hand
- 9 Swing Item in Left Hand
- A Attack Object with Item in Right Hand
- B Attack Object with Item in Left Hand
- C Begin Breaking Block
- E Complete Breaking Block
- F Cancel Breaking Block
struct 07_interact {
opcode: u8 = 0x07,
mode: u8, // F0 attack/use, 0F interaction type
oid: u32, // targeted object, 0 if none
block_x: i32, // targeted block position
block_y: i32,
block_z: i32,
item: u16, // used item ID
}
sizeof(07_interact) = 20
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
- 0 Close: Sent by the client or the server to close an open GUI.
- 1 Player: Sent by the client or the server. There is one 5x5 item field representing the player's inventory. There is two 1x4 item fields on the left and right for wearable items. Inbetween these two fields is a display of the player's appearance.
- 2 Cooking: Sent by the server. There is two 3x3 item fields on the left and right, for uncooked and cooked items respectively. There is a single item slot inbetween that is for fuel items.
- 3 8x8 Container: Sent by the server. A single 8x8 item field representing the contents of a container.
struct 08_gui_open {
opcode: u8 = 0x08,
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) = 12
09 GUI Interact
Sent by the client to move a container's items between slots or other containers.
Modes
- 0 Take, the player takes an item from a slot
- 1 Place, the player places a previously taken item into a slot
- 2 Swap, the player swaps the items between two slots
- 3 Throw, the player throws the item onto the floor
struct 09_gui_interact {
opcode: u8 = 0x09,
mode: u8,
send_cookie: u16,
recv_cookie: u16,
send_slot: u8,
recv_slot: u8,
}
sizeof(09_gui_interact) = 8
0A GUI Items
TODO
struct 0a_gui_items {
opcode: u8 = 0x0a,
}
sizeof(0a_gui_items) = ??
0B Message
A text message sent to the server, or a text message sent from the server to display on the client. The only ASCII control characters allowed are 00 NUL and 0A LF. Implementations must not assume that non-UTF-8 data will be transferred losslessly.
Channels
The channel field describes where the message should be displayed.
The following is a list of defined values, with names suggesting use cases:
- 0 Chat: The normal chat area players can send messages to. This area has a history listing of recently sent messages.
- 1 Small Announcement: The top-right of the screen. May be used for player death messages or minor announcements.
- 2 Announcement: Above the center of the screen. Messages sent here disappear after 5 seconds.
- 3 Hotbar: The bottom-center of the screen, above the player's hotbar if it is visible. Messages sent here disappear after 5 seconds.
- 4 Timer: The top-center of the screen. The most recent message sent here displays permanently, until an empty or zero-length message is sent.
- 5 Client IPC: Used for transferring textual information between the server and client. This message type must never be relayed to other clients. This message area should be hidden by default.
- 6 Plugin IPC: Not visible to human players. Used by plugins and bot players to communicate with eachother and the server. This message channel should be used conservatively to avoid swamping clients with message packets.
- 7 System: The top-left of the screen, used for minor server announcements or diagnostics. The client may optionally include its own diagnostic messages in this area.
- 8-127: These channels are implementation-defined.
struct 0b_message {
opcode: u8 = 0x0a,
cookie: u32, // a unique identifier for the whole message
// so multiple message chunks can be sent in parallel
channel: u8, // 8th bit final chunk marker, 7 bits of msg channel
msg: [64]u8, // a chunk of utf-8 text, padded with
// 00 bytes if the chunk is < 64 bytes long
}
sizeof(0b_message) = 66
10 World Chunk
Sends the block data for a 8Âł 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.
TODO: should this packet be compressed? it gets sent a lot and 1031 bytes aren't nothing
struct 10_chunk {
opcode: u8 = 0x10,
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) = 1031
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 {
opcode: u8 = 0x11,
chunk_x: i21, // these three fields are packed into 8 bytes
chunk_y: i19,
chunk_z: i21,
block_x: u4, // these four fields are packed into two bytes
block_y: u4,
block_z: u4,
block_nibble: u4, // the upper 4 bits of the block ID
block: u8,
}
sizeof(11_block) = 12
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
- 0 Block Breaking Animation (data1,2,3 are block position, data4 is breaking progress from 1-8, 0 removes animation overlay)
- 1 Weather (see the 'Weather Effects' section below)
- 1 Block/Item Break (data1,2,3 are signed fixed point 24.8 object position, data4 is block/item ID)
- 2 Explosion (data1,2,3 are signed fixed point 24.8 object position, data4 is 24-bit RGB and a scale modifier)
- 3 Smoke (data1,2,3 are signed fixed point 24.8 object position, data4 is 24-bit RGB and a scale modifier)
- 4 Water Splash (data1,2,3 are signed fixed point 24.8 object position, data4 is 24-bit RGB and a scale modifier)
Weather Effects
- 0 Clear: Removes any currently active weather effects.
- 1 Start Day Cycle: The client starts automatically animating the sun moving through the sky. 'data2' is the time the client should start animating from. 'data2' is unsigned 0.32 fixed point, encoding fractions of one day rotation, starting and ending with the sun rising from the horizon.
- 2 Stop Day Cycle: The client stops moving the sun if it was already moving. 'data2' is the same as described in 1 Start Day Cycle.
- 3 Sky Color: 'data2' is an RGBX color for the daytime sky. 'data3' is an RGBX color for the nighttime sky. 'data4' is an RGBA color for dawn or dusk sky.
- 4 Light Color: 'data2' is an RGBX color for sunlight. 'data3' is an RGBX color for artificial lights. 'data4' is an RGBX ambient color for unlit areas.
- 5 Fog: 'data2' is an RGBX fog color. 'data3' is the fog density scale. 'data4' is an interpolation time, in 40 millisecond increments.
struct 12_world_effect {
opcode: u8 = 0x12,
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) = 18
20 Gamemode Settings
Sent by the server to allow various cheats or gamemode tweaks on the client. Servers should not assume the client will cooperate with these settings.
Flags
- Bit 0: Invulnerable (also hides health/armor UI)
- Bit 1: Allow Flight
- Bit 2: Allow No-clip (implies bit 1)
- Bit 3: Unlimited Items
- Bit 4: Set Blocks Instantly
- Bit 5: Disallow Movement (gravity still applies unless bit 1 is set)
- Bit 6: Disallow Rotation
- Bit 7: Disallow Jumping
- Bit 8: Player X-ray (allows seeing other player characters through the world)
- Bit 9: NPC X-ray (allows seeing NPCs through the world)
- Bit 10: No Fall Damage
- Bit 11: Disallow Player-vs-Player Damage
- Bit 12: Disallow Player-vs-NPC Damage
- Bit 13: Spectate on Death (when set, the player character can fly around and see through other objects' eyes, when unset, the player character stays stationary and their screen fades)
- Bit 14: Auto Respawn (when unset, the client should show a "Respawn" button when the player character dies)
- Bit 15: Allow Debug Info
struct 20_gamemode {
opcode: u8 = 0x20,
permissions: u16,
walk_speed: u16, // unsigned 8.8 fixed point
jump_height: u16, // ditto
}
sizeof(20_gamemode) = 7
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.
- 000 Empty/Air
- 010 Dirt
- 011 Grass-covered dirt
- 012 Leaves-covered dirt
- 013 Sand
- 014 Red Sand
- 015 Gravel
- 016 Mud
- 017 Clay
- 018 Mud Bricks
- 019 Clay Bricks
- 01A Tilled Dirt
- 020 Stone
- 021 Marble
- 022 Basalt
- 023 Obsidian
- 024 Iron, rendered as ore in-world and as an un-placeable iron lump item
- 025 Coal, rendered as ore in-world and as an un-placeable coal lump item
- 026 Ruby, rendered as ore in-world and as an un-placeable gemstone item
- 027 Olivine, rendered as ore in-world and as an un-placeable gemstone item
- 028 Sapphire, rendered as ore in-world and as an un-placeable gemstone item
- 029 Zircon, rendered as ore in-world and as an un-placeable gemstone item
- 030 Brown-barked Log, facing Y
- 031 Brown-barked Log, facing X
- 032 Brown-barked Log, facing Z
- 033 White-barked Log, facing Y
- 034 White-barked Log, facing X
- 035 White-barked Log, facing Z
- 036 Leaves
- 037 Leaves with Fruit
- 038 Vine
- 039 Grass Tuft
- 03A Small Bush
- 03B Brown-barked Sapling
- 03C White-barked Sapling
- 03D Dead Bush
- 03E Cactus
- 03F Water Lily
- 040 White Flower
- 041 Yellow Flower
- 042 Red Flower
- 043 Blue Flower
- 044 Red Berries
- 045 Black Berries
- 046 White Mushroom
- 047 Brown Mushroom
- 048 Orange Mushroom, attaches to the side of a block rather than the ground
- 049 Red Mushroom, poisonous
- 04A Dead Crops
- 04B Crops (04B-04F are height from 25% to 100%)
- 050 Freshwater (050-053 are height from 100% to 25%)
- 054 Swampwater (054-057 are height from 100% to 25%)
- 058 Seawater (058-05B are height from 100% to 25%)
- 05C Lava (05C-05F are height from 100% to 25%)
- 060 Wooden Planks
- 061 Wooden Fence
- 062 Wooden Planks Half-block, facing -Y
- 063 Wooden Planks Half-block, facing +Y
- 064 Wooden Planks Half-block, facing -X
- 065 Wooden Planks Half-block, facing +X
- 066 Wooden Planks Half-block, facing -Z
- 067 Wooden Planks Half-block, facing +Z
- 068 Pale Wooden Planks
- 069 Pale Wooden Fence
- 06A Pale Wooden Planks Half-block, facing -Y
- 06B Pale Wooden Planks Half-block, facing +Y
- 06C Pale Wooden Planks Half-block, facing -X
- 06D Pale Wooden Planks Half-block, facing +X
- 06E Pale Wooden Planks Half-block, facing -Z
- 06F Pale Wooden Planks Half-block, facing +Z
- 070 Rope, facing Y
- 071 Rope, facing X
- 072 Rope, facing Z
- 073 Chain, facing Y
- 074 Chain, facing X
- 075 Chain, facing Z
- 076 Ladder, facing -X
- 077 Ladder, facing +X
- 078 Ladder, facing -Y
- 079 Ladder, facing +Y
- 07A Ladder, facing -Z
- 07B Ladder, facing +Z
- 07C Unlit Firepit
- 07D Lit Firepit
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.
- 800 Stick, digs through dirt-like blocks slightly faster
- 801 Stone
- 802 Flint
- 803 Kindling
- 810 Sharpened Stone, meta is remaining sharpness; zero turns this item back into 801 Stone
- 811 Stone Axe, meta is remaining sharpness; zero makes tool slower
- 812 Flint Firelighter, requires kindling to start fire
- 813 Steel Knife, meta is remaining sharpness; zero makes tool slower and deal less combat damage