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