3.0.39 • Published 5 months ago

@colyseus/schema v3.0.39

Weekly downloads
1,755
License
MIT
Repository
github
Last release
5 months ago

Features

  • Incremental State Synchronization: Send only the properties that have changed.
  • Trigger Callbacks at Decoding: Bring your own callback system at decoding, or use the built-in one.
  • Instance Reference Tracking: Share references of the same instance across the state.
  • State Views: Filter properties that should be sent only to specific clients.
  • Reflection: Encode/Decode schema definitions.
  • Schema Generation: Generate client-side schema files for strictly typed languages.
  • Type Safety: Strictly typed schema definitions.
  • Multiple Language Support: Decoders available for multiple languages (C#, Lua, Haxe).

Schema definition

@colyseus/schema uses type annotations to define types of synchronized properties.

import { Schema, type, ArraySchema, MapSchema } from '@colyseus/schema';

export class Player extends Schema {
  @type("string") name: string;
  @type("number") x: number;
  @type("number") y: number;
}

export class MyState extends Schema {
  @type('string') fieldString: string;
  @type('number') fieldNumber: number;
  @type(Player) player: Player;
  @type([ Player ]) arrayOfPlayers: ArraySchema<Player>;
  @type({ map: Player }) mapOfPlayers: MapSchema<Player>;
}

Supported types

Primitive Types

TypeDescriptionLimitation
stringutf8 stringsmaximum byte size of 4294967295
numberauto-detects int or float type. (extra byte on output)0 to 18446744073709551615
booleantrue or false0 or 1
int8signed 8-bit integer-128 to 127
uint8unsigned 8-bit integer0 to 255
int16signed 16-bit integer-32768 to 32767
uint16unsigned 16-bit integer0 to 65535
int32signed 32-bit integer-2147483648 to 2147483647
uint32unsigned 32-bit integer0 to 4294967295
int64signed 64-bit integer-9223372036854775808 to 9223372036854775807
uint64unsigned 64-bit integer0 to 18446744073709551615
float32single-precision floating-point number-3.40282347e+38 to 3.40282347e+38
float64double-precision floating-point number-1.7976931348623157e+308 to 1.7976931348623157e+308

Declaration:

Primitive types (string, number, boolean, etc)

@type("string")
name: string;

@type("int32")
name: number;

Child Schema structures

@type(Player)
player: Player;

Array of Schema structure

@type([ Player ])
arrayOfPlayers: ArraySchema<Player>;

Array of a primitive type

You can't mix types inside arrays.

@type([ "number" ])
arrayOfNumbers: ArraySchema<number>;

@type([ "string" ])
arrayOfStrings: ArraySchema<string>;

Map of Schema structure

@type({ map: Player })
mapOfPlayers: MapSchema<Player>;

Map of a primitive type

You can't mix primitive types inside maps.

@type({ map: "number" })
mapOfNumbers: MapSchema<number>;

@type({ map: "string" })
mapOfStrings: MapSchema<string>;

Reflection

The Schema definitions can encode itself through Reflection. You can have the definition implementation in the server-side, and just send the encoded reflection to the client-side, for example:

import { Schema, type, Reflection } from "@colyseus/schema";

class MyState extends Schema {
  @type("string") currentTurn: string;
  // ... more definitions
}

// send `encodedStateSchema` across the network
const encodedStateSchema = Reflection.encode(new MyState());

// instantiate `MyState` in the client-side, without having its definition:
const myState = Reflection.decode(encodedStateSchema);

StateView / @view()

You can use @view() to filter properties that should be sent only to StateView's that have access to it.

import { Schema, type, view } from "@colyseus/schema";

class Player extends Schema {
  @view() @type("string") secret: string;
  @type("string") notSecret: string;
}

class MyState extends Schema {
  @type({ map: Player }) players = new MapSchema<Player>();
}

Using the StateView

const view = new StateView();
view.add(player);

Encoder

There are 3 major features of the Encoder class:

  • Encoding the full state
  • Encoding the state changes
  • Encoding state with filters (properties using @view() tag)
import { Encoder } from "@colyseus/schema";

const state = new MyState();
const encoder = new Encoder(state);

New clients must receive the full state on their first connection:

const fullEncode = encoder.encodeAll();
// ... send "fullEncode" to client and decode it

Further state changes must be sent in order:

const changesBuffer = encoder.encode();
// ... send "changesBuffer" to client and decode it

Encoding with views

When using @view() and StateView's, a single "full encode" must be used for multiple views. Each view also must add its own changes.

// shared buffer iterator
const it = { offset: 0 };

// shared full encode
encoder.encodeAll(it);
const sharedOffset = it.offset;

// view 1
const fullEncode1 = encoder.encodeAllView(view1, sharedOffset, it);
// ... send "fullEncode1" to client1 and decode it

// view 2
const fullEncode2 = encoder.encodeAllView(view2, sharedOffset, it);
// ... send "fullEncode" to client2 and decode it

Encoding changes per views:

// shared buffer iterator
const it = { offset: 0 };

// shared changes encode
encoder.encode(it);
const sharedOffset = it.offset;

// view 1
const view1Encoded = this.encoder.encodeView(view1, sharedOffset, it);
// ... send "view1Encoded" to client1 and decode it

// view 2
const view2Encoded = this.encoder.encodeView(view2, sharedOffset, it);
// ... send "view2Encoded" to client2 and decode it

// discard all changes after encoding is done.
encoder.discardChanges();

Decoder

The Decoder class is used to decode the binary data received from the server.

import { Decoder } from "@colyseus/schema";

const state = new MyState();
const decoder = new Decoder(state);
decoder.decode(encodedBytes);

Backwards/forwards compatibility

Backwards/forwards compatibility is possible by declaring new fields at the end of existing structures, and earlier declarations to not be removed, but be marked @deprecated() when needed.

This is particularly useful for native-compiled targets, such as C#, C++, Haxe, etc - where the client-side can potentially not have the most up-to-date version of the schema definitions.

Limitations and best practices

  • Each Schema structure can hold up to 64 fields. If you need more fields, use nested structures.
  • NaN or null numbers are encoded as 0
  • null strings are encoded as ""
  • Infinity numbers are encoded as Number.MAX_SAFE_INTEGER
  • Multi-dimensional arrays are not supported.
  • Items inside Arrays and Maps must be all instance of the same type.
  • @colyseus/schema encodes only field values in the specified order.
    • Both encoder (server) and decoder (client) must have same schema definition.
    • The order of the fields must be the same.

Generating client-side schema files (for strictly typed languages)

If you're using JavaScript or LUA, there's no need to bother about this. Interpreted programming languages are able to re-build the Schema locally through the use of Reflection.

You can generate the client-side schema files based on the TypeScript schema definitions automatically.

# C#/Unity
schema-codegen ./schemas/State.ts --output ./unity-project/ --csharp

# C/C++
schema-codegen ./schemas/State.ts --output ./cpp-project/ --cpp

# Haxe
schema-codegen ./schemas/State.ts --output ./haxe-project/ --haxe

Benchmarks:

Scenario@colyseus/schemamsgpack + fossil-delta
Initial state size (100 entities)26713283
Updating x/y of 1 entity after initial state926
Updating x/y of 50 entities after initial state342684
Updating x/y of 100 entities after initial state6681529

Decoder implementation in other languages

Each Colyseus SDK has its own decoder implementation of the @colyseus/schema protocol:

Why

Initial thoughts/assumptions, for Colyseus:

  • little to no bottleneck for detecting state changes.
  • have a schema definition on both the server and the client
  • better experience on statically-typed languages (C#, C++)
  • mutations should be cheap.

Practical Colyseus issues this should solve:

  • Avoid decoding large objects that haven't been patched
  • Allow to send different patches for each client
  • Better developer experience on statically-typed languages

Inspiration:

License

MIT

3.0.0-alpha.50

8 months ago

3.0.4

8 months ago

3.0.3

8 months ago

3.0.2

8 months ago

3.0.1

8 months ago

3.0.8

8 months ago

3.0.7

8 months ago

3.0.6

8 months ago

3.0.5

8 months ago

3.0.0

8 months ago

3.0.0-alpha.36

11 months ago

3.0.0-alpha.35

11 months ago

3.0.0-alpha.38

11 months ago

3.0.0-alpha.37

11 months ago

3.0.0-alpha.39

10 months ago

3.0.9

8 months ago

3.0.0-alpha.47

8 months ago

3.0.0-alpha.49

8 months ago

3.0.0-alpha.48

8 months ago

3.0.0-alpha.41

9 months ago

3.0.0-alpha.40

9 months ago

3.0.0-alpha.42

9 months ago

3.0.0-alpha.45

8 months ago

3.0.0-alpha.44

8 months ago

2.0.37

6 months ago

3.0.12

8 months ago

3.0.13

8 months ago

3.0.10

8 months ago

3.0.11

8 months ago

3.0.16

8 months ago

3.0.17

8 months ago

3.0.14

8 months ago

3.0.15

8 months ago

3.0.23

7 months ago

3.0.24

7 months ago

3.0.21

7 months ago

3.0.22

7 months ago

3.0.27

7 months ago

3.0.28

7 months ago

3.0.25

7 months ago

3.0.26

7 months ago

3.0.20

7 months ago

3.0.18

8 months ago

3.0.19

7 months ago

3.0.34

6 months ago

3.0.35

6 months ago

3.0.32

6 months ago

3.0.33

6 months ago

3.0.38

5 months ago

3.0.39

5 months ago

3.0.36

6 months ago

3.0.37

5 months ago

3.0.30

7 months ago

3.0.31

7 months ago

3.0.29

7 months ago

2.0.36

12 months ago

3.0.0-alpha.32

1 year ago

3.0.0-alpha.34

1 year ago

3.0.0-alpha.33

1 year ago

3.0.0-alpha.14

1 year ago

3.0.0-alpha.13

1 year ago

3.0.0-alpha.16

1 year ago

3.0.0-alpha.15

1 year ago

3.0.0-alpha.18

1 year ago

3.0.0-alpha.17

1 year ago

3.0.0-alpha.19

1 year ago

3.0.0-alpha.10

1 year ago

3.0.0-alpha.12

1 year ago

3.0.0-alpha.11

1 year ago

3.0.0-alpha.25

1 year ago

3.0.0-alpha.24

1 year ago

3.0.0-alpha.27

1 year ago

3.0.0-alpha.26

1 year ago

3.0.0-alpha.29

1 year ago

3.0.0-alpha.28

1 year ago

3.0.0-alpha.23

1 year ago

3.0.0-alpha.22

1 year ago

3.0.0-alpha.30

1 year ago

3.0.0-alpha.31

1 year ago

3.0.0-alpha.7

1 year ago

3.0.0-alpha.6

1 year ago

3.0.0-alpha.9

1 year ago

3.0.0-alpha.8

1 year ago

2.0.35

1 year ago

3.0.0-alpha.1

1 year ago

3.0.0-alpha.0

1 year ago

2.0.33

1 year ago

3.0.0-alpha.3

1 year ago

2.0.34

1 year ago

3.0.0-alpha.2

1 year ago

3.0.0-alpha.5

1 year ago

3.0.0-alpha.4

1 year ago

2.0.32

1 year ago

2.0.31

1 year ago

2.0.30

2 years ago

2.0.28

2 years ago

2.0.29

2 years ago

2.0.27

2 years ago

2.0.26

2 years ago

2.0.15

2 years ago

2.0.16

2 years ago

2.0.13

2 years ago

2.0.14

2 years ago

2.0.11

2 years ago

2.0.12

2 years ago

2.0.19

2 years ago

2.0.17

2 years ago

2.0.18

2 years ago

2.0.24

2 years ago

2.0.25

2 years ago

2.0.22

2 years ago

2.0.23

2 years ago

2.0.20

2 years ago

2.0.21

2 years ago

2.0.10

2 years ago

2.0.5

2 years ago

2.0.7

2 years ago

2.0.6

2 years ago

2.0.9

2 years ago

2.0.8

2 years ago

1.0.46

2 years ago

1.0.44

3 years ago

1.0.43

3 years ago

1.0.42

3 years ago

1.0.45

3 years ago

1.0.41

3 years ago

1.0.40

3 years ago

1.0.39

3 years ago

1.0.38

3 years ago

1.0.36

3 years ago

1.0.35

3 years ago

2.0.3

4 years ago

2.0.2

4 years ago

2.0.4

4 years ago

1.0.33

4 years ago

1.0.32

4 years ago

1.0.34

4 years ago

2.0.0

4 years ago

1.0.29

4 years ago

1.0.31

4 years ago

1.0.30

4 years ago

1.0.28

4 years ago

1.0.27

4 years ago

1.0.26

4 years ago

1.0.25

4 years ago

1.0.24

4 years ago

1.0.23

4 years ago

1.0.22

5 years ago

1.0.19

5 years ago

1.0.18

5 years ago

1.0.17

5 years ago

1.0.21

5 years ago

1.0.20

5 years ago

1.0.16

5 years ago

1.1.0-alpha.2

5 years ago

1.1.0-alpha.3

5 years ago

1.0.15

5 years ago

1.0.14

5 years ago

1.1.0-alpha.1

5 years ago

1.1.0-alpha.0

5 years ago

1.0.13

5 years ago

1.0.12

5 years ago

1.0.11

5 years ago

1.0.10

5 years ago

1.0.9

5 years ago

1.0.8

5 years ago

1.0.7

5 years ago

1.0.6

5 years ago

1.0.5

5 years ago

1.0.4

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago

1.0.0-alpha.62

5 years ago

1.0.0-alpha.61

5 years ago

1.0.0-alpha.60

5 years ago

1.0.0-alpha.59

5 years ago

1.0.0-alpha.58

5 years ago

1.0.0-alpha.56

5 years ago

1.0.0-alpha.55

5 years ago

1.0.0-alpha.54

5 years ago

1.0.0-alpha.53

5 years ago

1.0.0-alpha.52

5 years ago

1.0.0-alpha.51

5 years ago

1.0.0-alpha.50

5 years ago

1.0.0-alpha.49

5 years ago

1.0.0-alpha.48

5 years ago

1.0.0-alpha.47

5 years ago

1.0.0-alpha.45

5 years ago

1.0.0-alpha.46

5 years ago

1.0.0-alpha.44

5 years ago

1.0.0-alpha.43

5 years ago

1.0.0-alpha.42

5 years ago

1.0.0-alpha.41

5 years ago

1.0.0-alpha.40

5 years ago

1.0.0-alpha.39

5 years ago

1.0.0-alpha.38

5 years ago

1.0.0-alpha.37

5 years ago

1.0.0-alpha.36

5 years ago

1.0.0-alpha.35

5 years ago

1.0.0-alpha.33

5 years ago

1.0.0-alpha.32

5 years ago

1.0.0-alpha.31

5 years ago

1.0.0-alpha.30

5 years ago

1.0.0-alpha.29

5 years ago

0.5.41

5 years ago

1.0.0-alpha.28

5 years ago

1.0.0-alpha.27

5 years ago

1.0.0-alpha.26

5 years ago

1.0.0-alpha.25

5 years ago

1.0.0-alpha.24

5 years ago

1.0.0-alpha.21

5 years ago

1.0.0-alpha.23

5 years ago

1.0.0-alpha.20

5 years ago

1.0.0-alpha.19

5 years ago

1.0.0-alpha.18

5 years ago

1.0.0-alpha.17

5 years ago

1.0.0-alpha.16

5 years ago

1.0.0-alpha.15

5 years ago

1.0.0-alpha.14

5 years ago

1.0.0-alpha.12

5 years ago

1.0.0-alpha.13

5 years ago

1.0.0-alpha.9

5 years ago

1.0.0-alpha.10

5 years ago

1.0.0-alpha.7

5 years ago

1.0.0-alpha.6

5 years ago

1.0.0-alpha.5

5 years ago

1.0.0-alpha.4

5 years ago

1.0.0-alpha.3

5 years ago

1.0.0-alpha.2

5 years ago

1.0.0-alpha.1

5 years ago

1.0.0-alpha.0

5 years ago

0.5.40

5 years ago

0.5.39

5 years ago

0.5.38

5 years ago

0.5.37

5 years ago

0.5.36

6 years ago

0.5.35

6 years ago

0.5.34

6 years ago

0.5.33

6 years ago

0.5.32

6 years ago

0.5.31

6 years ago

0.5.30

6 years ago

0.5.29

6 years ago

0.5.28

6 years ago

0.5.27

6 years ago

0.5.26

6 years ago

0.5.25

6 years ago

0.5.24-alpha.0

6 years ago

0.5.24

6 years ago

0.5.23

6 years ago

0.5.22

6 years ago

0.5.21

6 years ago

0.5.20

6 years ago

0.5.19

6 years ago

0.5.18

6 years ago

0.5.17

6 years ago

0.5.16

6 years ago

0.5.15

6 years ago

0.5.14

6 years ago

0.5.13

6 years ago

0.5.12

6 years ago

0.5.11

6 years ago

0.5.10

6 years ago

0.5.9

6 years ago

0.5.8

6 years ago

0.5.7

6 years ago

0.5.6

6 years ago

0.5.5

6 years ago

0.5.4

6 years ago

0.5.3

6 years ago

0.5.2

6 years ago

0.5.1

6 years ago

0.5.0

6 years ago

0.4.61

6 years ago

0.4.60

6 years ago

0.4.59

6 years ago

0.4.58

6 years ago

0.4.57

6 years ago

0.4.56

6 years ago

0.4.55

6 years ago

0.4.54

6 years ago

0.4.53

6 years ago

0.4.52

6 years ago

0.4.51

6 years ago

0.4.50

6 years ago

0.4.49

6 years ago

0.4.48

6 years ago

0.4.47

6 years ago

0.4.46

6 years ago

0.4.45

6 years ago

0.4.44

6 years ago

0.4.43

6 years ago

0.4.42

6 years ago

0.4.41

6 years ago

0.4.40

6 years ago

0.4.39

6 years ago

0.4.38

6 years ago

0.4.37

6 years ago

0.4.36

6 years ago

0.4.35

6 years ago

0.4.35-alpha.0

6 years ago

0.4.34

6 years ago

0.4.33

6 years ago

0.4.32

6 years ago

0.4.31

6 years ago

0.4.30

6 years ago

0.4.29

6 years ago

0.4.28

6 years ago

0.4.27

6 years ago

0.4.26

6 years ago

0.4.25

6 years ago

0.4.25-alpha.2

6 years ago

0.4.25-alpha.1

6 years ago

0.4.25-alpha.0

6 years ago

0.4.24

7 years ago

0.4.23

7 years ago

0.4.22

7 years ago

0.4.21

7 years ago

0.4.20

7 years ago

0.4.19

7 years ago

0.4.18

7 years ago

0.4.17

7 years ago

0.4.16

7 years ago

0.4.15

7 years ago

0.4.14

7 years ago

0.4.13

7 years ago

0.4.12

7 years ago

0.4.11

7 years ago

0.4.10

7 years ago

0.4.9

7 years ago

0.4.8

7 years ago

0.4.7

7 years ago

0.4.6

7 years ago

0.4.5

7 years ago

0.4.4

7 years ago

0.4.3

7 years ago

0.4.2

7 years ago

0.4.1

7 years ago

0.4.0

7 years ago

0.3.13

7 years ago

0.3.12

7 years ago

0.3.11

7 years ago

0.3.10

7 years ago

0.3.9

7 years ago

0.3.8

7 years ago

0.3.7

7 years ago

0.3.6

7 years ago

0.3.5

7 years ago

0.3.4

7 years ago

0.3.3

7 years ago

0.3.2

7 years ago

0.3.1

7 years ago

0.3.0

7 years ago

0.1.8

7 years ago

0.1.7

7 years ago

0.1.6

7 years ago

0.1.5

7 years ago

0.1.4

7 years ago

0.1.3

7 years ago

0.1.2

7 years ago

0.1.1

7 years ago

0.1.0

7 years ago