Protocol

    The Javelin protocol is a collection of functions used to build compact messages that can be handled either by your application directly, or by helpful utilities like MessageProducer or MessageHandler.

    Messages#

    The protcol is has a single message type with multiple parts. A message may contain the following information:

    • current tick number
    • component model (excluded by default)
    • attached components
    • updated components (full)
    • patched components (deltas)
    • detached components
    • destroyed entities

    Building Messages#

    Messages are created using createMessage:

    import { createMessage } from "@javelin/net"
    
    const message = createMessage()
    

    They are operated on via functions called message writers that correspond to various ECS instructions, like attach, update and destroy. These functions push the data of the operation into a temporary buffer that is read when the message is ultimately encoded. You may accumulate as many operations as you'd like on a message:

    import { component } from "@javelin/ecs"
    import { attach, update } from "@javelin/net"
    import { Body } from "./components"
    
    attach(message, 1, [component(Player)])
    update(message, 99, [updatedBody])
    destroy(message, 2)
    

    A message can be serialized into an ArrayBuffer using encode. Messages are deserialized with decodeMessage, which executes callbacks for each operation encoded in the message.

    import { encode } from "@javelin/net"
    
    const encoded = encode(message)
    channel.send(encoded)
    
    // ... somewhere on the client:
    import { decodeMessage } from "@javelin/net"
    
    decodeMessage(encoded, {
      onSpawn(e, components) {
        world.attach(e, components)
      },
    })
    

    Once you're done with a message, it can be reset and re-used between ticks:

    import { reset } from "@javelin/net"
    
    reset(message)
    

    Message Writers#

    attach(message: Message, entity: Entity, components: Component[]): void#

    Write an attach operation for an entity and one or more components.

    update(message: Message, entity: Entity, components: Component[]): void#

    Write an update operation for an entity and one or more components.

    patch(message: Message, entity: Entity, changes: InstanceOfSchema<typeof ChangeSet>): void#

    Write the changes stored in a ChangeSet for an entity.

    const sysPatchBodies = () =>
      players((entity, [body, changes]) => {
        const message = getEntityMessage(entity)
        patch(message, entity, changes)
      })
    

    detach(message: Message, entity: Entity, components: Component[]): void#

    Write a detach operation for an entity and one or more components.

    destroy(message: Message, entity: Entity): void#

    Write a destroy operation for an entity.