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 { stringify } from '@engine/utils';
|
||||
import { serialize } from '@engine/utils';
|
||||
|
||||
export class ClientSocketMessagePublisher implements MessagePublisher {
|
||||
private socket: WebSocket;
|
||||
@ -17,7 +17,7 @@ export class ClientSocketMessagePublisher implements MessagePublisher {
|
||||
public publish() {
|
||||
if (this.socket.readyState == WebSocket.OPEN) {
|
||||
this.messages.forEach((message: Message) =>
|
||||
this.socket.send(stringify(message))
|
||||
this.socket.send(serialize(message))
|
||||
);
|
||||
this.messages = [];
|
||||
}
|
||||
|
@ -10,9 +10,11 @@ export class ClientSocketMessageQueueProvider implements MessageQueueProvider {
|
||||
this.messages = [];
|
||||
|
||||
this.socket.addEventListener('message', (e) => {
|
||||
const messages = parse<Message[]>(e.data);
|
||||
e.data.arrayBuffer().then((buffer) => {
|
||||
const messages = parse<Message[]>(new Uint8Array(buffer));
|
||||
this.messages = this.messages.concat(messages);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public getNewMessages() {
|
||||
|
@ -1,3 +1,8 @@
|
||||
import { compatto } from './compatto';
|
||||
import dictionary from './dictionary';
|
||||
|
||||
const { compress, decompress } = compatto({ dictionary });
|
||||
|
||||
const replacer = (_key: any, value: any) => {
|
||||
if (value instanceof Map) {
|
||||
return {
|
||||
@ -31,10 +36,17 @@ const reviver = (_key: any, value: any) => {
|
||||
};
|
||||
|
||||
// "deterministic" stringify
|
||||
export const stringify = (obj: any) => {
|
||||
|
||||
export const stringify = (obj: any): string => {
|
||||
return JSON.stringify(sortObj(obj), replacer);
|
||||
};
|
||||
|
||||
export const parse = <T>(str: string) => {
|
||||
return JSON.parse(str, reviver) as unknown as T;
|
||||
export const serialize = (obj: any): Uint8Array => {
|
||||
//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 { Server } from 'bun';
|
||||
import { Constants } from '../constants';
|
||||
import { stringify } from '@engine/utils';
|
||||
import { serialize } from '@engine/utils';
|
||||
|
||||
export class ServerSocketMessagePublisher implements MessagePublisher {
|
||||
private server?: Server;
|
||||
@ -23,7 +23,7 @@ export class ServerSocketMessagePublisher implements MessagePublisher {
|
||||
|
||||
public publish() {
|
||||
if (this.messages.length) {
|
||||
this.server?.publish(Constants.GAME_TOPIC, stringify(this.messages));
|
||||
this.server?.publish(Constants.GAME_TOPIC, serialize(this.messages));
|
||||
|
||||
this.messages = [];
|
||||
}
|
||||
|
@ -10,11 +10,10 @@ import {
|
||||
Session,
|
||||
SessionManager
|
||||
} from './network';
|
||||
import { parse } from '@engine/utils';
|
||||
import { parse, serialize } from '@engine/utils';
|
||||
import { Server, ServerWebSocket } from 'bun';
|
||||
import { Input } from '@engine/systems';
|
||||
import { Control, NetworkUpdateable } from '@engine/components';
|
||||
import { stringify } from '@engine/utils';
|
||||
|
||||
export class GameServer {
|
||||
private server?: Server;
|
||||
@ -44,7 +43,8 @@ export class GameServer {
|
||||
websocket: {
|
||||
open: (ws) => this.openWebsocket(ws),
|
||||
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)
|
||||
}
|
||||
@ -57,7 +57,7 @@ export class GameServer {
|
||||
|
||||
private websocketMessage(
|
||||
websocket: ServerWebSocket<SessionData>,
|
||||
message: string
|
||||
message: Uint8Array
|
||||
) {
|
||||
const receivedMessage = parse<ServerMessage>(message);
|
||||
receivedMessage.sessionData = websocket.data;
|
||||
@ -117,7 +117,7 @@ export class GameServer {
|
||||
})
|
||||
}
|
||||
];
|
||||
websocket.sendText(stringify(addCurrentEntities));
|
||||
websocket.sendBinary(serialize(addCurrentEntities));
|
||||
|
||||
const addNewPlayer: Message = {
|
||||
type: MessageType.NEW_ENTITIES,
|
||||
|
Loading…
Reference in New Issue
Block a user