Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
let msgpackState = { players: {} };
const fixedUnitId = nanoid(9);
for (let i=0; i<100; i++) {
const id = (i === 50) ? fixedUnitId : nanoid(9);
const name = "Player " + i;
const x = Math.floor(Math.random() * 200);
const y = Math.floor(Math.random() * 200);
state.players[ id ] = new Player(name, x, y);
msgpackState.players[id] = { name, x, y };
}
const firstStateEncoded = msgpack.encode(msgpackState);
let encoded = state.encode();
const decodedState = new State();
decodedState.decode(encoded);
console.log("(@colyseus/state) INITIAL STATE SIZE:", encoded.length);
console.log("(msgpack) INITIAL STATE SIZE:", firstStateEncoded.length);
console.log("");
{
// CHANGE X/Y OF A SINGLE ENTITY
const x = Math.floor(Math.random() * 200);
const y = Math.floor(Math.random() * 200);
state.players[fixedUnitId].x = x
state.players[fixedUnitId].y = y
msgpackState.players[fixedUnitId].x = x
// for (let id in msgpackState.players) {
// const x = Math.floor(Math.random() * 200);
// const y = Math.floor(Math.random() * 200);
// state.players[id].x = x
// state.players[id].y = y
// msgpackState.players[id].x = x
// msgpackState.players[id].y = y
// i++;
// }
// }
encoded = state.encode();
decodedState.decode(encoded);
console.log("(@colyseus/state) SUBSEQUENT PATCH:", encoded.length);
console.log("(msgpack) SUBSEQUENT PATCH:", fossildelta.create(firstStateEncoded, msgpack.encode(msgpackState)).length);
this.read = async (data: Buffer) => {
this.logger.info(`read() buffer.length: ${data.length}`);
const {header: {serialization}} = persistencePartsUtil.split(data);
const decryptedData = await encryptionAdapter.read(data);
if (serialization && serialization.type === "msgpack") {
this.logger.verbose(`"msgpack.decode" start`);
const decoded = msgpack.decode(decryptedData) as FsDb;
this.logger.verbose(`"msgpack.decode" end`);
return decoded;
}
const readableStream = bufferToStream(decryptedData);
return new Promise((resolve, reject) => {
this.logger.verbose(`"oboe" start`);
// TODO replace "oboe" with alternative library that doesn't block the Event Loop so heavily
// review the following libraries:
// - https://gitlab.com/philbooth/bfj
// - https://github.com/ibmruntimes/yieldable-json
// or consider moving parsing to a separate Worker/Process
oboe(readableStream)
.done((parsed) => {
attach(
writer: NodeJS.WritableStream,
reader: NodeJS.ReadableStream,
client: any
) {
this.writer = writer;
this.reader = reader;
this.client = client;
this.reader.on('end', () => {
this.emit('detach');
});
const asyncDecodeGenerator = decodeStream(this.reader as any, {
extensionCodec: this.extensionCodec,
});
// naively iterate async generator created via decodeStream.
// when runtime / polyfill allows replace to `for await (const val of asyncDecodeGenerator)`
// syntax instead.
const resolveGeneratorRecursively = (iter: AsyncGenerator) => {
iter.next().then(resolved => {
if (!resolved.done) {
this.parseMessage(resolved.value);
return resolveGeneratorRecursively(iter);
}
return Promise.resolve();
});
};
public async *messages(): AsyncIterableIterator<
OpenNewTabReply | StdOutMessage
> {
for await (const data of this.connection) {
if (!data) continue
// TODO: maybe throw an error??
if (typeof data === "string") continue
const messages = BinaryMessageFormat.parse(data)
for (const message of messages) {
const decoded = decode(message) as [string, Buffer]
const type = decoded[0]
const payload = decode(decoded[1])
switch (type) {
case "OpenNewTabReply":
yield OpenNewTabReply.fromJS(payload)
break
case "StdOutMessage": {
const stdOut = StdOutMessage.fromJS(payload)
stdOut.data = Array.from(
(payload as { Data: number[] })["Data"],
)
yield stdOut
break
}
public async *messages(): AsyncIterableIterator<
OpenNewTabReply | StdOutMessage
> {
for await (const data of this.connection) {
if (!data) continue
// TODO: maybe throw an error??
if (typeof data === "string") continue
const messages = BinaryMessageFormat.parse(data)
for (const message of messages) {
const decoded = decode(message) as [string, Buffer]
const type = decoded[0]
const payload = decode(decoded[1])
switch (type) {
case "OpenNewTabReply":
yield OpenNewTabReply.fromJS(payload)
break
case "StdOutMessage": {
const stdOut = StdOutMessage.fromJS(payload)
stdOut.data = Array.from(
(payload as { Data: number[] })["Data"],
)
yield stdOut
break
}
default:
const serializeCommand = (message: Messages): ArrayBuffer => {
const bytes = encode(message.toJSON())
const payload = encode([getName(message), bytes]).slice()
const data = BinaryMessageFormat.write(payload)
return data
}
const serializeCommand = (message: Messages): ArrayBuffer => {
const bytes = encode(message.toJSON())
const payload = encode([getName(message), bytes]).slice()
const data = BinaryMessageFormat.write(payload)
return data
}
private encodeToBuffer(value: unknown) {
const encoded = encode(value, { extensionCodec: this.extensionCodec });
return Buffer.from(encoded.buffer, encoded.byteOffset, encoded.byteLength);
}
send(resp: any, isError?: boolean): void {
if (this.sent) {
throw new Error(`Response to id ${this.requestId} already sent`);
}
const encoded = encode([
1,
this.requestId,
isError ? resp : null,
!isError ? resp : null,
]);
this.encoder.write(
Buffer.from(encoded.buffer, encoded.byteOffset, encoded.byteLength)
);
this.sent = true;
}
}