@colyseus/schema 4.0.26 → 4.0.27
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/encoder/Encoder.d.ts +2 -0
- package/build/index.cjs +33 -26
- package/build/index.cjs.map +1 -1
- package/build/index.js +33 -26
- package/build/index.mjs +33 -26
- package/build/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/encoder/Encoder.ts +32 -29
package/build/index.js
CHANGED
|
@@ -4404,41 +4404,43 @@
|
|
|
4404
4404
|
encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView, metadata);
|
|
4405
4405
|
}
|
|
4406
4406
|
}
|
|
4407
|
-
if (it.offset
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4407
|
+
if (it.offset <= buffer.byteLength) {
|
|
4408
|
+
return buffer.subarray(0, it.offset);
|
|
4409
|
+
}
|
|
4410
|
+
// Overflowed: grow and re-encode. Reuse the same iterator so `it.offset`
|
|
4411
|
+
// ends accurate — a fresh one strands it at the overflow value and
|
|
4412
|
+
// corrupts the next view's `viewOffset` in a multi-view encode.
|
|
4413
|
+
buffer = this.ensureCapacity(buffer, it.offset);
|
|
4414
|
+
console.warn(`@colyseus/schema buffer overflow. Encoded state is higher than default BUFFER_SIZE. Use the following to increase default BUFFER_SIZE:
|
|
4412
4415
|
|
|
4413
4416
|
import { Encoder } from "@colyseus/schema";
|
|
4414
|
-
Encoder.BUFFER_SIZE = ${Math.round(
|
|
4417
|
+
Encoder.BUFFER_SIZE = ${Math.round(buffer.byteLength / 1024)} * 1024; // ${Math.round(buffer.byteLength / 1024)} KB
|
|
4415
4418
|
`);
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
// -> No we probably can't unless we catch the need for resize before encoding which is likely more computationally expensive than resizing on demand
|
|
4419
|
-
//
|
|
4420
|
-
const newBuffer = new Uint8Array(newSize);
|
|
4421
|
-
newBuffer.set(buffer); // copy previous encoding steps beyond the initialOffset
|
|
4422
|
-
buffer = newBuffer;
|
|
4423
|
-
// assign resized buffer to local sharedBuffer
|
|
4424
|
-
if (buffer === this.sharedBuffer) {
|
|
4425
|
-
this.sharedBuffer = buffer;
|
|
4426
|
-
}
|
|
4427
|
-
return this.encode({ offset: initialOffset }, view, buffer, changeSetName, isEncodeAll);
|
|
4428
|
-
}
|
|
4429
|
-
else {
|
|
4430
|
-
return buffer.subarray(0, it.offset);
|
|
4431
|
-
}
|
|
4419
|
+
it.offset = initialOffset;
|
|
4420
|
+
return this.encode(it, view, buffer, changeSetName, isEncodeAll);
|
|
4432
4421
|
}
|
|
4433
4422
|
encodeAll(it = { offset: 0 }, buffer = this.sharedBuffer) {
|
|
4434
4423
|
return this.encode(it, undefined, buffer, "allChanges", true);
|
|
4435
4424
|
}
|
|
4436
4425
|
encodeAllView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
4437
4426
|
const viewOffset = it.offset;
|
|
4438
|
-
//
|
|
4439
|
-
this.encode(it, view, bytes, "allFilteredChanges", true, viewOffset);
|
|
4427
|
+
// encode() may reallocate the buffer — keep its return, not the stale `bytes`.
|
|
4428
|
+
bytes = this.encode(it, view, bytes, "allFilteredChanges", true, viewOffset);
|
|
4440
4429
|
return concatBytes(bytes.subarray(0, sharedOffset), bytes.subarray(viewOffset, it.offset));
|
|
4441
4430
|
}
|
|
4431
|
+
/** Grow `buffer` to keep BUFFER_SIZE free bytes past `offset`, preserving `[0, offset)`. */
|
|
4432
|
+
ensureCapacity(buffer, offset) {
|
|
4433
|
+
if (offset + Encoder.BUFFER_SIZE <= buffer.byteLength) {
|
|
4434
|
+
return buffer;
|
|
4435
|
+
}
|
|
4436
|
+
const size = Math.ceil((offset + Encoder.BUFFER_SIZE) / Encoder.BUFFER_SIZE) * Encoder.BUFFER_SIZE;
|
|
4437
|
+
const grown = new Uint8Array(size);
|
|
4438
|
+
grown.set(buffer.subarray(0, offset));
|
|
4439
|
+
if (buffer === this.sharedBuffer) {
|
|
4440
|
+
this.sharedBuffer = grown;
|
|
4441
|
+
}
|
|
4442
|
+
return grown;
|
|
4443
|
+
}
|
|
4442
4444
|
encodeView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
4443
4445
|
const viewOffset = it.offset;
|
|
4444
4446
|
//
|
|
@@ -4477,6 +4479,9 @@
|
|
|
4477
4479
|
const ctor = ref.constructor;
|
|
4478
4480
|
const encoder = ctor[$encoder];
|
|
4479
4481
|
const metadata = ctor[Symbol.metadata];
|
|
4482
|
+
// These writes are unguarded and unrecoverable (view.changes is cleared
|
|
4483
|
+
// below), so unlike encode() they can't re-encode on overflow — grow ahead.
|
|
4484
|
+
bytes = this.ensureCapacity(bytes, it.offset);
|
|
4480
4485
|
bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;
|
|
4481
4486
|
encode.number(bytes, ref[$refId], it);
|
|
4482
4487
|
for (let i = 0, numChanges = keys.length; i < numChanges; i++) {
|
|
@@ -4496,8 +4501,10 @@
|
|
|
4496
4501
|
// clear "view" changes after encoding
|
|
4497
4502
|
view.changes.clear();
|
|
4498
4503
|
view.changesOutOfOrder = false;
|
|
4499
|
-
//
|
|
4500
|
-
|
|
4504
|
+
// encode() may reallocate the buffer — keep its return, not the stale `bytes`.
|
|
4505
|
+
// Anchor the re-encode at the current offset (default), not `viewOffset`: a
|
|
4506
|
+
// resize must not clobber the view.changes already written at [viewOffset, ).
|
|
4507
|
+
bytes = this.encode(it, view, bytes, "filteredChanges", false);
|
|
4501
4508
|
return concatBytes(bytes.subarray(0, sharedOffset), bytes.subarray(viewOffset, it.offset));
|
|
4502
4509
|
}
|
|
4503
4510
|
/**
|
package/build/index.mjs
CHANGED
|
@@ -4398,41 +4398,43 @@ class Encoder {
|
|
|
4398
4398
|
encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView, metadata);
|
|
4399
4399
|
}
|
|
4400
4400
|
}
|
|
4401
|
-
if (it.offset
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4401
|
+
if (it.offset <= buffer.byteLength) {
|
|
4402
|
+
return buffer.subarray(0, it.offset);
|
|
4403
|
+
}
|
|
4404
|
+
// Overflowed: grow and re-encode. Reuse the same iterator so `it.offset`
|
|
4405
|
+
// ends accurate — a fresh one strands it at the overflow value and
|
|
4406
|
+
// corrupts the next view's `viewOffset` in a multi-view encode.
|
|
4407
|
+
buffer = this.ensureCapacity(buffer, it.offset);
|
|
4408
|
+
console.warn(`@colyseus/schema buffer overflow. Encoded state is higher than default BUFFER_SIZE. Use the following to increase default BUFFER_SIZE:
|
|
4406
4409
|
|
|
4407
4410
|
import { Encoder } from "@colyseus/schema";
|
|
4408
|
-
Encoder.BUFFER_SIZE = ${Math.round(
|
|
4411
|
+
Encoder.BUFFER_SIZE = ${Math.round(buffer.byteLength / 1024)} * 1024; // ${Math.round(buffer.byteLength / 1024)} KB
|
|
4409
4412
|
`);
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
// -> No we probably can't unless we catch the need for resize before encoding which is likely more computationally expensive than resizing on demand
|
|
4413
|
-
//
|
|
4414
|
-
const newBuffer = new Uint8Array(newSize);
|
|
4415
|
-
newBuffer.set(buffer); // copy previous encoding steps beyond the initialOffset
|
|
4416
|
-
buffer = newBuffer;
|
|
4417
|
-
// assign resized buffer to local sharedBuffer
|
|
4418
|
-
if (buffer === this.sharedBuffer) {
|
|
4419
|
-
this.sharedBuffer = buffer;
|
|
4420
|
-
}
|
|
4421
|
-
return this.encode({ offset: initialOffset }, view, buffer, changeSetName, isEncodeAll);
|
|
4422
|
-
}
|
|
4423
|
-
else {
|
|
4424
|
-
return buffer.subarray(0, it.offset);
|
|
4425
|
-
}
|
|
4413
|
+
it.offset = initialOffset;
|
|
4414
|
+
return this.encode(it, view, buffer, changeSetName, isEncodeAll);
|
|
4426
4415
|
}
|
|
4427
4416
|
encodeAll(it = { offset: 0 }, buffer = this.sharedBuffer) {
|
|
4428
4417
|
return this.encode(it, undefined, buffer, "allChanges", true);
|
|
4429
4418
|
}
|
|
4430
4419
|
encodeAllView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
4431
4420
|
const viewOffset = it.offset;
|
|
4432
|
-
//
|
|
4433
|
-
this.encode(it, view, bytes, "allFilteredChanges", true, viewOffset);
|
|
4421
|
+
// encode() may reallocate the buffer — keep its return, not the stale `bytes`.
|
|
4422
|
+
bytes = this.encode(it, view, bytes, "allFilteredChanges", true, viewOffset);
|
|
4434
4423
|
return concatBytes(bytes.subarray(0, sharedOffset), bytes.subarray(viewOffset, it.offset));
|
|
4435
4424
|
}
|
|
4425
|
+
/** Grow `buffer` to keep BUFFER_SIZE free bytes past `offset`, preserving `[0, offset)`. */
|
|
4426
|
+
ensureCapacity(buffer, offset) {
|
|
4427
|
+
if (offset + Encoder.BUFFER_SIZE <= buffer.byteLength) {
|
|
4428
|
+
return buffer;
|
|
4429
|
+
}
|
|
4430
|
+
const size = Math.ceil((offset + Encoder.BUFFER_SIZE) / Encoder.BUFFER_SIZE) * Encoder.BUFFER_SIZE;
|
|
4431
|
+
const grown = new Uint8Array(size);
|
|
4432
|
+
grown.set(buffer.subarray(0, offset));
|
|
4433
|
+
if (buffer === this.sharedBuffer) {
|
|
4434
|
+
this.sharedBuffer = grown;
|
|
4435
|
+
}
|
|
4436
|
+
return grown;
|
|
4437
|
+
}
|
|
4436
4438
|
encodeView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
4437
4439
|
const viewOffset = it.offset;
|
|
4438
4440
|
//
|
|
@@ -4471,6 +4473,9 @@ class Encoder {
|
|
|
4471
4473
|
const ctor = ref.constructor;
|
|
4472
4474
|
const encoder = ctor[$encoder];
|
|
4473
4475
|
const metadata = ctor[Symbol.metadata];
|
|
4476
|
+
// These writes are unguarded and unrecoverable (view.changes is cleared
|
|
4477
|
+
// below), so unlike encode() they can't re-encode on overflow — grow ahead.
|
|
4478
|
+
bytes = this.ensureCapacity(bytes, it.offset);
|
|
4474
4479
|
bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;
|
|
4475
4480
|
encode.number(bytes, ref[$refId], it);
|
|
4476
4481
|
for (let i = 0, numChanges = keys.length; i < numChanges; i++) {
|
|
@@ -4490,8 +4495,10 @@ class Encoder {
|
|
|
4490
4495
|
// clear "view" changes after encoding
|
|
4491
4496
|
view.changes.clear();
|
|
4492
4497
|
view.changesOutOfOrder = false;
|
|
4493
|
-
//
|
|
4494
|
-
|
|
4498
|
+
// encode() may reallocate the buffer — keep its return, not the stale `bytes`.
|
|
4499
|
+
// Anchor the re-encode at the current offset (default), not `viewOffset`: a
|
|
4500
|
+
// resize must not clobber the view.changes already written at [viewOffset, ).
|
|
4501
|
+
bytes = this.encode(it, view, bytes, "filteredChanges", false);
|
|
4495
4502
|
return concatBytes(bytes.subarray(0, sharedOffset), bytes.subarray(viewOffset, it.offset));
|
|
4496
4503
|
}
|
|
4497
4504
|
/**
|