add compression to engine messages
This commit is contained in:
parent
d19da30f6d
commit
6708160cec
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "engine/utils/compatto"]
|
||||||
|
path = engine/utils/compatto
|
||||||
|
url = https://github.com/macarie/compatto
|
@ -1,5 +1,5 @@
|
|||||||
import type { Message, MessagePublisher } from '@engine/network';
|
import type { Message, MessagePublisher } from '@engine/network';
|
||||||
import { stringify } from '@engine/utils';
|
import { serialize } from '@engine/utils';
|
||||||
|
|
||||||
export class ClientSocketMessagePublisher implements MessagePublisher {
|
export class ClientSocketMessagePublisher implements MessagePublisher {
|
||||||
private socket: WebSocket;
|
private socket: WebSocket;
|
||||||
@ -17,7 +17,7 @@ export class ClientSocketMessagePublisher implements MessagePublisher {
|
|||||||
public publish() {
|
public publish() {
|
||||||
if (this.socket.readyState == WebSocket.OPEN) {
|
if (this.socket.readyState == WebSocket.OPEN) {
|
||||||
this.messages.forEach((message: Message) =>
|
this.messages.forEach((message: Message) =>
|
||||||
this.socket.send(stringify(message))
|
this.socket.send(serialize(message))
|
||||||
);
|
);
|
||||||
this.messages = [];
|
this.messages = [];
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,10 @@ export class ClientSocketMessageQueueProvider implements MessageQueueProvider {
|
|||||||
this.messages = [];
|
this.messages = [];
|
||||||
|
|
||||||
this.socket.addEventListener('message', (e) => {
|
this.socket.addEventListener('message', (e) => {
|
||||||
const messages = parse<Message[]>(e.data);
|
e.data.arrayBuffer().then((buffer) => {
|
||||||
this.messages = this.messages.concat(messages);
|
const messages = parse<Message[]>(new Uint8Array(buffer));
|
||||||
|
this.messages = this.messages.concat(messages);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
import { compatto } from './compatto';
|
||||||
|
import dictionary from './dictionary';
|
||||||
|
|
||||||
|
const { compress, decompress } = compatto({ dictionary });
|
||||||
|
|
||||||
const replacer = (_key: any, value: any) => {
|
const replacer = (_key: any, value: any) => {
|
||||||
if (value instanceof Map) {
|
if (value instanceof Map) {
|
||||||
return {
|
return {
|
||||||
@ -31,10 +36,17 @@ const reviver = (_key: any, value: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// "deterministic" stringify
|
// "deterministic" stringify
|
||||||
export const stringify = (obj: any) => {
|
|
||||||
|
export const stringify = (obj: any): string => {
|
||||||
return JSON.stringify(sortObj(obj), replacer);
|
return JSON.stringify(sortObj(obj), replacer);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parse = <T>(str: string) => {
|
export const serialize = (obj: any): Uint8Array => {
|
||||||
return JSON.parse(str, reviver) as unknown as T;
|
//return new Uint8Array(new TextEncoder().encode(stringify(obj)));
|
||||||
|
return compress(stringify(obj));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const parse = <T>(serialized: Uint8Array): T => {
|
||||||
|
//return JSON.parse(new TextDecoder().decode(serialized), reviver) as T;
|
||||||
|
return JSON.parse(decompress(serialized), reviver) as T;
|
||||||
};
|
};
|
||||||
|
1
engine/utils/compatto
Submodule
1
engine/utils/compatto
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 68628ac6f173f50b81cc2d83a75de176484b2c7f
|
56
engine/utils/dictionary.ts
Normal file
56
engine/utils/dictionary.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// basically a list of common strings between network components to help in compression
|
||||||
|
// can't be longer than 254 "words"
|
||||||
|
export default [
|
||||||
|
'{',
|
||||||
|
'}',
|
||||||
|
',',
|
||||||
|
'"',
|
||||||
|
"'",
|
||||||
|
',',
|
||||||
|
'1',
|
||||||
|
'2',
|
||||||
|
'3',
|
||||||
|
'4',
|
||||||
|
'5',
|
||||||
|
'6',
|
||||||
|
'7',
|
||||||
|
'8',
|
||||||
|
'9',
|
||||||
|
'0',
|
||||||
|
'.',
|
||||||
|
'Map',
|
||||||
|
'[',
|
||||||
|
']',
|
||||||
|
'BoundingBox',
|
||||||
|
'args',
|
||||||
|
'height',
|
||||||
|
'width',
|
||||||
|
'name',
|
||||||
|
'body',
|
||||||
|
'Velocity',
|
||||||
|
'Control',
|
||||||
|
'Component',
|
||||||
|
'NEW_ENTITIES',
|
||||||
|
'REMOVE_ENTITIES',
|
||||||
|
'UPDATE_ENTITIES',
|
||||||
|
'NEW_INPUT',
|
||||||
|
'REMOVE_INPUT',
|
||||||
|
'boundingBox',
|
||||||
|
'dTheta',
|
||||||
|
'id',
|
||||||
|
'Forces',
|
||||||
|
':',
|
||||||
|
'control',
|
||||||
|
'controllableBy',
|
||||||
|
'dimension',
|
||||||
|
'rotation',
|
||||||
|
'forces',
|
||||||
|
'velocity',
|
||||||
|
'center',
|
||||||
|
'dCartesian',
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
'"body":[{"args":{',
|
||||||
|
'controlVelocityComponent',
|
||||||
|
'"boundingBox":{"center":'
|
||||||
|
];
|
@ -1,7 +1,7 @@
|
|||||||
import { Message, MessagePublisher } from '@engine/network';
|
import { Message, MessagePublisher } from '@engine/network';
|
||||||
import { Server } from 'bun';
|
import { Server } from 'bun';
|
||||||
import { Constants } from '../constants';
|
import { Constants } from '../constants';
|
||||||
import { stringify } from '@engine/utils';
|
import { serialize } from '@engine/utils';
|
||||||
|
|
||||||
export class ServerSocketMessagePublisher implements MessagePublisher {
|
export class ServerSocketMessagePublisher implements MessagePublisher {
|
||||||
private server?: Server;
|
private server?: Server;
|
||||||
@ -23,7 +23,7 @@ export class ServerSocketMessagePublisher implements MessagePublisher {
|
|||||||
|
|
||||||
public publish() {
|
public publish() {
|
||||||
if (this.messages.length) {
|
if (this.messages.length) {
|
||||||
this.server?.publish(Constants.GAME_TOPIC, stringify(this.messages));
|
this.server?.publish(Constants.GAME_TOPIC, serialize(this.messages));
|
||||||
|
|
||||||
this.messages = [];
|
this.messages = [];
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,10 @@ import {
|
|||||||
Session,
|
Session,
|
||||||
SessionManager
|
SessionManager
|
||||||
} from './network';
|
} from './network';
|
||||||
import { parse } from '@engine/utils';
|
import { parse, serialize } from '@engine/utils';
|
||||||
import { Server, ServerWebSocket } from 'bun';
|
import { Server, ServerWebSocket } from 'bun';
|
||||||
import { Input } from '@engine/systems';
|
import { Input } from '@engine/systems';
|
||||||
import { Control, NetworkUpdateable } from '@engine/components';
|
import { Control, NetworkUpdateable } from '@engine/components';
|
||||||
import { stringify } from '@engine/utils';
|
|
||||||
|
|
||||||
export class GameServer {
|
export class GameServer {
|
||||||
private server?: Server;
|
private server?: Server;
|
||||||
@ -44,7 +43,8 @@ export class GameServer {
|
|||||||
websocket: {
|
websocket: {
|
||||||
open: (ws) => this.openWebsocket(ws),
|
open: (ws) => this.openWebsocket(ws),
|
||||||
message: (ws, msg) => {
|
message: (ws, msg) => {
|
||||||
if (typeof msg === 'string') this.websocketMessage(ws, msg);
|
if (typeof msg !== 'string')
|
||||||
|
this.websocketMessage(ws, new Uint8Array(msg));
|
||||||
},
|
},
|
||||||
close: (ws) => this.closeWebsocket(ws)
|
close: (ws) => this.closeWebsocket(ws)
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ export class GameServer {
|
|||||||
|
|
||||||
private websocketMessage(
|
private websocketMessage(
|
||||||
websocket: ServerWebSocket<SessionData>,
|
websocket: ServerWebSocket<SessionData>,
|
||||||
message: string
|
message: Uint8Array
|
||||||
) {
|
) {
|
||||||
const receivedMessage = parse<ServerMessage>(message);
|
const receivedMessage = parse<ServerMessage>(message);
|
||||||
receivedMessage.sessionData = websocket.data;
|
receivedMessage.sessionData = websocket.data;
|
||||||
@ -117,7 +117,7 @@ export class GameServer {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
websocket.sendText(stringify(addCurrentEntities));
|
websocket.sendBinary(serialize(addCurrentEntities));
|
||||||
|
|
||||||
const addNewPlayer: Message = {
|
const addNewPlayer: Message = {
|
||||||
type: MessageType.NEW_ENTITIES,
|
type: MessageType.NEW_ENTITIES,
|
||||||
|
Loading…
Reference in New Issue
Block a user