multyx
Version:
Framework designed to simplify the creation of multiplayer browser games by addressing the complexities of managing server-client communication, shared state, and input handling
143 lines (131 loc) • 3.85 kB
text/typescript
import { RawObject } from "../types";
export interface EditUpdate {
team: boolean;
path: string[];
value: any;
instruction: 'edit';
}
export interface SelfUpdate {
instruction: 'self';
property: 'controller' | 'uuid' | 'constraint' | 'space';
data: any;
}
export interface InputUpdate {
instruction: 'input';
input: string;
data: any;
}
export interface ResponseUpdate {
instruction: 'resp';
name: string;
response: any;
}
export interface ConnectionUpdate {
instruction: 'conn';
uuid: string;
publicData: RawObject;
}
export interface DisconnectUpdate {
instruction: 'dcon';
clientUUID: string;
}
export interface InitializeUpdate {
instruction: 'init';
client: RawObject;
tps: number;
constraintTable: RawObject;
clients: RawObject;
teams: RawObject;
space: string;
}
/**
* Compresses update into a string
* [instruction][specifier]:[data]
* @param update
* @returns Compressed update
*/
export function CompressUpdate(update: Update) {
let code, pieces;
if(update.instruction == 'edit') {
code = update.team ? '1' : '0';
pieces = [
update.path.join('.'),
JSON.stringify(update.value)
];
}
if(update.instruction == 'self') {
if(update.property == 'controller') code = '2';
else if(update.property == 'uuid') code = '3';
else if(update.property == 'space') code = '9';
else code = '4';
pieces = [
JSON.stringify(update.data)
];
}
if(update.instruction == 'resp') {
code = '5';
pieces = [
update.name,
JSON.stringify(update.response)
];
}
if(update.instruction == 'conn') {
code = '6';
pieces = [
update.uuid,
JSON.stringify(update.publicData)
];
}
if(update.instruction == 'dcon') {
code = '7';
pieces = [
update.clientUUID
];
}
if(update.instruction == 'init') {
code = '8';
pieces = [
JSON.stringify(update.client),
update.tps.toString(),
JSON.stringify(update.constraintTable),
JSON.stringify(update.clients),
JSON.stringify(update.teams),
JSON.stringify(update.space)
];
};
if(!pieces) return '';
let compressed = code;
for(let i = 0; i < pieces.length; i++) {
if(pieces[i] === undefined) pieces[i] = 'undefined';
compressed += pieces[i].replace(/;/g, ';_');
if(i < pieces.length - 1) compressed += ';,';
}
return compressed;
}
export function UncompressUpdate(str: string) {
try {
const [target, ...escapedData] = str.split(/;,/);
const instruction = target[0];
const specifier = target.slice(1).replace(/;_/g, ';');
const data = escapedData.map(d => d.replace(/;_/g, ';')).map(d => d == "undefined" ? undefined : JSON.parse(d));
if(instruction == '0') return {
instruction: 'edit',
team: false,
path: specifier.split('.'),
value: data[0]
} as EditUpdate;
if(instruction == '1') return {
instruction: 'input',
input: specifier,
data: data[0]
} as InputUpdate;
if(instruction == '2') return {
instruction: 'resp',
name: specifier,
response: data[0]
} as ResponseUpdate;
} catch {
return null;
}
}
export type Update = EditUpdate | InputUpdate | SelfUpdate | ResponseUpdate | InitializeUpdate | ConnectionUpdate | DisconnectUpdate;