Security News
npm Updates Search Experience with New Objective Sorting Options
npm has a revamped search experience with new, more transparent sorting options—Relevance, Downloads, Dependents, and Publish Date.
@colyseus/schema
Advanced tools
WORK-IN-PROGRESS EXPERIMENT OF A NEW SERIALIZATION ALGORITHM FOR COLYSEUS
Initial thoghts/assumptions:
Practical Colyseus issues this should solve:
As Colyseus is written in TypeScript, the schema is defined as type annotations inside the state class. Additional server logic may be added to that class, but client-side generated (not implemented) files will consider only the schema itself.
import { DataChange, Sync, sync } from '@colyseus/schema';
export class Player extends Sync {
@sync("string")
name: string;
@sync("number")
x: number;
@sync("number")
y: number;
}
export class State extends Sync {
@sync('string')
fieldString: string;
@sync('number') // varint
fieldNumber: number;
@sync(Player)
player: Player;
@sync([ Player ])
arrayOfPlayers: Player[];
@sync({ map: Player })
mapOfPlayers: { [id: string]: Player };
}
See example/State.ts.
Type | Description | Limitation |
---|---|---|
string | utf8 strings | maximum byte size of 4294967295 |
number | auto-detects int or float type. (extra byte on output) | 0 to 18446744073709551615 |
int8 | signed 8-bit integer | -128 to 127 |
uint8 | unsigned 8-bit integer | 0 to 255 |
int16 | signed 16-bit integer | -32768 to 32767 |
uint16 | unsigned 16-bit integer | 0 to 65535 |
int32 | signed 32-bit integer | -2147483648 to 2147483647 |
uint32 | unsigned 32-bit integer | 0 to 4294967295 |
int64 | signed 64-bit integer | -9223372036854775808 to 9223372036854775807 |
uint64 | unsigned 64-bit integer | 0 to 18446744073709551615 |
Declaration:
@sync("string") name: string;
@sync("number") level: number;
@sync(Player) player: Player;
@sync([ Player ]) arrayOfPlayers: Player[];
@sync([ "number" ]) arrayOfNumbers: number[];
@sync([ "string" ]) arrayOfStrings: string[];
@sync({ map: Player }) mapOfPlayers: {[id: string]: Player};
Sync
types.@colyseus/schema
encodes only field values in the specified order.
2
extra bytes for each index change. Example: If you have an array of 20 items, and remove the first item (through shift()
) this means 38
extra bytes to be serialized.2
extra bytes per key move.TODO: describe how changes will arrive on array and map types
import { DataChange } from "@colyseus/schema";
import { State } from "./YourStateDefinition";
const decodedState = new State();
decodedState.onChange = function(changes: DataChange[]) {
assert.equal(changes.length, 1);
assert.equal(changes[0].field, "fieldNumber");
assert.equal(changes[0].value, 50);
assert.equal(changes[0].previousValue, undefined);
}
decodedState.decode(incomingData);
THIS HAS NOT BEEN IMPLEMENTED
Decoders for each target language are located at /decoders/
. Usage should be as simple as dropping the decoder along with the schema files in your project, since they have no external dependencies.
# TypeScript
statefy ./schemas/State.ts --output ./ts-project/State.ts
# LUA/Defold
statefy ./schemas/State.ts --output ./lua-project/State.lua
# C/C++
statefy ./schemas/State.ts --output ./cpp-project/State.c
# C#/Unity
statefy ./schemas/State.ts --output ./unity-project/State.cs
# Haxe
statefy ./schemas/State.ts --output ./haxe-project/State.hx
This is the ideal scenario that should be possible to achieve.
class MyRoom extends Room<State> {
onInit() {
this.setState(new State());
}
onPatch (client: Client, state: State) {
const player = state.players[client.sessionId];
// filter enemies closer to current player
state.enemies = state.enemies.filter(enemy =>
distance(enemy.x, enemy.y, player.x, player.y) < 50);
return state;
}
}
class Room<T> {
// ...
public onPatch?(client: Client, state: T);
// ...
broadcastPatch() {
if (this.onPatch) {
for (let i=0; i<this.clients.length; i++) {
const client = this.clients[i];
const filteredState = this.onPatch(client, this.state.clone());
send(client, filteredState.encode());
}
} else {
this.broadcast(this.state.encode());
}
}
}
Scenario | @colyseus/schema | msgpack + fossil-delta |
---|---|---|
Initial state size (100 entities) | 2671 | 3283 |
Updating x/y of 1 entity after initial state | 9 | 26 |
Updating x/y of 50 entities after initial state | 342 | 684 |
Updating x/y of 100 entities after initial state | 668 | 1529 |
MIT
FAQs
Binary state serializer with delta encoding for games
We found that @colyseus/schema demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
npm has a revamped search experience with new, more transparent sorting options—Relevance, Downloads, Dependents, and Publish Date.
Security News
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.