Skip to main content

Documentation 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.

While feces is primarily designed for server-to-client replication, it can be used in the reverse direction. This requires careful permission checking on the server to prevent clients from replicating data they shouldn’t be able to modify.
This is not a recommended use of feces. It is documented here for completeness, for developers who want to minimize the number of replication libraries in their project or reduce manual replication logic. If you do use this pattern, the permission checks below are essential — never trust raw client packets without verification.

Approach 1: Per-Player Entity Ownership

In this approach, each player gets their own dedicated entity (or set of entities) for every component they are allowed to replicate to the server. The ownership relationship is stored using a jecs pair: pair(replicated, replicated).

Server Setup

On the server, when you create an entity that a specific player owns, record the owning player by setting pair(replicated, replicated) to their Player instance:
-- Server: grant a player ownership of an entity
world:set(entity, jecs.pair(replicated, replicated), sendingPlayer)

Server Verification

When the server receives a packet from a client, verify that the entity in the packet actually belongs to the sending player before applying any changes:
-- Server: validate a packet from sendingPlayer
remote.OnServerEvent:Connect(function(sendingPlayer, packet)
    for entity, _ in packet do
        local permission = world:get(entity, jecs.pair(replicated, replicated)) == sendingPlayer
        if not permission then
            -- Reject the packet — the client is trying to replicate
            -- an entity it does not own.
            return
        end
    end

    -- Permission confirmed — safe to apply
    feces:apply(packet)
end)
This approach is straightforward: one ownership record per entity, one check per entity in the packet.

Approach 2: Component-Level Permission

For finer-grained control, you can grant a player permission to replicate a specific component on an entity rather than the entire entity. This uses pair(replicated, someComponent) with the player as the value.

Server Setup

On the server, grant permission for a player to replicate a particular component on a given entity:
-- Server: allow sendingPlayer to replicate the Health component on entity
world:set(entity, pair(replicated, someComponent), sendingPlayer)

Server Verification

When receiving a packet, filter incoming data component-by-component and verify the permission for each:
-- Server: validate per-component permissions
remote.OnServerEvent:Connect(function(sendingPlayer, packet)
    for component, entities in packet do
        for entity, _ in entities do
            local permission = world:get(entity, pair(replicated, someComponent)) == sendingPlayer
            if not permission then
                -- The client is not allowed to replicate this component
                -- on this entity — skip or reject the packet.
                return
            end
        end
    end

    -- All permissions confirmed — safe to apply
    feces:apply(packet)
end)
This approach is more granular: a player may own the Health component on their character entity but not the Position component, for example.

Client-Side Sending

The client-side send implementation for reverse replication is currently a work in progress in the feces source. The permission verification patterns above are stable, but the client-side helper code for packaging and sending world state to the server has not been finalized. Check the feces repository for updates.
In the meantime, you can replicate from the client to the server manually by calling feces:delta() on the client feces instance and firing the resulting packet to the server through a RemoteEvent, where the server performs the permission checks described above before calling feces:apply().

Choosing an Approach

Per-entity ownership

Simpler to set up. Best when each player controls entire entities (e.g., a personal character entity with all components owned by that player).

Per-component permission

More granular. Best when players should only be able to update specific components on shared entities (e.g., voting on a shared entity, or updating only their own health on a team entity).

Build docs developers (and LLMs) love