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.

In 1.0.0.140

No region id stands for no region.

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

A client takes a client id only from 0 to 252, and leaves on any other.

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.

A client acts on that Registered alone and ignores every other, so it pairs no other player’s player id with a client id.

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 create message carries a node beside the object’s net id.

In 1.0.0.140–3.1.0.0

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

Every object a map places carries the identifier its name gives, turrets, navigation points and props among them.

A name holding _Destroyed or _FB gives no identifier.

In 1.0.0.140

MapHolds
1, 2, 6the six Barracks names, HQ_T1, HQ_T2, orderShop01, chaosShop01, spawn points named __P_…
3Barracks_T1_C1, Barracks_T2_C1, HQ_T1, HQ_T2, OrderShop01, ChaosShop01, ____P_Chaos_Spawn_Barracks__C01
4Barracks_T1_L1, Barracks_T1_R1, Barracks_T2_L1, Barracks_T2_R1, HQ_T1, HQ_T2, OrderShop01, ChaosShop01, spawn points named __P_…
8orderShop01, chaosShop01

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.

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

A client removes a region once its lifetime reaches 0, so a region given a lifetime of 0 does not last.

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

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 1.0.0.143–3.1.0.0

The stage of SoftReconnect that marks is 0.

In 1.0.0.143–3.1.0.0

A client reads only the two lowest bits of the stage: a stage with both clear marks, and any other removes.

In 1.0.0.150

ParticlesCreated does not replace a marked object holding its net id: that object stays until the removing stage.

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.

In 1.0.0.130–1.0.0.140

A WaypointGroup or WaypointGroupAtSpeed path for a unit not held is never applied, and a client does not read past its points: it reads the next path from inside the one it skipped, so every later path of that message comes out wrong. The WaypointAck is sent as usual and lists that path. A server MUST send the creating message first, and MUST NOT carry a path for a unit a client does not hold in a message with other paths.

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

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.

A byte from 128 to 255 enters the hash as its value less 256, worked in 32 bits, rather than as itself.

NameNumber
SummonerFlash0x06496EA8
RegenerationPotion0x0E75DC7E
EzrealMysticShotMissile0x05FE9CE5
global_ss_flash.troy0x0058E369
L_HAND0x0725E844

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