@colyseus/schema 3.0.2 → 3.0.4

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 CHANGED
@@ -9,13 +9,14 @@
9
9
 
10
10
  # Features
11
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)*
12
+ - **Incremental State Synchronization**: Send only the properties that have changed.
13
+ - **Trigger Callbacks at Decoding**: [Bring your own](https://docs.colyseus.io/state/callbacks/custom) callback system at decoding, or use the built-in one.
14
+ - **Instance Reference Tracking**: Share references of the same instance across the state.
15
+ - **State Views**: Filter properties that should be sent only to specific clients.
16
+ - **Reflection**: Encode/Decode schema definitions.
17
+ - **Schema Generation**: Generate client-side schema files for strictly typed languages.
18
+ - **Type Safety**: Strictly typed schema definitions.
19
+ - **Multiple Language Support**: Decoders available for multiple languages ([C#](https://github.com/colyseus/colyseus-unity-sdk/tree/master/Assets/Colyseus/Runtime/Colyseus/Serializer/Schema), [Lua](https://github.com/colyseus/colyseus-defold/tree/master/colyseus/serializer/schema), [Haxe](https://github.com/colyseus/colyseus-haxe/tree/master/src/io/colyseus/serializer/schema)).
19
20
 
20
21
  ## Schema definition
21
22
 
@@ -1547,7 +1547,7 @@ function decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges
1547
1547
  // previousValue,
1548
1548
  // });
1549
1549
  }
1550
- value = null;
1550
+ value = undefined;
1551
1551
  }
1552
1552
  if (operation === exports.OPERATION.DELETE) ;
1553
1553
  else if (Schema.is(type)) {
@@ -1861,6 +1861,9 @@ class ArraySchema {
1861
1861
  // type format: { array: "string" }
1862
1862
  (type['array'] !== undefined));
1863
1863
  }
1864
+ static from(iterable) {
1865
+ return new ArraySchema(...Array.from(iterable));
1866
+ }
1864
1867
  constructor(...items) {
1865
1868
  this.items = [];
1866
1869
  this.tmpItems = [];
@@ -2227,8 +2230,8 @@ class ArraySchema {
2227
2230
  lastIndexOf(searchElement, fromIndex = this.length - 1) {
2228
2231
  return this.items.lastIndexOf(searchElement, fromIndex);
2229
2232
  }
2230
- every(callbackfn, thisArg) {
2231
- return this.items.every(callbackfn, thisArg);
2233
+ every(predicate, thisArg) {
2234
+ return this.items.every(predicate, thisArg);
2232
2235
  }
2233
2236
  /**
2234
2237
  * Determines whether the specified callback function returns true for any element of an array.
@@ -2410,6 +2413,9 @@ class ArraySchema {
2410
2413
  //
2411
2414
  with(index, value) {
2412
2415
  const copy = this.items.slice();
2416
+ // Allow negative indexing from the end
2417
+ if (index < 0)
2418
+ index += this.length;
2413
2419
  copy[index] = value;
2414
2420
  return new ArraySchema(...copy);
2415
2421
  }
@@ -4485,7 +4491,10 @@ function getDecoderStateCallbacks(decoder) {
4485
4491
  }
4486
4492
  }
4487
4493
  // trigger onChange
4488
- if (change.value !== change.previousValue) {
4494
+ if (change.value !== change.previousValue &&
4495
+ // FIXME: see "should not encode item if added and removed at the same patch" test case.
4496
+ // some "ADD" + "DELETE" operations on same patch are being encoded as "DELETE"
4497
+ (change.value !== undefined || change.previousValue !== undefined)) {
4489
4498
  const replaceCallbacks = $callbacks[exports.OPERATION.REPLACE];
4490
4499
  for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {
4491
4500
  replaceCallbacks[i](change.value, change.dynamicIndex ?? change.field);
@@ -4598,6 +4607,9 @@ function getDecoderStateCallbacks(decoder) {
4598
4607
  const onRemove = function (ref, callback) {
4599
4608
  return $root.addCallback($root.refIds.get(ref), exports.OPERATION.DELETE, callback);
4600
4609
  };
4610
+ const onChange = function (ref, callback) {
4611
+ return $root.addCallback($root.refIds.get(ref), exports.OPERATION.REPLACE, callback);
4612
+ };
4601
4613
  return new Proxy({
4602
4614
  onAdd: function (callback, immediate = true) {
4603
4615
  //
@@ -4629,6 +4641,19 @@ function getDecoderStateCallbacks(decoder) {
4629
4641
  return onRemove(context.instance, callback);
4630
4642
  }
4631
4643
  },
4644
+ onChange: function (callback) {
4645
+ if (context.onInstanceAvailable) {
4646
+ // collection instance not received yet
4647
+ let detachCallback = () => { };
4648
+ context.onInstanceAvailable((ref) => {
4649
+ detachCallback = onChange(ref, callback);
4650
+ });
4651
+ return () => detachCallback();
4652
+ }
4653
+ else if (context.instance) {
4654
+ return onChange(context.instance, callback);
4655
+ }
4656
+ },
4632
4657
  }, {
4633
4658
  get(target, prop) {
4634
4659
  if (!target[prop]) {