Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Objects and identifiers

How the things a match is about are named on the wire, and when an object enters and leaves a client’s world.

The identifiers

IdentifierWidthFormedNo one
Player id64 bits, signedthe player’s account; a client is given its own when started-1, every bit set
Client id32 bits, unsignedchosen by the server for each player at registration, counting from 04294967295
Seata place in a side listthe order of a side’s player ids in Rosteran empty place
Net id32 bits, unsignedchosen by the server for what it creates; worked out from a name for what a map holds0
Node8 bits, unsignedthe owning client’s client id plus 1, or 0 for an object no client owns0
Region id32 bits, unsignedchosen by the server for each region, and carried by RegionAddedsee below
Name hash32 bits, unsignedworked out from the name of a spell, an effect, a particle or a bone0

A field’s own definition gives its exact type. Where a field carries one of these, it carries it whole, at the width above.

No region id stands for no region.

A server MUST give each player a client id from 0 to 252.

How they relate

A player is known by a player id. A server answers a client’s Register with Registered, and the one carrying the client’s own player id gives the client its own client id.

Registration pairs each player id with a client id: a server answers a client’s Register with one Registered for every seat. Every later message that names a player by client id is read through that pairing.

Roster lists each side’s player ids in order, and a player’s seat is their place in that list. A client finds a seat’s client id through its player id. SeatName, SeatChampion and the VersionSync seats name a player by player id; SeatLoadProgress names both.

A champion carries the client id of the player it belongs to. The CreateChampion carrying a client’s own client id makes that champion the client’s own.

A bot’s champion carries 4294967295.

Net ids

A net id names one object in a client’s world: a unit, a missile, a particle, a marker, a prop. The header of every game message carries one, and fields naming a unit, an owner or a target carry one too.

  • A server MUST NOT give an object net id 0, which names nothing.
  • A server SHOULD NOT give an object a net id whose top byte is 0xFF, which the identifiers of what a map holds use, nor one whose top byte is any client’s client id plus 1, which a client uses for objects of its own making.
  • A server MUST NOT give a new object a net id it has given another object in the same match, except in a soft reconnect (see below).

A client that still holds the earlier object creates the new one but keeps the net id on the old one, so messages naming it reach the old object, and removing either leaves the id naming neither.

A create message carries a node beside the object’s net id.

Nothing a player sees depends on it.

Net ids of what a map holds

Some objects are on the field before any message puts them there, and no message ever does: the buildings a side defends, the shops beside them, and the spawn points a side’s minions come from. A receiving end knows them from the map it loaded, and every message naming one names it by an identifier worked out from that object’s name in the map.

The identifier is the CRC-32 of the name, with the top byte set:

identifier = crc32(name) | 0xFF000000

The name is taken byte for byte with its case kept, so OrderShop01 and orderShop01 are two names and give two identifiers. The CRC-32 is the common one: the polynomial 0x04C11DB7 read reflected, starting from 0xFFFFFFFF and finishing with every bit inverted, so the nine bytes 123456789 give 0xCBF43926.

Among the identifiers with that top byte are these:

NameIdentifier
Barracks_T1_C10xFF4A20F1
Barracks_T1_L10xFFD23C3E
Barracks_T1_R10xFF9303E1
Barracks_T2_C10xFFFF8F1F
Barracks_T2_L10xFF6793D0
Barracks_T2_R10xFF26AC0F
__P_Order_Spawn_Barracks__C010xFFB77171
__P_Order_Spawn_Barracks__L010xFFEB364C
__P_Order_Spawn_Barracks__R010xFF53B836
__P_Chaos_Spawn_Barracks__C010xFFBA00E8
__P_Chaos_Spawn_Barracks__L010xFFE647D5
__P_Chaos_Spawn_Barracks__R010xFF5EC9AF
____P_Chaos_Spawn_Barracks__C010xFF707D61
ChaosShop010xFF3A98D9
chaosShop010xFFA6170E
HQ_T10xFFF97DB5
HQ_T20xFFF02C0F
OrderShop010xFF8C490C
orderShop010xFF10C6DB
Namemap
Barracks_T1_C11, 11, 12
Barracks_T1_L11, 10, 11
Barracks_T1_R11, 10, 11
Barracks_T2_C11, 11, 12
Barracks_T2_L11, 10, 11
Barracks_T2_R11, 10, 11
__P_Order_Spawn_Barracks__C011
ChaosShop0112
chaosShop011, 8, 10, 11
HQ_T11, 10, 11, 12
HQ_T21, 10, 11, 12
OrderShop0112
orderShop011, 8, 11

The Barracks names above belong to inhibitors, whatever the name says. The minions a side sends out come from spawn points of their own, which are among the objects a map holds.

A client puts a minion on the field for a SpawnFromBarracks naming a spawn point, and creates nothing for one naming an inhibitor such as Barracks_T1_C1.

A server MUST name each object a map holds by the identifier its name gives.

CreateTurret gives a net id to a turret the map already holds, matched by name. Given to a turret that already has one, it gives it a second, and both name it.

What a client holds

A client holds an object from the message that creates it until the message, or the end of its life, that removes it. Creating messages are listed in Units. What a map holds, a client holds from the moment it loads the map.

Several creating messages can arrive inside the EnterSight that brings a unit into view.

Leaving a client’s sight removes nothing: LeaveSight and LeaveTeamSight hide an object, and it is held as before.

LeaveLocalSight hides an object too, and it is held as before.

In 4.1–4.19

RegionRemoved for a region a client does not hold does nothing.

In 4.1–4.19

How each kind leaves a client’s world:

KindRemovedIts death
Championby ChampionRemoved, at oncekills it; it is held, and comes back
Minion, monster, petby the client, once it has been dead for its death time, 4 seconds unless its character says otherwise; a new SpawnPet for an owner removes that owner’s pet before itstarts that wait; a death naming no killer does nothing
Turretby the client, 1.2 seconds after its death, or after the time its SpawnTurret gives; a lane turret is held where VersionSync’s features keep destroyed turrets (turretsPersist)kills it
Inhibitor, nexusneverBuildingDied plays its death; it is held, and an inhibitor comes back
Missileby DestroyMissile, by its flight ending, or once its caster is removed
Particleby KillParticle, naming it in its body, or once its effect ends
Followeronce the unit it follows is removed
Markeronly by a soft reconnect
Regionby RegionRemoved, once its lifetime runs out (a lifetime of 0 never does), or once the unit it follows is removed

In 4.1–4.19

A client fails on a RegionMoved naming a region it does not hold, one whose lifetime has run out included, and a server MUST NOT send one.

A soft reconnect

SoftReconnect rebuilds a client’s world without a new connection, in two halves. The first marks every unit and every object kept until a checkpoint, inhibitors aside. A create message for a marked net id replaces the marked object rather than keeping the id on it. The second removes every object still marked. In between, a server sends again each object the client is to keep. Each stage either marks or removes.

In 4.1–4.17

The stage of SoftReconnect that marks is 0.

In 4.18–4.20

The stage of SoftReconnect that marks is 1.

Messages about objects a client does not hold

A message whose header names a net id the client does not hold, or whose body names one it needs, does nothing, and the client answers nothing for it. Creating messages are the exception, and so are these:

  • CreateFollower does nothing where the unit it follows is not held.
  • A Replication batch skips the units a client does not hold, and goes unanswered (see Ordering).
  • SoundPlayed naming an owner the client does not hold plays the sound with no place.

SpawnPet takes the net id in its header for the new pet, but does nothing where the owner its body names is not held.

A WaypointGroup or WaypointGroupAtSpeed path for a unit not yet held is applied once an object takes that net id, and its WaypointAck is sent as usual. A server SHOULD send the creating message first.

EnterSight and EnterLocalSight act on the messages they carry whether or not the client holds the unit they name.

Nothing else is held back for later: a message that arrives before the message creating what it names is lost. Ordering says what that requires of a server.

A message naming its sender

A server MUST set any field naming the sender from the connection the message arrived on, and MUST NOT copy the value the message carried; otherwise one player can send messages every other client attributes to another.

Name hashes

Some things a message names are known to a client by name: a spell, an effect a unit carries, a particle, and a place on a unit that particles hang from. A message names one of these by a number worked out from its name.

The number is the ELF hash of the name with its capital letters lowered:

number = 0
for each byte b of the name, with A to Z made a to z:
    number = (number << 4) + b
    high = number & 0xF0000000
    if high != 0:
        number = number ^ (high >> 24)
    number = number & ~high

Every step is worked in 32 bits. Only A to Z change, so SummonerFlash and summonerflash give one number. A particle’s name includes its extension, so the number comes from global_ss_flash.troy and not from global_ss_flash. The nine bytes 123456789 give 0x0678AEE9.

Every byte other than A to Z is taken as it is.

NameNumber
SummonerFlash0x06496EA8
RegenerationPotion0x0E75DC7E
EzrealMysticShotMissile0x05FE9CE5
global_ss_flash.troy0x0058E369
L_HAND0x0725E844

A server MUST name each such thing by the number its name gives.