feces uses several structured types to represent replication data. Understanding these types helps when building custom networking layers or extending feces behavior. All types below are exported fromDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/NeonD00m/feces/llms.txt
Use this file to discover all available pages before exploring further.
feces/types.luau and referenced throughout the library — you will encounter them when calling delta, combine, apply, and full.
TestPlayer
Player instance; in non-Roblox or test environments a plain string is accepted instead. TestPlayer is the key type in Changes, Deletes, and the return value of combine.
LocalEntity
Entity (a numeric ID) that lives in the local world — whichever side (server or client) created it. LocalEntity values are world-specific and are never sent directly over the network; they are always translated to a LookupEntity first.
LookupEntity
Entity used as a stable replication index. The same lookup ID refers to the conceptually same entity across both the server and client worlds, making it safe to include in network packets. LookupEntity values are stored in Group.lookups and Group.refs, and appear as keys in Applyable, Changes, and Deletes.
PlayerObject
feces.replicated component. It controls which players receive replication data for a given entity. feces supports Roblox Player instances as well as plain strings for non-Roblox environments via the TestPlayer alias.
A single player (or string identifier), or
nil for public replication. Only that player receives updates for this entity; nil means all players.An array of players. Each listed player receives updates for this entity.
A filter function. Called once per connected player; returns
true if that player should receive updates.Group
Group represents an isolated lookup namespace used to scope replication. The feces instance itself acts as the default group; additional groups are created with feces.reserve().
A human-readable debug string identifying where this group was created (e.g.
"script:23 reserve()"). Emitted in warnings when the group’s size is exceeded.The maximum number of entities this group can hold. feces emits a warning if more entities than
size are assigned to the group. Use this to bound how many bits are needed to serialize a lookup ID on the wire.Maps local entity IDs (in
feces.world) to their stable lookup IDs. Use this table for a non-allocating lookup check; call feces:lookup(entity, group) if you need to allocate on miss.Maps stable lookup IDs back to local entity IDs. Use this table for a non-allocating ref check; call
feces:ref(lookupId, group) if you need to allocate on miss.Changes
feces:delta(). Organizes pending component mutations by component, then by player (TestPlayer), and finally by the type of change. Pass a Changes object to feces.combine() to produce per-player Applyable packets.
Top-level key is the jecs component entity ID.
none vs remove: none means world:set(entity, component, nil) was called — the component still exists on the entity as a tag with no value. remove means world:remove(entity, component) was called — the component is fully detached from the entity. These produce different mutations when applied on the receiving end.Deletes
Changes by feces:delta(). Maps each TestPlayer to an array of lookup IDs for entities that were deleted or had their replicated tag removed since the last delta() call. Pass a Deletes object (optionally) to feces.combine() alongside Changes.
Array of lookup IDs that should be deleted in the receiving player’s local world. These become entries in
Applyable.__d after combine() processes them.Applyable
Applyable is both the output of feces.combine() and feces:full() and the input of feces:apply(). Serialize this table and send it to each client; on the client, pass the deserialized table to feces:apply().
A component entity ID. Each component that changed maps to a sub-table of affected entities.
The special deletion key. Contains an array of lookup IDs for entities that should be deleted in the receiving world.
feces:apply() detects this key and calls world:delete() for each referenced entity.types.luau:
Applyable is the universal wire format in feces. feces.combine(changes, deletes) and feces:full() both produce an Applyable (one per player for combine, one global snapshot for full). feces:apply(delta) consumes an Applyable. This means the same serialization/deserialization path covers both delta updates and full-state syncs (e.g. for newly joined players).ChangeType
Applyable or Storages represents. The two defined values are None = 0x1 and Remove = 0x2, both exported from types.luau. When action is absent (nil), the entry is a plain value set.
PendingDeletes
delta() calls. Stored at feces._deleted. When delta() runs, entries are drained from PendingDeletes and translated into the Deletes return value.
Storages
delta() calls. Each component gets a sub-table keyed by local entity ID. When delta() is called, feces drains Storages, translates local IDs to lookup IDs, and builds Changes.
Lib
Creates and returns a new
Feces instance that observes world for changes.Translates a
Changes + Deletes pair into a map of per-player Applyable packets, keyed by TestPlayer.Creates a new
Group with an isolated lookup namespace of the given size. The optional second argument enables debug.info origin recording.Feces
feces.new(). It extends both Lib (static helpers) and Group (default lookup namespace), and adds all instance methods. See the feces instance reference for full documentation of each method.