Skip to content

Latest commit

 

History

History
122 lines (96 loc) · 3.75 KB

README.md

File metadata and controls

122 lines (96 loc) · 3.75 KB

anchor

What is this?

Anchor is a mod+server that enables co-op on Ship of Harkinian. It's primary functions are loading save state from a remote player when you join their session, and sending flag sets/item gives across all players in a session. This is not multi-world, and it requires that all players have the same randomizer seed loaded, but this is a great example to reference for it and other multiplayer ventures.

How to

You don't technically need this, I'm hosting this on my end. Instead see the associated SoH Build

If you would like to host your own server:

  • Install deno
  • If you don't want to make any code changes, you can run it straight from github with
deno run --allow-all https://raw.githubusercontent.com/garrettjoecox/anchor/main/mod.ts
deno run --allow-all mod.ts
  • In the network tab update your remote IP to point to your server, eg:
-"gRemoteGIIP": "anchor.proxysaw.dev",
+"gRemoteGIIP": "127.0.0.1",

Docker

docker run -p 43385:43385 -v /my/mnt/logs:/logs ghcr.io/garrettjoecox/anchor:latest

Optional environment variables can be set:

  • PORT: configures the server port inside the container; defaults to 43385
  • QUIET: when set, fewer log messages are output; defaults to unset

Packet protocol

This is for anyone wanting to extend the client side of anchor while still using the hosted server

Packets are delimited by a null terminator \0. Clients built prior to December 5th 2023 instead use a newline \n as a delimiter, if you are using one of these clients you will need to use the legacy-newline-terminator branch of this repo.

// Packets that the client will receive from server
interface IncomingPacket {
  type: string;
  roomId: string; // roomId which the client belongs to
  clientId?: number; // clientId whom the packet came from. Server can send packets so not always provided
  quiet?: boolean; // prevent this packet from logging. Any position/location packets should use this
  ...any valid json
}
// Packets the client sends to server
interface OutgoingPacket {
  type: string;
  roomId: string; // roomId which the client belongs to
  targetClientId?: number; // the server will only send this packet to the targetted client ID
  quiet?: boolean; // prevent this packet from logging. Any position/location packets should use this
  ...any valid json
}

All packets sent to server will be forwarded to all clients in the same room with the following exceptions:

  • If the packet contains a targetClientId it will only be forwarded to that one client
  • If the packet is PUSH_SAVE_STATE, it will only be sent to clients who have requested a save state with REQUEST_SAVE_STATE

Upon joining a room a client should register it's data with the UPDATE_CLIENT_DATA packet. The data should be an object with string keys and arbitrary values, for example:

{
  "type": "UPDATE_CLIENT_DATA",
  "roomId": "testRoom",
  "data": {
    "name": "ProxySaw",
    "color": { "r": 0, "g": 255, "b": 0 }
  }
}

Upon any client joining or leaving a room, an ALL_CLIENT_DATA packet is sent to all clients with the remaining client's registered data for example:

{
  "type": "ALL_CLIENT_DATA",
  "roomId": "testRoom",
  "clients": [
    {
      "clientId": 45,
      "name": "ProxySaw",
      "color": { "r": 0, "g": 255, "b": 0 }
    }
  ]
}

To clarify, it is up to the clients to send/parse this data, so this can be anything you might want to store.