Skip to content

Entity data

Unstable: everything in this chapter needs the unstable feature and may change in any release (Stability).

Entity data is what a mod attaches to any entity of the world: the player who owns a placed chest, the nickname of a survivor, the day a gate was built. It works as item data does, for every entity instead of items alone: kinds with ids <mod>:<name>, a value type of the mod’s choosing, values kept per world beside the game’s save, never inside it. The entity_data module reads and writes it.

use enshwick::Entity;
use enshwick::entity_data::Replication;
#[derive(serde::Serialize, serde::Deserialize)]
struct Owner {
player: u64,
}
fn init(load: &mut enshwick::Load<'_>) -> Result<(), enshwick::Off> {
// `<this mod>:owner`, kept on the server alone.
let owners = load.entity_data::<Owner>("owner", Replication::Server)?;
let chest = Entity(4_200);
if owners.get(chest).is_none() {
let _set = owners.set(chest, &Owner { player: 7 });
}
Ok(())
}

load.entity_data::<T>(id, replication) opens a kind during init, on both sides. As for item data, name is the mod’s own kind and mod:name any mod’s: every mod that opens one id shares its values, which is how mods share entity data without depending on each other. One id is either an item kind or an entity kind; opening it as both turns the second mod off. A value is encoded with postcard and takes at most 512 bytes.

ReplicationWho gets the values
Serverthe server alone
Clientsthe server, and every client that runs Enshwick: all values on joining, each change after

A kind is sent once any mod opens it with Clients.

CallDoes
get(entity)The entity’s value, or None. Any thread.
set(entity, &value)Sets it. On the server’s game thread, once the world has loaded.
remove(entity)Removes it. As for set.

set and remove return a SetError: the value does not encode or is too long, the call came off the server’s game thread, the world has not loaded, the entity does not exist, or no load finds the entity again (NotKept).

An entity id lasts one session. Each load of a world numbers its entities anew in the order of the save, so adding or removing one thing moves the ids of everything saved after it. Entity therefore has no serde form, and a mod keeps nothing by entity id in its own files.

The server keeps each value under its entity’s place instead: the template and the position, as the save keeps it, to a sixteen-thousandth of a metre. After the first step of a loaded world, every value finds its entity again by that place. A value whose place names no entity for certain goes aside: its place holds no entity, or two entities of the template share it, such as two chests a mod spawned at one point, even turned apart. A value aside stays in the world’s file, attached to nothing and never matched again, since a later entity may take its place. The log says how many went aside. Nothing is given to another entity on a guess.

Only an entity the save keeps in place can carry a value: a placed prop, an altar, a container, a survivor. A player’s character is not one, so set refuses it with SetError::NotKept; keep player data by PlayerKey.

The server also keeps, with each value, the template its entity had when the value was set. When the game destroys the entity, the server drops its values after that step and tells the clients. When its id names another thing:

  • a read on the server’s game thread finds it out and the value reads as missing;
  • the server drops every such value when the world saves.

An entity the world no longer holds when it saves, gone without a destroy the server saw, has its values set aside.

Reads on other threads answer from what the server keeps, until that next check.

The server keeps item and entity data in one file, mod-data/enshwick/worlds/<key>/attachments.bin, written when the world saves and when the server stops. Removing the mods leaves the world vanilla.

A client and the server number entities apart: the client’s own world gives a replicated entity another id. A sent kind reaches clients under the server’s ids, so a client reads a value by an id the server named, such as one in a message or the item entities of inventory slots.