Solve serialization
This commit is contained in:
parent
ba8b1a29fd
commit
8e44dd3733
45 changed files with 242 additions and 201 deletions
|
|
@ -7,6 +7,7 @@
|
||||||
"start": "concurrently --kill-others \"webpack --mode development -w\" \"nodemon --legacy-watch dist/main.js\"",
|
"start": "concurrently --kill-others \"webpack --mode development -w\" \"nodemon --legacy-watch dist/main.js\"",
|
||||||
"lint": "eslint --fix \"src/**/*.ts\" && prettier --write \"src/**/*.ts\"",
|
"lint": "eslint --fix \"src/**/*.ts\" && prettier --write \"src/**/*.ts\"",
|
||||||
"build": "webpack --mode production",
|
"build": "webpack --mode production",
|
||||||
|
"try-build": "npm run build && node dist/main.js",
|
||||||
"initialize": "npm install"
|
"initialize": "npm install"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import {
|
||||||
applyArrayPlugins,
|
applyArrayPlugins,
|
||||||
Random,
|
Random,
|
||||||
TransportEvents,
|
TransportEvents,
|
||||||
deserializeCommand,
|
deserialize,
|
||||||
StepCommand,
|
StepCommand,
|
||||||
} from 'shared';
|
} from 'shared';
|
||||||
import './index.html';
|
import './index.html';
|
||||||
|
|
@ -23,7 +23,6 @@ applyArrayPlugins();
|
||||||
Random.seed = 42;
|
Random.seed = 42;
|
||||||
|
|
||||||
const objects = new PhysicalContainer();
|
const objects = new PhysicalContainer();
|
||||||
|
|
||||||
createDungeon(objects);
|
createDungeon(objects);
|
||||||
createDungeon(objects);
|
createDungeon(objects);
|
||||||
createDungeon(objects);
|
createDungeon(objects);
|
||||||
|
|
@ -59,8 +58,8 @@ app.get('/', function (req, res) {
|
||||||
io.on('connection', (socket: SocketIO.Socket) => {
|
io.on('connection', (socket: SocketIO.Socket) => {
|
||||||
socket.on(TransportEvents.PlayerJoining, () => {
|
socket.on(TransportEvents.PlayerJoining, () => {
|
||||||
const player = new Player(objects, socket);
|
const player = new Player(objects, socket);
|
||||||
socket.on(TransportEvents.PlayerToServer, (text: string) => {
|
socket.on(TransportEvents.PlayerToServer, (json: string) => {
|
||||||
const command = deserializeCommand(JSON.parse(text));
|
const command = deserialize(json);
|
||||||
player.sendCommand(command);
|
player.sendCommand(command);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import {
|
||||||
settings,
|
settings,
|
||||||
CommandExecutors,
|
CommandExecutors,
|
||||||
MoveActionCommand,
|
MoveActionCommand,
|
||||||
typeToBaseType,
|
serializable,
|
||||||
} from 'shared';
|
} from 'shared';
|
||||||
|
|
||||||
import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box';
|
import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box';
|
||||||
|
|
@ -15,7 +15,7 @@ import { CirclePhysical } from './circle-physical';
|
||||||
import { Physical } from '../physics/physical';
|
import { Physical } from '../physics/physical';
|
||||||
import { PhysicalContainer } from '../physics/containers/physical-container';
|
import { PhysicalContainer } from '../physics/containers/physical-container';
|
||||||
|
|
||||||
@typeToBaseType
|
@serializable(CharacterBase)
|
||||||
export class CharacterPhysical extends CharacterBase implements Physical {
|
export class CharacterPhysical extends CharacterBase implements Physical {
|
||||||
public readonly canCollide = true;
|
public readonly canCollide = true;
|
||||||
public readonly isInverted = false;
|
public readonly isInverted = false;
|
||||||
|
|
@ -166,9 +166,4 @@ export class CharacterPhysical extends CharacterBase implements Physical {
|
||||||
this.container.removeObject(this.leftFoot);
|
this.container.removeObject(this.leftFoot);
|
||||||
this.container.removeObject(this.rightFoot);
|
this.container.removeObject(this.rightFoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
|
||||||
const { type, id, head, leftFoot, rightFoot } = this;
|
|
||||||
return [type, id, head, leftFoot, rightFoot];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import {
|
||||||
clamp,
|
clamp,
|
||||||
CommandExecutors,
|
CommandExecutors,
|
||||||
GameObject,
|
GameObject,
|
||||||
|
serializable,
|
||||||
settings,
|
settings,
|
||||||
StepCommand,
|
StepCommand,
|
||||||
} from 'shared';
|
} from 'shared';
|
||||||
|
|
@ -14,6 +15,7 @@ import { BoundingBoxBase } from '../physics/bounding-boxes/bounding-box-base';
|
||||||
import { moveCircle } from '../physics/move-circle';
|
import { moveCircle } from '../physics/move-circle';
|
||||||
import { PhysicalContainer } from '../physics/containers/physical-container';
|
import { PhysicalContainer } from '../physics/containers/physical-container';
|
||||||
|
|
||||||
|
@serializable(Circle)
|
||||||
export class CirclePhysical implements Circle, Physical {
|
export class CirclePhysical implements Circle, Physical {
|
||||||
readonly isInverted = false;
|
readonly isInverted = false;
|
||||||
readonly canCollide = true;
|
readonly canCollide = true;
|
||||||
|
|
@ -154,8 +156,8 @@ export class CirclePhysical implements Circle, Physical {
|
||||||
return wasHit;
|
return wasHit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
public toArray(): Array<any> {
|
||||||
const { center, radius } = this;
|
const { center, radius } = this;
|
||||||
return { center, radius };
|
return [center, radius];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { vec2, vec3 } from 'gl-matrix';
|
import { vec2, vec3 } from 'gl-matrix';
|
||||||
import { LampBase, settings, id, typeToBaseType } from 'shared';
|
import { LampBase, settings, id, serializable } from 'shared';
|
||||||
|
|
||||||
import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box';
|
import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box';
|
||||||
|
|
||||||
import { Physical } from '../physics/physical';
|
import { Physical } from '../physics/physical';
|
||||||
|
|
||||||
@typeToBaseType
|
@serializable(LampBase)
|
||||||
export class LampPhysical extends LampBase implements Physical {
|
export class LampPhysical extends LampBase implements Physical {
|
||||||
public readonly canCollide = false;
|
public readonly canCollide = false;
|
||||||
public readonly isInverted = false;
|
public readonly isInverted = false;
|
||||||
|
|
@ -38,9 +38,4 @@ export class LampPhysical extends LampBase implements Physical {
|
||||||
public distance(_: vec2): number {
|
public distance(_: vec2): number {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
|
||||||
const { type, id, center, color, lightness } = this;
|
|
||||||
return [type, id, center, color, lightness];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { clamp01, mix, TunnelBase, id, typeToBaseType } from 'shared';
|
import { clamp01, mix, TunnelBase, id, serializable } from 'shared';
|
||||||
|
|
||||||
import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box';
|
import { ImmutableBoundingBox } from '../physics/bounding-boxes/immutable-bounding-box';
|
||||||
import { StaticPhysical } from '../physics/containers/static-physical-object';
|
import { StaticPhysical } from '../physics/containers/static-physical-object';
|
||||||
|
|
||||||
@typeToBaseType
|
@serializable(TunnelBase)
|
||||||
export class TunnelPhysical extends TunnelBase implements StaticPhysical {
|
export class TunnelPhysical extends TunnelBase implements StaticPhysical {
|
||||||
public readonly canCollide = true;
|
public readonly canCollide = true;
|
||||||
public readonly isInverted = true;
|
public readonly isInverted = true;
|
||||||
|
|
@ -45,9 +45,4 @@ export class TunnelPhysical extends TunnelBase implements StaticPhysical {
|
||||||
public get gameObject(): TunnelPhysical {
|
public get gameObject(): TunnelPhysical {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
|
||||||
const { type, id, from, to, fromRadius, toRadius } = this;
|
|
||||||
return [type, id, from, to, fromRadius, toRadius];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
CreatePlayerCommand,
|
CreatePlayerCommand,
|
||||||
DeleteObjectsCommand,
|
DeleteObjectsCommand,
|
||||||
MoveActionCommand,
|
MoveActionCommand,
|
||||||
|
serialize,
|
||||||
SetViewAreaActionCommand,
|
SetViewAreaActionCommand,
|
||||||
TransportEvents,
|
TransportEvents,
|
||||||
UpdateObjectsCommand,
|
UpdateObjectsCommand,
|
||||||
|
|
@ -16,7 +17,6 @@ import { CharacterPhysical } from '../objects/character-physical';
|
||||||
import { BoundingBox } from '../physics/bounding-boxes/bounding-box';
|
import { BoundingBox } from '../physics/bounding-boxes/bounding-box';
|
||||||
import { PhysicalContainer } from '../physics/containers/physical-container';
|
import { PhysicalContainer } from '../physics/containers/physical-container';
|
||||||
import { Physical } from '../physics/physical';
|
import { Physical } from '../physics/physical';
|
||||||
import { jsonSerialize } from '../serialize';
|
|
||||||
|
|
||||||
export class Player extends CommandReceiver {
|
export class Player extends CommandReceiver {
|
||||||
public isActive = true;
|
public isActive = true;
|
||||||
|
|
@ -50,7 +50,7 @@ export class Player extends CommandReceiver {
|
||||||
|
|
||||||
socket.emit(
|
socket.emit(
|
||||||
TransportEvents.ServerToPlayer,
|
TransportEvents.ServerToPlayer,
|
||||||
jsonSerialize(new CreatePlayerCommand(jsonSerialize(this.character)))
|
serialize(new CreatePlayerCommand(this.character))
|
||||||
);
|
);
|
||||||
|
|
||||||
this.sendObjects();
|
this.sendObjects();
|
||||||
|
|
@ -72,13 +72,12 @@ export class Player extends CommandReceiver {
|
||||||
const noLongerIntersecting = this.objectsPreviouslyInViewArea.filter(
|
const noLongerIntersecting = this.objectsPreviouslyInViewArea.filter(
|
||||||
(o) => !this.objectsInViewArea.includes(o)
|
(o) => !this.objectsInViewArea.includes(o)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.objectsPreviouslyInViewArea = this.objectsInViewArea;
|
this.objectsPreviouslyInViewArea = this.objectsInViewArea;
|
||||||
|
|
||||||
if (noLongerIntersecting.length > 0) {
|
if (noLongerIntersecting.length > 0) {
|
||||||
this.socket.emit(
|
this.socket.emit(
|
||||||
TransportEvents.ServerToPlayer,
|
TransportEvents.ServerToPlayer,
|
||||||
jsonSerialize(
|
serialize(
|
||||||
new DeleteObjectsCommand([
|
new DeleteObjectsCommand([
|
||||||
...new Set(noLongerIntersecting.map((p) => p.gameObject.id)),
|
...new Set(noLongerIntersecting.map((p) => p.gameObject.id)),
|
||||||
])
|
])
|
||||||
|
|
@ -89,24 +88,22 @@ export class Player extends CommandReceiver {
|
||||||
if (newlyIntersecting.length > 0) {
|
if (newlyIntersecting.length > 0) {
|
||||||
this.socket.emit(
|
this.socket.emit(
|
||||||
TransportEvents.ServerToPlayer,
|
TransportEvents.ServerToPlayer,
|
||||||
jsonSerialize(
|
serialize(
|
||||||
new CreateObjectsCommand(
|
new CreateObjectsCommand([
|
||||||
jsonSerialize([...new Set(newlyIntersecting.map((p) => p.gameObject))])
|
...new Set(newlyIntersecting.map((p) => p.gameObject)),
|
||||||
)
|
])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.socket.emit(
|
this.socket.emit(
|
||||||
TransportEvents.ServerToPlayer,
|
TransportEvents.ServerToPlayer,
|
||||||
jsonSerialize(
|
serialize(
|
||||||
new UpdateObjectsCommand(
|
new UpdateObjectsCommand([
|
||||||
jsonSerialize([
|
...new Set(
|
||||||
...new Set(
|
this.objectsInViewArea.filter((p) => p.canMove).map((p) => p.gameObject)
|
||||||
this.objectsInViewArea.filter((p) => p.canMove).map((p) => p.gameObject)
|
),
|
||||||
),
|
])
|
||||||
])
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
export const jsonSerialize = (o: any): string =>
|
|
||||||
JSON.stringify(o, (key, value) => (value?.toFixed ? Number(value.toFixed(3)) : value));
|
|
||||||
|
|
@ -32,29 +32,14 @@ module.exports = {
|
||||||
new TerserJSPlugin({
|
new TerserJSPlugin({
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
cache: true,
|
cache: true,
|
||||||
test: /\.ts$/i,
|
test: /\.ts$/,
|
||||||
terserOptions: {
|
|
||||||
ecma: 5,
|
|
||||||
warnings: true,
|
|
||||||
parse: {},
|
|
||||||
compress: { defaults: true },
|
|
||||||
mangle: true,
|
|
||||||
module: false,
|
|
||||||
output: null,
|
|
||||||
toplevel: true,
|
|
||||||
nameCache: null,
|
|
||||||
ie8: false,
|
|
||||||
keep_classnames: false,
|
|
||||||
keep_fnames: false,
|
|
||||||
safari10: false,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.html$/i,
|
test: /\.html$/,
|
||||||
use: {
|
use: {
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
query: {
|
query: {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
"start": "webpack-dev-server --mode development",
|
"start": "webpack-dev-server --mode development",
|
||||||
"lint": "eslint --fix \"src/**/*.ts\" && prettier --write \"src/**/*.ts\"",
|
"lint": "eslint --fix \"src/**/*.ts\" && prettier --write \"src/**/*.ts\"",
|
||||||
"build": "webpack --mode production && find dist -type f -not -name '*.html' | xargs rm",
|
"build": "webpack --mode production && find dist -type f -not -name '*.html' | xargs rm",
|
||||||
|
"try-build": "npm run build && cd dist && python3 -m http.server 8080",
|
||||||
"initialize": "npm install"
|
"initialize": "npm install"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Command, CommandReceiver, TransportEvents } from 'shared';
|
import { Command, CommandReceiver, serialize, TransportEvents } from 'shared';
|
||||||
|
|
||||||
export class CommandReceiverSocket extends CommandReceiver {
|
export class CommandReceiverSocket extends CommandReceiver {
|
||||||
constructor(private readonly socket: SocketIOClient.Socket) {
|
constructor(private readonly socket: SocketIOClient.Socket) {
|
||||||
|
|
@ -6,6 +6,6 @@ export class CommandReceiverSocket extends CommandReceiver {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected defaultCommandExecutor(command: Command) {
|
protected defaultCommandExecutor(command: Command) {
|
||||||
this.socket.emit(TransportEvents.PlayerToServer, JSON.stringify(command));
|
this.socket.emit(TransportEvents.PlayerToServer, serialize(command));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ import {
|
||||||
} from 'sdf-2d';
|
} from 'sdf-2d';
|
||||||
import {
|
import {
|
||||||
broadcastCommands,
|
broadcastCommands,
|
||||||
|
deserialize,
|
||||||
prettyPrint,
|
prettyPrint,
|
||||||
|
serialize,
|
||||||
settings,
|
settings,
|
||||||
SetViewAreaActionCommand,
|
SetViewAreaActionCommand,
|
||||||
StepCommand,
|
StepCommand,
|
||||||
|
|
@ -27,9 +29,13 @@ import { RenderCommand } from './commands/types/render';
|
||||||
import { Configuration } from './config/configuration';
|
import { Configuration } from './config/configuration';
|
||||||
import { DeltaTimeCalculator } from './helper/delta-time-calculator';
|
import { DeltaTimeCalculator } from './helper/delta-time-calculator';
|
||||||
import { rgb } from './helper/rgb';
|
import { rgb } from './helper/rgb';
|
||||||
|
import { CharacterView } from './objects/character-view';
|
||||||
|
import { TunnelView } from './objects/tunnel-view';
|
||||||
|
import { LampView } from './objects/lamp-view';
|
||||||
import { GameObjectContainer } from './objects/game-object-container';
|
import { GameObjectContainer } from './objects/game-object-container';
|
||||||
import { BlobShape } from './shapes/blob-shape';
|
import { BlobShape } from './shapes/blob-shape';
|
||||||
import { deserialize } from './transport/deserialize';
|
|
||||||
|
const a = [CharacterView, TunnelView, LampView];
|
||||||
|
|
||||||
export class Game {
|
export class Game {
|
||||||
public readonly gameObjects = new GameObjectContainer();
|
public readonly gameObjects = new GameObjectContainer();
|
||||||
|
|
@ -149,7 +155,7 @@ export class Game {
|
||||||
// todo: Should only send aspect ratio
|
// todo: Should only send aspect ratio
|
||||||
this.socket.emit(
|
this.socket.emit(
|
||||||
TransportEvents.PlayerToServer,
|
TransportEvents.PlayerToServer,
|
||||||
JSON.stringify(new SetViewAreaActionCommand(this.gameObjects.camera.viewArea))
|
serialize(new SetViewAreaActionCommand(this.gameObjects.camera.viewArea))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { CharacterBase, CommandExecutors } from 'shared';
|
import { CharacterBase, CommandExecutors, deserializable } from 'shared';
|
||||||
import { RenderCommand } from '../commands/types/render';
|
import { RenderCommand } from '../commands/types/render';
|
||||||
import { BlobShape } from '../shapes/blob-shape';
|
import { BlobShape } from '../shapes/blob-shape';
|
||||||
|
|
||||||
|
@deserializable(CharacterBase)
|
||||||
export class CharacterView extends CharacterBase {
|
export class CharacterView extends CharacterBase {
|
||||||
private shape = new BlobShape();
|
private shape = new BlobShape();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import {
|
||||||
StepCommand,
|
StepCommand,
|
||||||
UpdateObjectsCommand,
|
UpdateObjectsCommand,
|
||||||
} from 'shared';
|
} from 'shared';
|
||||||
import { deserialize, deserializeJsonArray } from '../transport/deserialize';
|
|
||||||
import { Camera } from './camera';
|
import { Camera } from './camera';
|
||||||
import { CharacterView } from './character-view';
|
import { CharacterView } from './character-view';
|
||||||
|
|
||||||
|
|
@ -21,7 +20,7 @@ export class GameObjectContainer extends CommandReceiver {
|
||||||
|
|
||||||
protected commandExecutors: CommandExecutors = {
|
protected commandExecutors: CommandExecutors = {
|
||||||
[CreatePlayerCommand.type]: (c: CreatePlayerCommand) => {
|
[CreatePlayerCommand.type]: (c: CreatePlayerCommand) => {
|
||||||
this.player = deserialize(c.serializedPlayer) as CharacterView;
|
this.player = c.character as CharacterView;
|
||||||
this.camera = new Camera();
|
this.camera = new Camera();
|
||||||
this.addObject(this.player);
|
this.addObject(this.player);
|
||||||
this.addObject(this.camera);
|
this.addObject(this.camera);
|
||||||
|
|
@ -34,13 +33,13 @@ export class GameObjectContainer extends CommandReceiver {
|
||||||
},
|
},
|
||||||
|
|
||||||
[CreateObjectsCommand.type]: (c: CreateObjectsCommand) =>
|
[CreateObjectsCommand.type]: (c: CreateObjectsCommand) =>
|
||||||
deserializeJsonArray(c.serializedObjects).forEach((o) => this.addObject(o)),
|
c.objects.forEach((o) => this.addObject(o)),
|
||||||
|
|
||||||
[DeleteObjectsCommand.type]: (c: DeleteObjectsCommand) =>
|
[DeleteObjectsCommand.type]: (c: DeleteObjectsCommand) =>
|
||||||
c.ids.forEach((id: Id) => this.objects.delete(id)),
|
c.ids.forEach((id: Id) => this.objects.delete(id)),
|
||||||
|
|
||||||
[UpdateObjectsCommand.type]: (c: UpdateObjectsCommand) =>
|
[UpdateObjectsCommand.type]: (c: UpdateObjectsCommand) =>
|
||||||
deserializeJsonArray(c.serializedObjects).forEach((o) => {
|
c.objects.forEach((o) => {
|
||||||
this.objects.delete(o.id);
|
this.objects.delete(o.id);
|
||||||
this.addObject(o);
|
this.addObject(o);
|
||||||
if (o.id === this.player.id) {
|
if (o.id === this.player.id) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { vec2, vec3 } from 'gl-matrix';
|
import { vec2, vec3 } from 'gl-matrix';
|
||||||
import { CircleLight } from 'sdf-2d';
|
import { CircleLight } from 'sdf-2d';
|
||||||
import { CommandExecutors, Id, LampBase } from 'shared';
|
import { CommandExecutors, deserializable, Id, LampBase } from 'shared';
|
||||||
import { RenderCommand } from '../commands/types/render';
|
import { RenderCommand } from '../commands/types/render';
|
||||||
|
|
||||||
|
@deserializable(LampBase)
|
||||||
export class LampView extends LampBase {
|
export class LampView extends LampBase {
|
||||||
private light: CircleLight;
|
private light: CircleLight;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { InvertedTunnel } from 'sdf-2d';
|
import { InvertedTunnel } from 'sdf-2d';
|
||||||
import { CommandExecutors, Id, TunnelBase } from 'shared';
|
import { CommandExecutors, deserializable, Id, TunnelBase } from 'shared';
|
||||||
import { RenderCommand } from '../commands/types/render';
|
import { RenderCommand } from '../commands/types/render';
|
||||||
|
|
||||||
|
@deserializable(TunnelBase)
|
||||||
export class TunnelView extends TunnelBase {
|
export class TunnelView extends TunnelBase {
|
||||||
private shape: InvertedTunnel;
|
private shape: InvertedTunnel;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
import {
|
|
||||||
CharacterBase,
|
|
||||||
commandConstructors,
|
|
||||||
GameObject,
|
|
||||||
LampBase,
|
|
||||||
TunnelBase,
|
|
||||||
} from 'shared';
|
|
||||||
import { CharacterView } from '../objects/character-view';
|
|
||||||
import { LampView } from '../objects/lamp-view';
|
|
||||||
import { TunnelView } from '../objects/tunnel-view';
|
|
||||||
|
|
||||||
const constructors: { [type: string]: new (...values: Array<any>) => GameObject } = {
|
|
||||||
[TunnelBase.type]: TunnelView,
|
|
||||||
[LampBase.type]: LampView,
|
|
||||||
[CharacterBase.type]: CharacterView,
|
|
||||||
...commandConstructors,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deserialize = (json: string): GameObject => {
|
|
||||||
const [type, ...values] = JSON.parse(json);
|
|
||||||
return new constructors[type](...values);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deserializeJsonArray = (json: string): Array<GameObject> => {
|
|
||||||
return (JSON.parse(json) as Array<any>).map(([type, ...values]) => {
|
|
||||||
return new constructors[type](...values);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
@ -10,6 +10,9 @@
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
"module": "es6",
|
"module": "es6",
|
||||||
"lib": ["es2015", "dom"]
|
"lib": [
|
||||||
|
"es2015",
|
||||||
|
"dom"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -31,28 +31,13 @@ module.exports = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
minimize: true,
|
minimize: false,
|
||||||
usedExports: true,
|
usedExports: true,
|
||||||
minimizer: [
|
minimizer: [
|
||||||
new TerserJSPlugin({
|
new TerserJSPlugin({
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
cache: true,
|
cache: true,
|
||||||
test: /\.ts$/i,
|
test: /\.ts$/,
|
||||||
terserOptions: {
|
|
||||||
ecma: 5,
|
|
||||||
warnings: true,
|
|
||||||
parse: {},
|
|
||||||
compress: { defaults: true },
|
|
||||||
mangle: true,
|
|
||||||
module: false,
|
|
||||||
output: null,
|
|
||||||
toplevel: true,
|
|
||||||
nameCache: null,
|
|
||||||
ie8: false,
|
|
||||||
keep_classnames: false,
|
|
||||||
keep_fnames: false,
|
|
||||||
safari10: false,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
new OptimizeCSSAssetsPlugin({}),
|
new OptimizeCSSAssetsPlugin({}),
|
||||||
],
|
],
|
||||||
|
|
@ -81,7 +66,7 @@ module.exports = {
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.ico$/i,
|
test: /\.ico$/,
|
||||||
use: {
|
use: {
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
query: {
|
query: {
|
||||||
|
|
@ -91,7 +76,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.scss$/i,
|
test: /\.scss$/,
|
||||||
use: [
|
use: [
|
||||||
MiniCssExtractPlugin.loader,
|
MiniCssExtractPlugin.loader,
|
||||||
'css-loader',
|
'css-loader',
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "lerna run --parallel start",
|
"start": "lerna run --parallel start",
|
||||||
|
"try-build": "lerna run --parallel try-build",
|
||||||
|
"build": "lerna run build",
|
||||||
"initialize": "lerna run initialize"
|
"initialize": "lerna run initialize"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
import { Typed } from '../transport/typed';
|
export abstract class Command {
|
||||||
|
public static get type(): string {
|
||||||
|
return (this as any).name;
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class Command extends Typed { }
|
public get type(): string {
|
||||||
|
return (this as any).constructor.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
|
import { GameObject } from '../../objects/game-object';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class CreateObjectsCommand extends Command {
|
export class CreateObjectsCommand extends Command {
|
||||||
public constructor(public readonly serializedObjects: string) {
|
public constructor(public readonly objects: Array<GameObject>) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
public toArray(): Array<any> {
|
||||||
return [this.type, this.serializedObjects];
|
return [this.objects];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
|
import { CharacterBase } from '../../objects/types/character-base';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class CreatePlayerCommand extends Command {
|
export class CreatePlayerCommand extends Command {
|
||||||
public constructor(public readonly serializedPlayer: string) {
|
public constructor(public readonly character: CharacterBase) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
public toArray(): Array<any> {
|
||||||
return [this.type, this.serializedPlayer];
|
return [this.character];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import { Id } from '../../transport/identity';
|
import { Id } from '../../transport/identity';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class DeleteObjectsCommand extends Command {
|
export class DeleteObjectsCommand extends Command {
|
||||||
public constructor(public readonly ids: Array<Id>) {
|
public constructor(public readonly ids: Array<Id>) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
public toArray(): Array<any> {
|
||||||
return [this.type, this.ids];
|
return [this.ids];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class MoveActionCommand extends Command {
|
export class MoveActionCommand extends Command {
|
||||||
public constructor(public readonly delta: vec2) {
|
public constructor(public readonly delta: vec2) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
public toArray(): Array<any> {
|
||||||
return [this.type, this.delta];
|
return [this.delta];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class PrimaryActionCommand extends Command {
|
export class PrimaryActionCommand extends Command {
|
||||||
public constructor(public readonly position: vec2) {
|
public constructor(public readonly position: vec2) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
public toArray(): Array<any> {
|
||||||
return [this.type, this.position];
|
return [this.position];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class SecondaryActionCommand extends Command {
|
export class SecondaryActionCommand extends Command {
|
||||||
public constructor(public readonly position: vec2) {
|
public constructor(public readonly position: vec2) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
public toArray(): Array<any> {
|
||||||
return [this.type, this.position];
|
return [this.position];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import { Rectangle } from '../../helper/rectangle';
|
import { Rectangle } from '../../helper/rectangle';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class SetViewAreaActionCommand extends Command {
|
export class SetViewAreaActionCommand extends Command {
|
||||||
public constructor(public readonly viewArea: Rectangle) {
|
public constructor(public readonly viewArea: Rectangle) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
public toArray(): Array<any> {
|
||||||
return [this.type, this.viewArea];
|
return [this.viewArea];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class TernaryActionCommand extends Command {
|
export class TernaryActionCommand extends Command {
|
||||||
public constructor(public readonly position: vec2) {
|
public constructor(public readonly position: vec2) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
public toArray(): Array<any> {
|
||||||
return [this.type, this.position];
|
return [this.position];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
|
import { GameObject } from '../../objects/game-object';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
import { Command } from '../command';
|
import { Command } from '../command';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class UpdateObjectsCommand extends Command {
|
export class UpdateObjectsCommand extends Command {
|
||||||
public constructor(public readonly serializedObjects: string) {
|
public constructor(public readonly objects: Array<GameObject>) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): any {
|
public toArray(): Array<any> {
|
||||||
return [this.type, this.serializedObjects];
|
return [this.objects];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
import { serializable } from '../transport/serializable/serializable';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class Circle {
|
export class Circle {
|
||||||
constructor(public center: vec2, public radius: number) {}
|
constructor(public center: vec2, public radius: number) { }
|
||||||
|
|
||||||
|
public toArray(): Array<any> {
|
||||||
|
return [this.center, this.radius];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
|
import { serializable } from '../transport/serializable/serializable';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export class Rectangle {
|
export class Rectangle {
|
||||||
constructor(public topLeft = vec2.create(), public size = vec2.create()) {}
|
constructor(public topLeft = vec2.create(), public size = vec2.create()) { }
|
||||||
|
|
||||||
|
public toArray(): Array<any> {
|
||||||
|
return [this.topLeft, this.size];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ export * from './helper/random';
|
||||||
export * from './helper/unique';
|
export * from './helper/unique';
|
||||||
export * from './helper/rotate-90-deg';
|
export * from './helper/rotate-90-deg';
|
||||||
export * from './objects/game-object';
|
export * from './objects/game-object';
|
||||||
export * from './objects/deserialize';
|
export * from './transport/serializable/deserialize';
|
||||||
|
export * from './transport/serializable/serialize';
|
||||||
|
export * from './transport/serializable/serializable';
|
||||||
export * from './objects/types/character-base';
|
export * from './objects/types/character-base';
|
||||||
export * from './objects/types/lamp-base';
|
export * from './objects/types/lamp-base';
|
||||||
export * from './objects/types/tunnel-base';
|
export * from './objects/types/tunnel-base';
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import { CreatePlayerCommand } from '../commands/types/create-player';
|
|
||||||
import { MoveActionCommand } from '../commands/types/move-action';
|
|
||||||
import { PrimaryActionCommand } from '../commands/types/primary-action';
|
|
||||||
import { SecondaryActionCommand } from '../commands/types/secondary-action';
|
|
||||||
import { SetViewAreaActionCommand } from '../commands/types/set-view-area-action';
|
|
||||||
import { TernaryActionCommand } from '../commands/types/ternary-action';
|
|
||||||
import { UpdateObjectsCommand } from '../commands/types/update-objects';
|
|
||||||
import { Command, CreateObjectsCommand, DeleteObjectsCommand } from '../main';
|
|
||||||
|
|
||||||
export const commandConstructors: {
|
|
||||||
[type: string]: new (...values: Array<any>) => any;
|
|
||||||
} = {
|
|
||||||
[CreateObjectsCommand.type]: CreateObjectsCommand,
|
|
||||||
[DeleteObjectsCommand.type]: DeleteObjectsCommand,
|
|
||||||
[CreatePlayerCommand.type]: CreatePlayerCommand,
|
|
||||||
[MoveActionCommand.type]: MoveActionCommand,
|
|
||||||
[PrimaryActionCommand.type]: PrimaryActionCommand,
|
|
||||||
[SecondaryActionCommand.type]: SecondaryActionCommand,
|
|
||||||
[TernaryActionCommand.type]: TernaryActionCommand,
|
|
||||||
[SetViewAreaActionCommand.type]: SetViewAreaActionCommand,
|
|
||||||
[UpdateObjectsCommand.type]: UpdateObjectsCommand,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deserializeCommand = ([type, ...values]: [string, Array<any>]): Command => {
|
|
||||||
return new commandConstructors[type](...values);
|
|
||||||
};
|
|
||||||
|
|
@ -2,14 +2,6 @@ import { CommandReceiver } from '../commands/command-receiver';
|
||||||
import { Id } from '../transport/identity';
|
import { Id } from '../transport/identity';
|
||||||
|
|
||||||
export abstract class GameObject extends CommandReceiver {
|
export abstract class GameObject extends CommandReceiver {
|
||||||
public static get type(): string {
|
|
||||||
return (this as any).name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get type(): string {
|
|
||||||
return (this as any).constructor.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(public readonly id: Id) {
|
constructor(public readonly id: Id) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
import { Circle } from '../../helper/circle';
|
import { Circle } from '../../helper/circle';
|
||||||
import { Id } from '../../main';
|
import { Id } from '../../transport/identity';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
import { GameObject } from '../game-object';
|
import { GameObject } from '../game-object';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export abstract class CharacterBase extends GameObject {
|
export abstract class CharacterBase extends GameObject {
|
||||||
constructor(
|
constructor(
|
||||||
id: Id,
|
id: Id,
|
||||||
|
|
@ -11,4 +13,9 @@ export abstract class CharacterBase extends GameObject {
|
||||||
) {
|
) {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public toArray(): Array<any> {
|
||||||
|
const { id, head, leftFoot, rightFoot } = this as any;
|
||||||
|
return [id, head, leftFoot, rightFoot];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
import { vec2, vec3 } from 'gl-matrix';
|
import { vec2, vec3 } from 'gl-matrix';
|
||||||
import { Id } from '../../main';
|
import { Id, serializable } from '../../main';
|
||||||
import { GameObject } from '../game-object';
|
import { GameObject } from '../game-object';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export abstract class LampBase extends GameObject {
|
export abstract class LampBase extends GameObject {
|
||||||
constructor(id: Id, public center: vec2, public color: vec3, public lightness: number) {
|
constructor(id: Id, public center: vec2, public color: vec3, public lightness: number) {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public toArray(): Array<any> {
|
||||||
|
const { id, center, color, lightness } = this as any;
|
||||||
|
return [id, center, color, lightness];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { GameObject, Id } from '../../main';
|
import { Id } from '../../transport/identity';
|
||||||
|
import { serializable } from '../../transport/serializable/serializable';
|
||||||
|
import { GameObject } from '../game-object';
|
||||||
|
|
||||||
|
@serializable()
|
||||||
export abstract class TunnelBase extends GameObject {
|
export abstract class TunnelBase extends GameObject {
|
||||||
constructor(
|
constructor(
|
||||||
id: Id,
|
id: Id,
|
||||||
|
|
@ -11,4 +14,9 @@ export abstract class TunnelBase extends GameObject {
|
||||||
) {
|
) {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public toArray(): Array<any> {
|
||||||
|
const { id, from, to, fromRadius, toRadius } = this as any;
|
||||||
|
return [id, from, to, fromRadius, toRadius];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
shared/src/transport/serializable/deserialize.ts
Normal file
13
shared/src/transport/serializable/deserialize.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { serializableClasses } from './serializable';
|
||||||
|
|
||||||
|
export const deserialize = (json: string): any => {
|
||||||
|
return JSON.parse(json, (k, v) => {
|
||||||
|
const possibleType = v[0];
|
||||||
|
const overridableConstructor = serializableClasses.get(possibleType);
|
||||||
|
if (overridableConstructor) {
|
||||||
|
const [_, ...values] = v;
|
||||||
|
return new overridableConstructor.constructor(...values);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
};
|
||||||
58
shared/src/transport/serializable/serializable.ts
Normal file
58
shared/src/transport/serializable/serializable.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
export const serializableClasses = new Map<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
constructor: any;
|
||||||
|
overriden: boolean;
|
||||||
|
}
|
||||||
|
>();
|
||||||
|
|
||||||
|
export const serializable = (serializableType?) => {
|
||||||
|
return (type): any => {
|
||||||
|
const actualType = serializableType
|
||||||
|
? Object.getPrototypeOf((serializableType as any).prototype).constructor
|
||||||
|
: type;
|
||||||
|
|
||||||
|
const typeName = actualType.name;
|
||||||
|
|
||||||
|
const overridableConstructor = serializableClasses.get(typeName);
|
||||||
|
if (!overridableConstructor) {
|
||||||
|
serializableClasses.set(typeName, {
|
||||||
|
constructor: actualType,
|
||||||
|
overriden: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(actualType.prototype, 'toArray')) {
|
||||||
|
throw new Error(
|
||||||
|
`Class ${typeName} must define a toArray returning an array containing the arguments for its constructor.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return class extends type {
|
||||||
|
public get type(): string {
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static get type(): string {
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deserializable = (fromType) => {
|
||||||
|
return (type): any => {
|
||||||
|
const overridableConstructor = serializableClasses.get(fromType.name);
|
||||||
|
if (!overridableConstructor || !overridableConstructor.overriden) {
|
||||||
|
serializableClasses.set(fromType.name, {
|
||||||
|
constructor: type,
|
||||||
|
overriden: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
`Constructor ${fromType} already overriden, cannot override again with ${type}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
};
|
||||||
|
};
|
||||||
10
shared/src/transport/serializable/serialize.ts
Normal file
10
shared/src/transport/serializable/serialize.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
export const serialize = (object): string => {
|
||||||
|
const result = JSON.stringify(object, (key, value) => {
|
||||||
|
if (value?.type) {
|
||||||
|
return [value.type, ...value.toArray()];
|
||||||
|
}
|
||||||
|
return value?.toFixed ? Number(value.toFixed(3)) : value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
export abstract class Typed {
|
|
||||||
public static get type(): string {
|
|
||||||
return (this as any).name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get type(): string {
|
|
||||||
return (this as any).constructor.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -10,6 +10,9 @@
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
"module": "es6",
|
"module": "es6",
|
||||||
"lib": ["es2015", "dom"]
|
"lib": [
|
||||||
|
"es2015",
|
||||||
|
"dom"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue