@colyseus/schema 3.0.0-alpha.9 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -62
- package/bin/schema-debug +94 -0
- package/build/cjs/index.js +2222 -1513
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +2223 -1516
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +2225 -1516
- package/lib/Metadata.d.ts +21 -9
- package/lib/Metadata.js +169 -32
- package/lib/Metadata.js.map +1 -1
- package/lib/Reflection.d.ts +19 -4
- package/lib/Reflection.js +66 -31
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +12 -5
- package/lib/Schema.js +57 -56
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +31 -34
- package/lib/annotations.js +110 -160
- package/lib/annotations.js.map +1 -1
- package/lib/codegen/api.js +1 -2
- package/lib/codegen/api.js.map +1 -1
- package/lib/codegen/languages/cpp.js +1 -2
- package/lib/codegen/languages/cpp.js.map +1 -1
- package/lib/codegen/languages/csharp.js +9 -46
- package/lib/codegen/languages/csharp.js.map +1 -1
- package/lib/codegen/languages/haxe.js +4 -2
- package/lib/codegen/languages/haxe.js.map +1 -1
- package/lib/codegen/languages/java.js +1 -2
- package/lib/codegen/languages/java.js.map +1 -1
- package/lib/codegen/languages/js.js +1 -2
- package/lib/codegen/languages/js.js.map +1 -1
- package/lib/codegen/languages/lua.js +23 -25
- package/lib/codegen/languages/lua.js.map +1 -1
- package/lib/codegen/languages/ts.js +1 -2
- package/lib/codegen/languages/ts.js.map +1 -1
- package/lib/codegen/parser.js +85 -3
- package/lib/codegen/parser.js.map +1 -1
- package/lib/codegen/types.js +6 -3
- package/lib/codegen/types.js.map +1 -1
- package/lib/decoder/DecodeOperation.d.ts +3 -4
- package/lib/decoder/DecodeOperation.js +35 -17
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +5 -6
- package/lib/decoder/Decoder.js +10 -10
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/ReferenceTracker.js +4 -2
- package/lib/decoder/ReferenceTracker.js.map +1 -1
- package/lib/decoder/strategy/RawChanges.js +1 -2
- package/lib/decoder/strategy/RawChanges.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.d.ts +44 -11
- package/lib/decoder/strategy/StateCallbacks.js +74 -64
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +28 -20
- package/lib/encoder/ChangeTree.js +242 -188
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/EncodeOperation.d.ts +3 -6
- package/lib/encoder/EncodeOperation.js +51 -65
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +8 -7
- package/lib/encoder/Encoder.js +128 -79
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.d.ts +22 -0
- package/lib/encoder/Root.js +81 -0
- package/lib/encoder/Root.js.map +1 -0
- package/lib/encoder/StateView.d.ts +7 -7
- package/lib/encoder/StateView.js +72 -74
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/assert.d.ts +7 -6
- package/lib/encoding/assert.js +13 -5
- package/lib/encoding/assert.js.map +1 -1
- package/lib/encoding/decode.d.ts +36 -19
- package/lib/encoding/decode.js +54 -84
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +36 -18
- package/lib/encoding/encode.js +61 -48
- package/lib/encoding/encode.js.map +1 -1
- package/lib/encoding/spec.d.ts +4 -5
- package/lib/encoding/spec.js +1 -2
- package/lib/encoding/spec.js.map +1 -1
- package/lib/index.d.ts +10 -9
- package/lib/index.js +24 -17
- package/lib/index.js.map +1 -1
- package/lib/types/HelperTypes.d.ts +34 -2
- package/lib/types/HelperTypes.js.map +1 -1
- package/lib/types/TypeContext.d.ts +29 -0
- package/lib/types/TypeContext.js +151 -0
- package/lib/types/TypeContext.js.map +1 -0
- package/lib/types/custom/ArraySchema.d.ts +2 -2
- package/lib/types/custom/ArraySchema.js +33 -22
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/CollectionSchema.d.ts +2 -2
- package/lib/types/custom/CollectionSchema.js +1 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.d.ts +18 -16
- package/lib/types/custom/MapSchema.js +12 -4
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/custom/SetSchema.d.ts +2 -2
- package/lib/types/custom/SetSchema.js +1 -0
- package/lib/types/custom/SetSchema.js.map +1 -1
- package/lib/types/registry.d.ts +8 -1
- package/lib/types/registry.js +23 -6
- package/lib/types/registry.js.map +1 -1
- package/lib/types/symbols.d.ts +8 -5
- package/lib/types/symbols.js +9 -6
- package/lib/types/symbols.js.map +1 -1
- package/lib/types/utils.js +1 -2
- package/lib/types/utils.js.map +1 -1
- package/lib/utils.js +9 -7
- package/lib/utils.js.map +1 -1
- package/package.json +19 -18
- package/src/Metadata.ts +190 -42
- package/src/Reflection.ts +76 -38
- package/src/Schema.ts +72 -70
- package/src/annotations.ts +156 -202
- package/src/codegen/languages/csharp.ts +8 -47
- package/src/codegen/languages/haxe.ts +4 -0
- package/src/codegen/languages/lua.ts +19 -27
- package/src/codegen/parser.ts +107 -0
- package/src/codegen/types.ts +1 -0
- package/src/decoder/DecodeOperation.ts +43 -15
- package/src/decoder/Decoder.ts +12 -10
- package/src/decoder/ReferenceTracker.ts +5 -3
- package/src/decoder/strategy/StateCallbacks.ts +152 -81
- package/src/encoder/ChangeTree.ts +282 -209
- package/src/encoder/EncodeOperation.ts +78 -78
- package/src/encoder/Encoder.ts +152 -88
- package/src/encoder/Root.ts +93 -0
- package/src/encoder/StateView.ts +80 -88
- package/src/encoding/assert.ts +17 -8
- package/src/encoding/decode.ts +73 -93
- package/src/encoding/encode.ts +76 -45
- package/src/encoding/spec.ts +3 -5
- package/src/index.ts +12 -20
- package/src/types/HelperTypes.ts +54 -2
- package/src/types/TypeContext.ts +175 -0
- package/src/types/custom/ArraySchema.ts +49 -19
- package/src/types/custom/CollectionSchema.ts +1 -0
- package/src/types/custom/MapSchema.ts +30 -17
- package/src/types/custom/SetSchema.ts +1 -0
- package/src/types/registry.ts +22 -3
- package/src/types/symbols.ts +10 -7
- package/src/utils.ts +7 -3
- package/lib/Decoder.d.ts +0 -16
- package/lib/Decoder.js +0 -182
- package/lib/Decoder.js.map +0 -1
- package/lib/Encoder.d.ts +0 -13
- package/lib/Encoder.js +0 -79
- package/lib/Encoder.js.map +0 -1
- package/lib/changes/ChangeSet.d.ts +0 -12
- package/lib/changes/ChangeSet.js +0 -35
- package/lib/changes/ChangeSet.js.map +0 -1
- package/lib/changes/ChangeTree.d.ts +0 -53
- package/lib/changes/ChangeTree.js +0 -202
- package/lib/changes/ChangeTree.js.map +0 -1
- package/lib/changes/DecodeOperation.d.ts +0 -15
- package/lib/changes/DecodeOperation.js +0 -186
- package/lib/changes/DecodeOperation.js.map +0 -1
- package/lib/changes/EncodeOperation.d.ts +0 -18
- package/lib/changes/EncodeOperation.js +0 -130
- package/lib/changes/EncodeOperation.js.map +0 -1
- package/lib/changes/ReferenceTracker.d.ts +0 -14
- package/lib/changes/ReferenceTracker.js +0 -83
- package/lib/changes/ReferenceTracker.js.map +0 -1
- package/lib/changes/consts.d.ts +0 -14
- package/lib/changes/consts.js +0 -18
- package/lib/changes/consts.js.map +0 -1
- package/lib/decoding/decode.d.ts +0 -48
- package/lib/decoding/decode.js +0 -267
- package/lib/decoding/decode.js.map +0 -1
- package/lib/ecs.d.ts +0 -11
- package/lib/ecs.js +0 -160
- package/lib/ecs.js.map +0 -1
- package/lib/filters/index.d.ts +0 -8
- package/lib/filters/index.js +0 -24
- package/lib/filters/index.js.map +0 -1
- package/lib/spec.d.ts +0 -13
- package/lib/spec.js +0 -42
- package/lib/spec.js.map +0 -1
- package/lib/types/ArraySchema.d.ts +0 -238
- package/lib/types/ArraySchema.js +0 -555
- package/lib/types/ArraySchema.js.map +0 -1
- package/lib/types/CollectionSchema.d.ts +0 -35
- package/lib/types/CollectionSchema.js +0 -150
- package/lib/types/CollectionSchema.js.map +0 -1
- package/lib/types/MapSchema.d.ts +0 -38
- package/lib/types/MapSchema.js +0 -215
- package/lib/types/MapSchema.js.map +0 -1
- package/lib/types/SetSchema.d.ts +0 -32
- package/lib/types/SetSchema.js +0 -162
- package/lib/types/SetSchema.js.map +0 -1
- package/lib/types/typeRegistry.d.ts +0 -5
- package/lib/types/typeRegistry.js +0 -13
- package/lib/types/typeRegistry.js.map +0 -1
- package/lib/usage.d.ts +0 -1
- package/lib/usage.js +0 -22
- package/lib/usage.js.map +0 -1
- package/lib/v3.d.ts +0 -1
- package/lib/v3.js +0 -427
- package/lib/v3.js.map +0 -1
- package/lib/v3_experiment.d.ts +0 -1
- package/lib/v3_experiment.js +0 -407
- package/lib/v3_experiment.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,55 +1,47 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="logo.png?raw=true" />
|
|
2
|
+
<img src="logo.png?raw=true" width="50%" />
|
|
3
3
|
<br>
|
|
4
|
-
<br>
|
|
5
|
-
|
|
6
4
|
<p>
|
|
7
5
|
An incremental binary state serializer with delta encoding for games.<br>
|
|
8
|
-
|
|
6
|
+
Made for <a href="https://github.com/colyseus/colyseus">Colyseus</a>, yet can be used standalone.
|
|
9
7
|
</p>
|
|
10
8
|
</div>
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
# Features
|
|
11
|
+
|
|
12
|
+
- Flexible Schema Definition
|
|
13
|
+
- Optimized Data Encoding
|
|
14
|
+
- Automatic State Synchronization
|
|
15
|
+
- Client-side Change Detection
|
|
16
|
+
- Per-client portions of the state
|
|
17
|
+
- Type Safety
|
|
18
|
+
- *...decoders available for multiple languages (C#, Lua, Haxe)*
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
## Schema definition
|
|
21
|
+
|
|
22
|
+
`@colyseus/schema` uses type annotations to define types of synchronized properties.
|
|
15
23
|
|
|
16
24
|
```typescript
|
|
17
25
|
import { Schema, type, ArraySchema, MapSchema } from '@colyseus/schema';
|
|
18
26
|
|
|
19
27
|
export class Player extends Schema {
|
|
20
|
-
@type("string")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@type("number")
|
|
24
|
-
x: number;
|
|
25
|
-
|
|
26
|
-
@type("number")
|
|
27
|
-
y: number;
|
|
28
|
+
@type("string") name: string;
|
|
29
|
+
@type("number") x: number;
|
|
30
|
+
@type("number") y: number;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
export class
|
|
31
|
-
@type('string')
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@type(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
@type(Player)
|
|
38
|
-
player: Player;
|
|
39
|
-
|
|
40
|
-
@type([ Player ])
|
|
41
|
-
arrayOfPlayers: ArraySchema<Player>;
|
|
42
|
-
|
|
43
|
-
@type({ map: Player })
|
|
44
|
-
mapOfPlayers: MapSchema<Player>;
|
|
33
|
+
export class MyState extends Schema {
|
|
34
|
+
@type('string') fieldString: string;
|
|
35
|
+
@type('number') fieldNumber: number;
|
|
36
|
+
@type(Player) player: Player;
|
|
37
|
+
@type([ Player ]) arrayOfPlayers: ArraySchema<Player>;
|
|
38
|
+
@type({ map: Player }) mapOfPlayers: MapSchema<Player>;
|
|
45
39
|
}
|
|
46
40
|
```
|
|
47
41
|
|
|
48
|
-
See [example](test/Schema.ts).
|
|
49
|
-
|
|
50
42
|
## Supported types
|
|
51
43
|
|
|
52
|
-
|
|
44
|
+
### Primitive Types
|
|
53
45
|
|
|
54
46
|
| Type | Description | Limitation |
|
|
55
47
|
|------|-------------|------------|
|
|
@@ -79,14 +71,14 @@ name: string;
|
|
|
79
71
|
name: number;
|
|
80
72
|
```
|
|
81
73
|
|
|
82
|
-
####
|
|
74
|
+
#### Child `Schema` structures
|
|
83
75
|
|
|
84
76
|
```typescript
|
|
85
77
|
@type(Player)
|
|
86
78
|
player: Player;
|
|
87
79
|
```
|
|
88
80
|
|
|
89
|
-
#### Array of
|
|
81
|
+
#### Array of `Schema` structure
|
|
90
82
|
|
|
91
83
|
```typescript
|
|
92
84
|
@type([ Player ])
|
|
@@ -105,7 +97,7 @@ arrayOfNumbers: ArraySchema<number>;
|
|
|
105
97
|
arrayOfStrings: ArraySchema<string>;
|
|
106
98
|
```
|
|
107
99
|
|
|
108
|
-
#### Map of
|
|
100
|
+
#### Map of `Schema` structure
|
|
109
101
|
|
|
110
102
|
```typescript
|
|
111
103
|
@type({ map: Player })
|
|
@@ -114,7 +106,7 @@ mapOfPlayers: MapSchema<Player>;
|
|
|
114
106
|
|
|
115
107
|
#### Map of a primitive type
|
|
116
108
|
|
|
117
|
-
You can't mix types inside maps.
|
|
109
|
+
You can't mix primitive types inside maps.
|
|
118
110
|
|
|
119
111
|
```typescript
|
|
120
112
|
@type({ map: "number" })
|
|
@@ -124,16 +116,6 @@ mapOfNumbers: MapSchema<number>;
|
|
|
124
116
|
mapOfStrings: MapSchema<string>;
|
|
125
117
|
```
|
|
126
118
|
|
|
127
|
-
### Backwards/forwards compability
|
|
128
|
-
|
|
129
|
-
Backwards/fowards compatibility is possible by declaring new fields at the
|
|
130
|
-
end of existing structures, and earlier declarations to not be removed, but
|
|
131
|
-
be marked `@deprecated()` when needed.
|
|
132
|
-
|
|
133
|
-
This is particularly useful for native-compiled targets, such as C#, C++,
|
|
134
|
-
Haxe, etc - where the client-side can potentially not have the most
|
|
135
|
-
up-to-date version of the schema definitions.
|
|
136
|
-
|
|
137
119
|
### Reflection
|
|
138
120
|
|
|
139
121
|
The Schema definitions can encode itself through `Reflection`. You can have the
|
|
@@ -144,10 +126,8 @@ reflection to the client-side, for example:
|
|
|
144
126
|
import { Schema, type, Reflection } from "@colyseus/schema";
|
|
145
127
|
|
|
146
128
|
class MyState extends Schema {
|
|
147
|
-
@type("string")
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
// more definitions relating to more Schema types.
|
|
129
|
+
@type("string") currentTurn: string;
|
|
130
|
+
// ... more definitions
|
|
151
131
|
}
|
|
152
132
|
|
|
153
133
|
// send `encodedStateSchema` across the network
|
|
@@ -157,22 +137,125 @@ const encodedStateSchema = Reflection.encode(new MyState());
|
|
|
157
137
|
const myState = Reflection.decode(encodedStateSchema);
|
|
158
138
|
```
|
|
159
139
|
|
|
160
|
-
###
|
|
140
|
+
### `StateView` / `@view()`
|
|
161
141
|
|
|
162
|
-
|
|
142
|
+
You can use `@view()` to filter properties that should be sent only to `StateView`'s that have access to it.
|
|
163
143
|
|
|
164
144
|
```typescript
|
|
165
|
-
import { Schema, type,
|
|
145
|
+
import { Schema, type, view } from "@colyseus/schema";
|
|
166
146
|
|
|
167
|
-
|
|
168
|
-
@
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
147
|
+
class Player extends Schema {
|
|
148
|
+
@view() @type("string") secret: string;
|
|
149
|
+
@type("string") notSecret: string;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
class MyState extends Schema {
|
|
153
|
+
@type({ map: Player }) players = new MapSchema<Player>();
|
|
173
154
|
}
|
|
174
155
|
```
|
|
175
156
|
|
|
157
|
+
Using the `StateView`
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
const view = new StateView();
|
|
161
|
+
view.add(player);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Encoder
|
|
165
|
+
|
|
166
|
+
There are 3 major features of the `Encoder` class:
|
|
167
|
+
|
|
168
|
+
- Encoding the full state
|
|
169
|
+
- Encoding the state changes
|
|
170
|
+
- Encoding state with filters (properties using `@view()` tag)
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
import { Encoder } from "@colyseus/schema";
|
|
174
|
+
|
|
175
|
+
const state = new MyState();
|
|
176
|
+
const encoder = new Encoder(state);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
New clients must receive the full state on their first connection:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
const fullEncode = encoder.encodeAll();
|
|
183
|
+
// ... send "fullEncode" to client and decode it
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Further state changes must be sent in order:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
const changesBuffer = encoder.encode();
|
|
190
|
+
// ... send "changesBuffer" to client and decode it
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Encoding with views
|
|
194
|
+
|
|
195
|
+
When using `@view()` and `StateView`'s, a single "full encode" must be used for multiple views. Each view also must add its own changes.
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// shared buffer iterator
|
|
199
|
+
const it = { offset: 0 };
|
|
200
|
+
|
|
201
|
+
// shared full encode
|
|
202
|
+
encoder.encodeAll(it);
|
|
203
|
+
const sharedOffset = it.offset;
|
|
204
|
+
|
|
205
|
+
// view 1
|
|
206
|
+
const fullEncode1 = encoder.encodeAllView(view1, sharedOffset, it);
|
|
207
|
+
// ... send "fullEncode1" to client1 and decode it
|
|
208
|
+
|
|
209
|
+
// view 2
|
|
210
|
+
const fullEncode2 = encoder.encodeAllView(view2, sharedOffset, it);
|
|
211
|
+
// ... send "fullEncode" to client2 and decode it
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Encoding changes per views:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
// shared buffer iterator
|
|
218
|
+
const it = { offset: 0 };
|
|
219
|
+
|
|
220
|
+
// shared changes encode
|
|
221
|
+
encoder.encode(it);
|
|
222
|
+
const sharedOffset = it.offset;
|
|
223
|
+
|
|
224
|
+
// view 1
|
|
225
|
+
const view1Encoded = this.encoder.encodeView(view1, sharedOffset, it);
|
|
226
|
+
// ... send "view1Encoded" to client1 and decode it
|
|
227
|
+
|
|
228
|
+
// view 2
|
|
229
|
+
const view2Encoded = this.encoder.encodeView(view2, sharedOffset, it);
|
|
230
|
+
// ... send "view2Encoded" to client2 and decode it
|
|
231
|
+
|
|
232
|
+
// discard all changes after encoding is done.
|
|
233
|
+
encoder.discardChanges();
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Decoder
|
|
237
|
+
|
|
238
|
+
The `Decoder` class is used to decode the binary data received from the server.
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
import { Decoder } from "@colyseus/schema";
|
|
242
|
+
|
|
243
|
+
const state = new MyState();
|
|
244
|
+
const decoder = new Decoder(state);
|
|
245
|
+
decoder.decode(encodedBytes);
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Backwards/forwards compability
|
|
249
|
+
|
|
250
|
+
Backwards/fowards compatibility is possible by declaring new fields at the
|
|
251
|
+
end of existing structures, and earlier declarations to not be removed, but
|
|
252
|
+
be marked `@deprecated()` when needed.
|
|
253
|
+
|
|
254
|
+
This is particularly useful for native-compiled targets, such as C#, C++,
|
|
255
|
+
Haxe, etc - where the client-side can potentially not have the most
|
|
256
|
+
up-to-date version of the schema definitions.
|
|
257
|
+
|
|
258
|
+
|
|
176
259
|
## Limitations and best practices
|
|
177
260
|
|
|
178
261
|
- Each `Schema` structure can hold up to `64` fields. If you need more fields, use nested structures.
|
|
@@ -184,7 +267,6 @@ export class State extends Schema {
|
|
|
184
267
|
- `@colyseus/schema` encodes only field values in the specified order.
|
|
185
268
|
- Both encoder (server) and decoder (client) must have same schema definition.
|
|
186
269
|
- The order of the fields must be the same.
|
|
187
|
-
- Avoid manipulating indexes of an array. This result in at least `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.
|
|
188
270
|
|
|
189
271
|
## Generating client-side schema files (for strictly typed languages)
|
|
190
272
|
|
|
@@ -213,10 +295,14 @@ schema-codegen ./schemas/State.ts --output ./haxe-project/ --haxe
|
|
|
213
295
|
| Updating x/y of 50 entities after initial state | 342 | 684 |
|
|
214
296
|
| Updating x/y of 100 entities after initial state | 668 | 1529 |
|
|
215
297
|
|
|
298
|
+
## Decoder implementation in other languages
|
|
216
299
|
|
|
217
|
-
|
|
300
|
+
Each Colyseus SDK has its own decoder implementation of the `@colyseus/schema` protocol:
|
|
218
301
|
|
|
219
|
-
|
|
302
|
+
- [C#](https://github.com/colyseus/colyseus-unity-sdk)
|
|
303
|
+
- [Haxe](https://github.com/colyseus/colyseus-haxe)
|
|
304
|
+
- [Lua](https://github.com/colyseus/colyseus-defold)
|
|
305
|
+
- [C++](https://github.com/colyseus/colyseus-cocos2d-x) _(Not up-to-date)_
|
|
220
306
|
|
|
221
307
|
## Why
|
|
222
308
|
|
package/bin/schema-debug
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const schema = require('@colyseus/schema');
|
|
5
|
+
|
|
6
|
+
const Reflection = schema.Reflection;
|
|
7
|
+
const Decoder = schema.Decoder;
|
|
8
|
+
|
|
9
|
+
if (!fs.existsSync(process.argv[2])) {
|
|
10
|
+
console.error("Error: File not found:", process.argv[2]);
|
|
11
|
+
console.log("");
|
|
12
|
+
console.log("Usage: schema-debug <schema-debug.txt>");
|
|
13
|
+
console.log("");
|
|
14
|
+
console.log(" From your server-side, you must use the SchemaSerializerDebug as serializer, in order to generate the schema-debug.txt file.");
|
|
15
|
+
console.log("");
|
|
16
|
+
console.log(" Example:");
|
|
17
|
+
console.log("");
|
|
18
|
+
console.log(" import { SchemaSerializerDebug } from '@colyseus/core';");
|
|
19
|
+
console.log(" // ...");
|
|
20
|
+
console.log(" onCreate() {");
|
|
21
|
+
console.log(" const state = new MyRoomState();");
|
|
22
|
+
console.log(" this.setState(state);");
|
|
23
|
+
console.log(" // Override serializer");
|
|
24
|
+
console.log(" this.setSerializer(new SchemaSerializerDebug());");
|
|
25
|
+
console.log(" this['_serializer'].reset(state)");
|
|
26
|
+
console.log(" // ...");
|
|
27
|
+
console.log("");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const contents = fs.readFileSync(process.argv[2], { encoding: "utf8" }).toString();
|
|
32
|
+
|
|
33
|
+
let isCommentBlock = false;
|
|
34
|
+
let lastComment = "";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @type {Decoder}
|
|
38
|
+
*/
|
|
39
|
+
let decoder;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
*
|
|
43
|
+
* @param line string
|
|
44
|
+
* @returns {Buffer}
|
|
45
|
+
*/
|
|
46
|
+
function getBuffer(line) {
|
|
47
|
+
const start = line.lastIndexOf(":");
|
|
48
|
+
const buffer = Buffer.from(new Uint8Array(line.substring(start + 1).split(",").map(n => Number(n))));
|
|
49
|
+
console.log(`(${buffer.byteLength}) ${Array.from(buffer).join(",")}`)
|
|
50
|
+
// console.log("");
|
|
51
|
+
// console.log("");
|
|
52
|
+
// console.log("> ", line);
|
|
53
|
+
// console.log("> substring:", line.substring(start + 1))
|
|
54
|
+
return buffer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param buffer {Buffer}
|
|
59
|
+
*/
|
|
60
|
+
function decode(buffer) {
|
|
61
|
+
try {
|
|
62
|
+
decoder.decode(buffer);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
console.error(e);
|
|
65
|
+
console.log("NOT OK. Last log:\n\n")
|
|
66
|
+
console.log(lastComment);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
contents.split("\n").forEach((line) => {
|
|
71
|
+
if (line.startsWith("#")) {
|
|
72
|
+
// reset last comment.
|
|
73
|
+
if (isCommentBlock === false) { lastComment = ""; }
|
|
74
|
+
|
|
75
|
+
isCommentBlock = true;
|
|
76
|
+
lastComment += line.substring(line.indexOf(":") + 1) + "\n";
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
isCommentBlock = false;
|
|
81
|
+
|
|
82
|
+
if (line.startsWith("handshake:") && !decoder) {
|
|
83
|
+
const state = Reflection.decode(getBuffer(line));
|
|
84
|
+
decoder = new Decoder(state);
|
|
85
|
+
|
|
86
|
+
} else if (line.startsWith("state:")) {
|
|
87
|
+
decode(getBuffer(line));
|
|
88
|
+
|
|
89
|
+
} else if (line.startsWith("patch:")) {
|
|
90
|
+
decode(getBuffer(line));
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
console.log("OK:", decoder.state.toJSON());
|