@colyseus/schema 3.0.0-alpha.15 → 3.0.0-alpha.17

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.
@@ -27,6 +27,7 @@ exports.OPERATION = void 0;
27
27
  OPERATION[OPERATION["REVERSE"] = 15] = "REVERSE";
28
28
  OPERATION[OPERATION["MOVE"] = 32] = "MOVE";
29
29
  OPERATION[OPERATION["DELETE_BY_REFID"] = 33] = "DELETE_BY_REFID";
30
+ OPERATION[OPERATION["ADD_BY_REFID"] = 129] = "ADD_BY_REFID";
30
31
  })(exports.OPERATION || (exports.OPERATION = {}));
31
32
 
32
33
  Symbol.metadata ??= Symbol.for("Symbol.metadata");
@@ -967,15 +968,19 @@ const encodeKeyValueOperation = function (encoder, bytes, changeTree, field, ope
967
968
  */
968
969
  const encodeArray = function (encoder, bytes, changeTree, field, operation, it, isEncodeAll, hasView) {
969
970
  const ref = changeTree.ref;
970
- if (hasView &&
971
- operation === exports.OPERATION.DELETE &&
972
- typeof (changeTree.getType(field)) !== "string") {
973
- // encode delete by refId (array of schemas)
974
- bytes[it.offset++] = exports.OPERATION.DELETE_BY_REFID;
975
- const value = ref['tmpItems'][field];
976
- const refId = value[$changes].refId;
977
- number$1(bytes, refId, it);
978
- return;
971
+ const useOperationByRefId = hasView && changeTree.isFiltered && (typeof (changeTree.getType(field)) !== "string");
972
+ let refOrIndex;
973
+ if (useOperationByRefId) {
974
+ refOrIndex = ref['tmpItems'][field][$changes].refId;
975
+ if (operation === exports.OPERATION.DELETE) {
976
+ operation = exports.OPERATION.DELETE_BY_REFID;
977
+ }
978
+ else if (operation === exports.OPERATION.ADD) {
979
+ operation = exports.OPERATION.ADD_BY_REFID;
980
+ }
981
+ }
982
+ else {
983
+ refOrIndex = field;
979
984
  }
980
985
  // encode operation
981
986
  bytes[it.offset++] = operation & 255;
@@ -984,7 +989,7 @@ const encodeArray = function (encoder, bytes, changeTree, field, operation, it,
984
989
  return;
985
990
  }
986
991
  // encode index
987
- number$1(bytes, field, it);
992
+ number$1(bytes, refOrIndex, it);
988
993
  // Do not encode value for DELETE operations
989
994
  if (operation === exports.OPERATION.DELETE) {
990
995
  return;
@@ -1443,7 +1448,8 @@ const decodeKeyValueOperation = function (decoder, bytes, it, ref, allChanges) {
1443
1448
  };
1444
1449
  const decodeArray = function (decoder, bytes, it, ref, allChanges) {
1445
1450
  // "uncompressed" index + operation (array/map items)
1446
- const operation = bytes[it.offset++];
1451
+ let operation = bytes[it.offset++];
1452
+ let index;
1447
1453
  if (operation === exports.OPERATION.CLEAR) {
1448
1454
  //
1449
1455
  // When decoding:
@@ -1458,7 +1464,7 @@ const decodeArray = function (decoder, bytes, it, ref, allChanges) {
1458
1464
  // TODO: refactor here, try to follow same flow as below
1459
1465
  const refId = number(bytes, it);
1460
1466
  const previousValue = decoder.root.refs.get(refId);
1461
- const index = ref.findIndex((value) => value === previousValue);
1467
+ index = ref.findIndex((value) => value === previousValue);
1462
1468
  ref[$deleteByIndex](index);
1463
1469
  allChanges.push({
1464
1470
  ref,
@@ -1471,7 +1477,18 @@ const decodeArray = function (decoder, bytes, it, ref, allChanges) {
1471
1477
  });
1472
1478
  return;
1473
1479
  }
1474
- const index = number(bytes, it);
1480
+ else if (operation === exports.OPERATION.ADD_BY_REFID) {
1481
+ // operation = OPERATION.ADD;
1482
+ const refId = number(bytes, it);
1483
+ const itemByRefId = decoder.root.refs.get(refId);
1484
+ // use existing index, or push new value
1485
+ index = (itemByRefId)
1486
+ ? ref.findIndex((value) => value === itemByRefId)
1487
+ : ref.length;
1488
+ }
1489
+ else {
1490
+ index = number(bytes, it);
1491
+ }
1475
1492
  const type = ref[$childType];
1476
1493
  let dynamicIndex = index;
1477
1494
  const { value, previousValue } = decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges);
@@ -4017,16 +4034,7 @@ function getStateCallbacks(decoder) {
4017
4034
  //
4018
4035
  // Handle collection of items
4019
4036
  //
4020
- if (change.op === exports.OPERATION.ADD && change.previousValue === undefined) {
4021
- // triger onAdd
4022
- isTriggeringOnAdd = true;
4023
- const addCallbacks = $callbacks[exports.OPERATION.ADD];
4024
- for (let i = addCallbacks?.length - 1; i >= 0; i--) {
4025
- addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
4026
- }
4027
- isTriggeringOnAdd = false;
4028
- }
4029
- else if ((change.op & exports.OPERATION.DELETE) === exports.OPERATION.DELETE) {
4037
+ if ((change.op & exports.OPERATION.DELETE) === exports.OPERATION.DELETE) {
4030
4038
  //
4031
4039
  // FIXME: `previousValue` should always be available.
4032
4040
  //
@@ -4046,6 +4054,15 @@ function getStateCallbacks(decoder) {
4046
4054
  }
4047
4055
  }
4048
4056
  }
4057
+ else if ((change.op & exports.OPERATION.ADD) === exports.OPERATION.ADD && change.previousValue === undefined) {
4058
+ // triger onAdd
4059
+ isTriggeringOnAdd = true;
4060
+ const addCallbacks = $callbacks[exports.OPERATION.ADD];
4061
+ for (let i = addCallbacks?.length - 1; i >= 0; i--) {
4062
+ addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
4063
+ }
4064
+ isTriggeringOnAdd = false;
4065
+ }
4049
4066
  // trigger onChange
4050
4067
  if (change.value !== change.previousValue) {
4051
4068
  const replaceCallbacks = $callbacks[exports.OPERATION.REPLACE];
@@ -4217,12 +4234,18 @@ class StateView {
4217
4234
  console.warn("StateView#add(), invalid object:", obj);
4218
4235
  return this;
4219
4236
  }
4237
+ // FIXME: ArraySchema/MapSchema does not have metadata
4238
+ const metadata = obj.constructor[Symbol.metadata];
4220
4239
  let changeTree = obj[$changes];
4221
4240
  this.items.add(changeTree);
4222
4241
  // Add children of this ChangeTree to this view
4223
- changeTree.forEachChild((change, _) => this.add(change.ref, tag));
4224
- // FIXME: ArraySchema/MapSchema does not have metadata
4225
- const metadata = obj.constructor[Symbol.metadata];
4242
+ changeTree.forEachChild((change, index) => {
4243
+ // Do not ADD children that don't have the same tag
4244
+ if (metadata && metadata[metadata[index]].tag !== tag) {
4245
+ return;
4246
+ }
4247
+ this.add(change.ref, tag);
4248
+ });
4226
4249
  // add parent ChangeTree's, if they are invisible to this view
4227
4250
  // TODO: REFACTOR addParent()
4228
4251
  this.addParent(changeTree, tag);
@@ -4249,7 +4272,6 @@ class StateView {
4249
4272
  tags = this.tags.get(changeTree);
4250
4273
  }
4251
4274
  tags.add(tag);
4252
- // console.log("BY TAG:", tag);
4253
4275
  // Ref: add tagged properties
4254
4276
  metadata?.[-3]?.[tag]?.forEach((index) => {
4255
4277
  if (changeTree.getChange(index) !== exports.OPERATION.DELETE) {