@colyseus/schema 5.0.3 → 5.0.5
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/build/codegen/cli.cjs +23 -0
- package/build/codegen/cli.cjs.map +1 -1
- package/build/decoder/strategy/Callbacks.d.ts +6 -6
- package/build/encoder/StateView.d.ts +17 -0
- package/build/index.cjs +184 -37
- package/build/index.cjs.map +1 -1
- package/build/index.js +184 -37
- package/build/index.mjs +184 -37
- package/build/index.mjs.map +1 -1
- package/build/input/index.cjs +28 -4
- package/build/input/index.cjs.map +1 -1
- package/build/input/index.mjs +28 -4
- package/build/input/index.mjs.map +1 -1
- package/build/types/builder.d.ts +83 -29
- package/package.json +6 -5
- package/src/annotations.ts +48 -18
- package/src/codegen/languages/csharp.ts +24 -0
- package/src/decoder/strategy/Callbacks.ts +16 -14
- package/src/encoder/Encoder.ts +13 -2
- package/src/encoder/StateView.ts +63 -2
- package/src/encoder/changeTree/inheritedFlags.ts +16 -2
- package/src/types/builder.ts +82 -20
package/src/types/builder.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface BuilderDefinition {
|
|
|
27
27
|
static?: boolean;
|
|
28
28
|
stream?: boolean;
|
|
29
29
|
optional?: boolean;
|
|
30
|
+
/** Local-only field: typed + initialized, but never registered for sync. */
|
|
31
|
+
noSync?: boolean;
|
|
30
32
|
/** Declaration-scope priority callback for `.stream()` fields. */
|
|
31
33
|
streamPriority?: (view: any, element: any) => number;
|
|
32
34
|
}
|
|
@@ -64,21 +66,24 @@ export class FieldBuilder<
|
|
|
64
66
|
> {
|
|
65
67
|
readonly [$builder]: true = true;
|
|
66
68
|
|
|
67
|
-
// Internal configuration.
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
69
|
+
// Internal configuration. Declared `private` (soft-private): hidden from
|
|
70
|
+
// editor autocomplete and from normal external `.field` access, but still
|
|
71
|
+
// reachable at runtime via element access (e.g. `builder['_noSync']`) for
|
|
72
|
+
// internal tooling/tests. Not meant to be mutated by end users.
|
|
73
|
+
private _type: DefinitionType;
|
|
74
|
+
private _default: any = undefined;
|
|
75
|
+
private _hasDefault = false;
|
|
76
|
+
private _view: number | undefined = undefined;
|
|
77
|
+
private _owned = false;
|
|
78
|
+
private _unreliable = false;
|
|
79
|
+
private _transient = false;
|
|
80
|
+
private _deprecated = false;
|
|
81
|
+
private _deprecatedThrows = true;
|
|
82
|
+
private _static = false;
|
|
83
|
+
private _stream = false;
|
|
84
|
+
private _optional = false;
|
|
85
|
+
private _noSync = false;
|
|
86
|
+
private _streamPriority: ((view: any, element: any) => number) | undefined = undefined;
|
|
82
87
|
|
|
83
88
|
constructor(type: DefinitionType) {
|
|
84
89
|
this._type = type;
|
|
@@ -136,6 +141,31 @@ export class FieldBuilder<
|
|
|
136
141
|
return this;
|
|
137
142
|
}
|
|
138
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Mark this field as **local-only** — it is typed and initialized on the
|
|
146
|
+
* instance (so `.default()` and the inferred instance type still apply),
|
|
147
|
+
* but is never registered for synchronization: it never enters change
|
|
148
|
+
* tracking, never goes over the wire, and decoders never receive it.
|
|
149
|
+
*
|
|
150
|
+
* Useful for server-side scratch state, per-peer UI state, or values you
|
|
151
|
+
* want on the class for typing convenience without paying any sync cost.
|
|
152
|
+
*
|
|
153
|
+
* Mutually exclusive with the sync-only modifiers (`.view()`, `.owned()`,
|
|
154
|
+
* `.unreliable()`, `.transient()`, `.static()`, `.stream()`) — combining
|
|
155
|
+
* them throws at `schema()` time.
|
|
156
|
+
*
|
|
157
|
+
* ```ts
|
|
158
|
+
* const Player = schema({
|
|
159
|
+
* hp: t.uint8().default(100), // synchronized
|
|
160
|
+
* lastInputTick: t.number().noSync(), // local-only
|
|
161
|
+
* }, 'Player');
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
noSync(): this {
|
|
165
|
+
this._noSync = true;
|
|
166
|
+
return this;
|
|
167
|
+
}
|
|
168
|
+
|
|
139
169
|
/**
|
|
140
170
|
* Opt a collection field into priority-batched streaming delivery —
|
|
141
171
|
* ADDs drain at most `maxPerTick` per tick per view (or per broadcast
|
|
@@ -194,7 +224,12 @@ export class FieldBuilder<
|
|
|
194
224
|
return this as unknown as FieldBuilder<T | undefined, HasDefault, true>;
|
|
195
225
|
}
|
|
196
226
|
|
|
197
|
-
|
|
227
|
+
/**
|
|
228
|
+
* @internal — snapshot of the builder's configuration consumed by
|
|
229
|
+
* `schema()`. `private` keeps it out of autocomplete; internal callers
|
|
230
|
+
* reach it via element access (`builder['toDefinition']()`).
|
|
231
|
+
*/
|
|
232
|
+
private toDefinition(): BuilderDefinition {
|
|
198
233
|
return {
|
|
199
234
|
type: this._type,
|
|
200
235
|
default: this._default,
|
|
@@ -208,6 +243,7 @@ export class FieldBuilder<
|
|
|
208
243
|
static: this._static,
|
|
209
244
|
stream: this._stream,
|
|
210
245
|
optional: this._optional,
|
|
246
|
+
noSync: this._noSync,
|
|
211
247
|
streamPriority: this._streamPriority,
|
|
212
248
|
};
|
|
213
249
|
}
|
|
@@ -221,8 +257,33 @@ export function isBuilder(value: any): value is FieldBuilder<any> {
|
|
|
221
257
|
// Factory helpers
|
|
222
258
|
// ---------------------------------------------------------------------------
|
|
223
259
|
|
|
224
|
-
|
|
225
|
-
|
|
260
|
+
/**
|
|
261
|
+
* Primitive field factory. Calling it bare (`t.int8()`) yields the natural type
|
|
262
|
+
* for the wire codec (`number` for the int/float formats, plus `string` /
|
|
263
|
+
* `boolean` / `bigint`). Pass an explicit type argument to refine the inferred
|
|
264
|
+
* value at the TYPE level, while the wire encoding is unchanged:
|
|
265
|
+
*
|
|
266
|
+
* moveX: t.int8<-1 | 0 | 1>(), // typed -1|0|1, still encoded as int8
|
|
267
|
+
* team: t.string<"red" | "blue">(),
|
|
268
|
+
*
|
|
269
|
+
* Two call signatures, NOT a defaulted generic `<T extends TBase = TBase>`: the
|
|
270
|
+
* bare form must return a CONCRETE `FieldBuilder<TBase>` so `schema({ x:
|
|
271
|
+
* t.number() })` still infers `x: number`. A defaulted free type parameter gets
|
|
272
|
+
* captured as `any` during `schema()`'s self-referential field inference (and
|
|
273
|
+
* `undefined extends any` then flips every field optional).
|
|
274
|
+
*
|
|
275
|
+
* NOTE: the refinement is a TYPE-LEVEL assertion, not a runtime guarantee — the
|
|
276
|
+
* wire still carries the codec's full range and the DECODER writes whatever
|
|
277
|
+
* bytes arrive. Sound for server-authored state; for INPUT schemas the value
|
|
278
|
+
* comes from an untrusted client (the type reads `-1|0|1` while a peer can send
|
|
279
|
+
* any int8), so keep validating/clamping on the receiving side.
|
|
280
|
+
*/
|
|
281
|
+
interface PrimitiveFactory<TBase> {
|
|
282
|
+
(): FieldBuilder<TBase>;
|
|
283
|
+
<T extends TBase>(): FieldBuilder<T>;
|
|
284
|
+
}
|
|
285
|
+
function primitive<TBase>(name: RawPrimitiveType): PrimitiveFactory<TBase> {
|
|
286
|
+
return (() => new FieldBuilder<TBase>(name)) as PrimitiveFactory<TBase>;
|
|
226
287
|
}
|
|
227
288
|
|
|
228
289
|
// Accepts a Schema class, a primitive string, or another FieldBuilder as a child type.
|
|
@@ -233,7 +294,8 @@ export type ChildType =
|
|
|
233
294
|
|
|
234
295
|
function resolveChild(child: ChildType): DefinitionType {
|
|
235
296
|
if (isBuilder(child)) {
|
|
236
|
-
|
|
297
|
+
// `_type` is private; element access bypasses the visibility check.
|
|
298
|
+
return child['_type'];
|
|
237
299
|
}
|
|
238
300
|
return child as DefinitionType;
|
|
239
301
|
}
|
|
@@ -283,7 +345,7 @@ const collectionFactory: CollectionFactory = ((child: ChildType) =>
|
|
|
283
345
|
new FieldBuilder({ collection: resolveChild(child) } as DefinitionType)) as CollectionFactory;
|
|
284
346
|
const streamFactory: StreamFactory = ((child: ChildType) => {
|
|
285
347
|
const b = new FieldBuilder({ stream: resolveChild(child) } as DefinitionType);
|
|
286
|
-
b
|
|
348
|
+
b['_stream'] = true; // element access bypasses `private`
|
|
287
349
|
return b;
|
|
288
350
|
}) as StreamFactory;
|
|
289
351
|
|