flow: to synchronized
This commit is contained in:
parent
688820786d
commit
21ae93f1cc
|
@ -8,8 +8,8 @@ import {
|
|||
merge,
|
||||
mergeDiff,
|
||||
} from '@avocado/core';
|
||||
import {SynchronizedMixin} from '@avocado/net';
|
||||
import {Resource} from '@avocado/resource';
|
||||
import {Synchronized} from '@avocado/state';
|
||||
|
||||
import {EntityCreatePacket} from './packets/entity-create.packet';
|
||||
import {hasTrait, lookupTrait} from './trait/registry';
|
||||
|
@ -83,7 +83,7 @@ function enumerateTraitAccessorKeys(prototype) {
|
|||
|
||||
const decorate = compose(
|
||||
EventEmitter,
|
||||
Synchronized,
|
||||
SynchronizedMixin,
|
||||
);
|
||||
|
||||
let numericUid = 1;
|
|
@ -1,4 +1,4 @@
|
|||
export {Entity} from './entity.resource';
|
||||
export {Entity} from './entity.synchronized';
|
||||
|
||||
export {EntityCreatePacket} from './packets/entity-create.packet';
|
||||
export {EntityRemovePacket} from './packets/entity-remove.packet';
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import {compose, EventEmitter} from '@avocado/core';
|
||||
import {QuadTree, Rectangle, Vector} from '@avocado/math';
|
||||
import {Synchronized} from '@avocado/state';
|
||||
|
||||
import {EntityCreatePacket} from '../packets/entity-create.packet';
|
||||
import {EntityRemovePacket} from '../packets/entity-remove.packet';
|
||||
import {Entity} from '../entity.resource';
|
||||
import {Entity} from '../entity.synchronized';
|
||||
|
||||
const decorate = compose(
|
||||
EventEmitter,
|
||||
Synchronized,
|
||||
);
|
||||
|
||||
export class EntityList extends decorate(class {}) {
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import {compose, merge, mergeDiff, Property} from '@avocado/core';
|
||||
import {Vector} from '@avocado/math';
|
||||
import {Synchronized} from '@avocado/state';
|
||||
|
||||
const decorate = compose(
|
||||
Synchronized,
|
||||
);
|
||||
|
||||
export class Trait extends decorate(class {}) {
|
||||
|
|
|
@ -7,3 +7,17 @@ export {
|
|||
registerPacket,
|
||||
SocketIoParser,
|
||||
} from './packet';
|
||||
|
||||
export {
|
||||
allSynchronizeds,
|
||||
ClientSynchronizer,
|
||||
idFromSynchronized,
|
||||
registerSynchronized,
|
||||
ServerSynchronizer,
|
||||
SynchronizedMixin,
|
||||
SynchronizedPacket,
|
||||
SynchronizedCreatePacket,
|
||||
SynchronizedDestroyPacket,
|
||||
SynchronizedUpdatePacket,
|
||||
synchronizedFromId,
|
||||
} from './s13n';
|
||||
|
|
58
packages/net/s13n/client.js
Normal file
58
packages/net/s13n/client.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
import {idFromSynchronized, synchronizedFromId} from './registry';
|
||||
|
||||
import {SynchronizedCreatePacket} from './synchronized-create.packet';
|
||||
import {SynchronizedDestroyPacket} from './synchronized-destroy.packet';
|
||||
import {SynchronizedUpdatePacket} from './synchronized-update.packet';
|
||||
|
||||
export class ClientSynchronizer {
|
||||
|
||||
constructor() {
|
||||
this._synchronized = {};
|
||||
}
|
||||
|
||||
acceptPackets(packets) {
|
||||
for (let i = 0; i < packets.length; i++) {
|
||||
const packet = packets[i];
|
||||
if ((packet instanceof SynchronizedCreatePacket)) {
|
||||
const json = packet.data.spec;
|
||||
const {id, type} = packet.data.synchronized;
|
||||
const Synchronized = synchronizedFromId(type);
|
||||
if (!(type in this._synchronized)) {
|
||||
this._synchronized[type] = {};
|
||||
}
|
||||
if (this._synchronized[type][id]) {
|
||||
this._synchronized[type][id].fromJSON(json);
|
||||
}
|
||||
else {
|
||||
this._synchronized[type][id] = new Synchronized(json);
|
||||
}
|
||||
}
|
||||
else if ((packet instanceof SynchronizedUpdatePacket)) {
|
||||
const {
|
||||
synchronized: {id, type},
|
||||
} = packet.data;
|
||||
this._synchronized[type][id].acceptPacket(packet);
|
||||
}
|
||||
else if ((packet instanceof SynchronizedDestroyPacket)) {
|
||||
const {
|
||||
synchronized: {id, type},
|
||||
} = packet.data;
|
||||
this._synchronized[type][id].destroy();
|
||||
this._synchronized[type][id] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addSynchronized(synchronized) {
|
||||
const type = idFromSynchronized(synchronized.constructor);
|
||||
if (!(type in this._synchronized)) {
|
||||
this._synchronized[type] = new Map();
|
||||
}
|
||||
const synchronizationId = synchronized.synchronizationId();
|
||||
if (this._synchronized[type].has(synchronizationId)) {
|
||||
return;
|
||||
}
|
||||
this._synchronized[type][synchronizationId] = synchronized;
|
||||
}
|
||||
|
||||
}
|
16
packages/net/s13n/index.js
Normal file
16
packages/net/s13n/index.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
export {
|
||||
allSynchronizeds,
|
||||
idFromSynchronized,
|
||||
synchronizedFromId,
|
||||
registerSynchronized,
|
||||
} from './registry';
|
||||
|
||||
export {ClientSynchronizer} from './client';
|
||||
export {ServerSynchronizer} from './server';
|
||||
|
||||
export {SynchronizedMixin} from './synchronized'
|
||||
|
||||
export {SynchronizedPacket} from './synchronized.packet';
|
||||
export {SynchronizedCreatePacket} from './synchronized-create.packet';
|
||||
export {SynchronizedDestroyPacket} from './synchronized-destroy.packet';
|
||||
export {SynchronizedUpdatePacket} from './synchronized-update.packet';
|
21
packages/net/s13n/registry.js
Normal file
21
packages/net/s13n/registry.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
let synchronizedId = 0;
|
||||
const synchronizedToIdMap = new Map();
|
||||
const idToSynchronizedMap = new Map();
|
||||
export function allSynchronizeds() {
|
||||
return Array.from(idToSynchronizedMap.values());
|
||||
}
|
||||
export function idFromSynchronized(Synchronized) {
|
||||
return synchronizedToIdMap.get(Synchronized);
|
||||
}
|
||||
export function synchronizedFromId(id) {
|
||||
return idToSynchronizedMap.get(id);
|
||||
}
|
||||
export function registerSynchronized(Synchronized) {
|
||||
if (synchronizedToIdMap.has(Synchronized)) {
|
||||
return;
|
||||
}
|
||||
const id = synchronizedId++;
|
||||
synchronizedToIdMap.set(Synchronized, id);
|
||||
idToSynchronizedMap.set(id, Synchronized);
|
||||
return id;
|
||||
}
|
93
packages/net/s13n/server.js
Normal file
93
packages/net/s13n/server.js
Normal file
|
@ -0,0 +1,93 @@
|
|||
import {idFromSynchronized, synchronizedFromId} from './registry';
|
||||
|
||||
import {SynchronizedCreatePacket} from './synchronized-create.packet';
|
||||
import {SynchronizedDestroyPacket} from './synchronized-destroy.packet';
|
||||
|
||||
export class ServerSynchronizer {
|
||||
|
||||
constructor() {
|
||||
this._added = [];
|
||||
this._removed = [];
|
||||
this._synchronized = {};
|
||||
this._synchronizedFlat = [];
|
||||
}
|
||||
|
||||
addSynchronized(synchronized) {
|
||||
if (this.hasSynchronized(synchronized)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this._added.push(synchronized);
|
||||
}
|
||||
const type = idFromSynchronized(synchronized.constructor);
|
||||
if (!(type in this._synchronized)) {
|
||||
this._synchronized[type] = new Map();
|
||||
}
|
||||
this._synchronizedFlat.push(synchronized);
|
||||
const synchronizationId = synchronized.synchronizationId();
|
||||
this._synchronized[type].set(synchronizationId, synchronized);
|
||||
}
|
||||
|
||||
destroy() {}
|
||||
|
||||
hasSynchronized(synchronized) {
|
||||
return -1 !== this._synchronizedFlat.indexOf(synchronized);
|
||||
}
|
||||
|
||||
removeSynchronized(synchronized) {
|
||||
if (!this.hasSynchronized(synchronized)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this._removed.push(synchronized);
|
||||
}
|
||||
const index = this._synchronizedFlat.indexOf(synchronized);
|
||||
this._synchronizedFlat.splice(index, 1);
|
||||
const type = idFromSynchronized(synchronized.constructor);
|
||||
const synchronizationId = synchronized.synchronizationId();
|
||||
this._synchronized[type].delete(synchronizationId);
|
||||
}
|
||||
|
||||
packetsFor(informed) {
|
||||
const payload = [];
|
||||
for (let i = 0; i < this._synchronizedFlat.length; i++) {
|
||||
const synchronized = this._synchronizedFlat[i];
|
||||
const id = synchronized.synchronizationId();
|
||||
const type = idFromSynchronized(synchronized.constructor);
|
||||
if (-1 !== this._added.indexOf(synchronized)) {
|
||||
const packet = new SynchronizedCreatePacket({
|
||||
synchronized: {
|
||||
id,
|
||||
type,
|
||||
},
|
||||
spec: synchronized.toJSON(),
|
||||
});
|
||||
payload.push(packet);
|
||||
}
|
||||
else if (-1 !== this._removed.indexOf(synchronized)) {
|
||||
const packet = new SynchronizedDestroyPacket({
|
||||
synchronized: {
|
||||
id,
|
||||
type,
|
||||
},
|
||||
});
|
||||
payload.push(packet);
|
||||
}
|
||||
else {
|
||||
const packets = synchronized.packetsFor(informed);
|
||||
for (let j = 0; j < packets.length; j++) {
|
||||
const packet = packets[j];
|
||||
packet.data.synchronized = {
|
||||
id,
|
||||
type,
|
||||
};
|
||||
payload.push(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._added = [];
|
||||
this._removed = [];
|
||||
return payload;
|
||||
}
|
||||
|
||||
}
|
30
packages/net/s13n/synchronized-create.packet.js
Normal file
30
packages/net/s13n/synchronized-create.packet.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
import msgpack from 'msgpack-lite';
|
||||
|
||||
import {SynchronizedPacket} from './synchronized.packet';
|
||||
|
||||
export class SynchronizedCreatePacket extends SynchronizedPacket {
|
||||
|
||||
static pack(packet) {
|
||||
const data = packet.data[1];
|
||||
data.spec = msgpack.encode(data.spec);
|
||||
return super.pack(packet);
|
||||
}
|
||||
|
||||
static get schema() {
|
||||
const superSchema = super.schema;
|
||||
return {
|
||||
...superSchema,
|
||||
data: {
|
||||
...superSchema.data,
|
||||
spec: 'buffer',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static unpack(packet) {
|
||||
const data = super.unpack(packet);
|
||||
data.spec = msgpack.decode(data.spec);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
4
packages/net/s13n/synchronized-destroy.packet.js
Normal file
4
packages/net/s13n/synchronized-destroy.packet.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import {SynchronizedPacket} from './synchronized.packet';
|
||||
|
||||
export class SynchronizedDestroyPacket extends SynchronizedPacket {
|
||||
}
|
4
packages/net/s13n/synchronized-update.packet.js
Normal file
4
packages/net/s13n/synchronized-update.packet.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import {SynchronizedPacket} from './synchronized.packet';
|
||||
|
||||
export class SynchronizedUpdatePacket extends SynchronizedPacket {
|
||||
}
|
|
@ -2,8 +2,8 @@ export function SynchronizedMixin(Superclass) {
|
|||
|
||||
return class Synchronized extends Superclass {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this._idempotentPackets = [];
|
||||
}
|
||||
|
||||
|
@ -11,15 +11,19 @@ export function SynchronizedMixin(Superclass) {
|
|||
this._idempotentPackets = [];
|
||||
}
|
||||
|
||||
destroy() {}
|
||||
|
||||
packets(informed) {}
|
||||
|
||||
packetsAreIdempotent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
packets(informed) {
|
||||
packetsFor(informed) {
|
||||
if (this._idempotentPackets.length > 0) {
|
||||
return this._idempotentPackets;
|
||||
}
|
||||
let packets = this.packetsForTick(informed);
|
||||
let packets = this.packets(informed);
|
||||
if (!packets) {
|
||||
return [];
|
||||
}
|
||||
|
@ -30,7 +34,9 @@ export function SynchronizedMixin(Superclass) {
|
|||
return packets;
|
||||
}
|
||||
|
||||
packetsForTick(informed) {}
|
||||
synchronizationId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
17
packages/net/s13n/synchronized.packet.js
Normal file
17
packages/net/s13n/synchronized.packet.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import {Packet} from '@avocado/net';
|
||||
|
||||
export class SynchronizedPacket extends Packet {
|
||||
|
||||
static get schema() {
|
||||
return {
|
||||
...super.schema,
|
||||
data: {
|
||||
synchronized: {
|
||||
type: 'uint8',
|
||||
id: 'uint32',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +1,2 @@
|
|||
export {
|
||||
allResources,
|
||||
idFromResource,
|
||||
resourceFromId,
|
||||
registerResource,
|
||||
} from './registry';
|
||||
export {Resource} from './resource';
|
||||
export {ResourceRegistry, globalRegistry} from './store';
|
||||
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
import {Packet} from '@avocado/net';
|
||||
|
||||
export class ResourcePacket extends Packet {
|
||||
|
||||
static get schema() {
|
||||
return {
|
||||
...super.schema,
|
||||
resourceType: 'string',
|
||||
uuid: 'string',
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
let resourceId = 0;
|
||||
const resourceToIdMap = new Map();
|
||||
const idToResourceMap = new Map();
|
||||
export function allResources() {
|
||||
return Array.from(idToResourceMap.values());
|
||||
}
|
||||
export function idFromResource(Resource) {
|
||||
return resourceToIdMap.get(Resource);
|
||||
}
|
||||
export function resourceFromId(id) {
|
||||
return idToResourceMap.get(id);
|
||||
}
|
||||
export function registerResource(Resource) {
|
||||
if (resourceToIdMap.has(Resource)) {
|
||||
return;
|
||||
}
|
||||
const id = resourceId++;
|
||||
resourceToIdMap.set(Resource, id);
|
||||
idToResourceMap.set(id, Resource);
|
||||
return id;
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
export {Synchronized} from './synchronized';
|
||||
export {Synchronizer} from './synchronizer';
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"name": "@avocado/state",
|
||||
"version": "1.0.4",
|
||||
"main": "index.js",
|
||||
"author": "cha0s",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immutable": "4.0.0-rc.12",
|
||||
"msgpack-lite": "0.1.26"
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
export function Synchronized(Superclass) {
|
||||
return class Synchronized extends Superclass {
|
||||
|
||||
acceptPacket(packet) {}
|
||||
|
||||
packetsForUpdate(force = false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
export class Synchronizer {
|
||||
|
||||
constructor(children) {
|
||||
this.children = children;
|
||||
this.childrenPacketsForUpdate = this.children.map((child) => {
|
||||
return child.packetsForUpdate.bind(child);
|
||||
});
|
||||
}
|
||||
|
||||
acceptPacket(packet) {
|
||||
for (let i = 0; i < this.children.length; i++) {
|
||||
this.children[i].acceptPacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
addChild(child) {
|
||||
this.children.push(child);
|
||||
this.childrenPacketsForUpdate.push(child.packetsForUpdate.bind(child));
|
||||
}
|
||||
|
||||
packetsForUpdate(force = false) {
|
||||
const packetsForUpdate = [];
|
||||
for (let i = 0; i < this.childrenPacketsForUpdate.length; i++) {
|
||||
const childPacketsForUpdate = this.childrenPacketsForUpdate[i](force);
|
||||
for (let j = 0; j < childPacketsForUpdate.length; j++) {
|
||||
packetsForUpdate.push(childPacketsForUpdate[j]);
|
||||
}
|
||||
}
|
||||
return packetsForUpdate;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
export {Camera} from './camera';
|
||||
export {Layer} from './layer';
|
||||
export {LayerView} from './layer-view';
|
||||
export {Room} from './room.resource';
|
||||
export {Room} from './room.synchronized';
|
||||
export {RoomView} from './room-view';
|
||||
export {TilesRenderer} from './tiles-renderer';
|
||||
export {Tiles} from './tiles';
|
||||
|
|
|
@ -2,7 +2,6 @@ import {compose, EventEmitter, Property} from '@avocado/core';
|
|||
import {Entity, EntityCreatePacket, EntityList} from '@avocado/entity';
|
||||
import {Vector} from '@avocado/math';
|
||||
import {ShapeList} from '@avocado/physics';
|
||||
import {Synchronized} from '@avocado/state';
|
||||
|
||||
import {Tiles} from './tiles';
|
||||
import {Tileset} from './tileset';
|
||||
|
@ -20,7 +19,6 @@ const decorate = compose(
|
|||
Property('world', {
|
||||
track: true,
|
||||
}),
|
||||
Synchronized,
|
||||
);
|
||||
|
||||
export class Layer extends decorate(class {}) {
|
||||
|
|
|
@ -2,7 +2,6 @@ import * as I from 'immutable';
|
|||
|
||||
import {arrayUnique, compose, EventEmitter, flatten} from '@avocado/core';
|
||||
import {EntityCreatePacket} from '@avocado/entity';
|
||||
import {Synchronized} from '@avocado/state';
|
||||
|
||||
import {Layer} from './layer';
|
||||
import {LayerCreatePacket} from './packets/layer-create.packet';
|
||||
|
@ -10,7 +9,6 @@ import {TileUpdatePacket} from './packets/tile-update.packet';
|
|||
|
||||
const decorate = compose(
|
||||
EventEmitter,
|
||||
Synchronized,
|
||||
);
|
||||
|
||||
export class Layers extends decorate(class {}) {
|
||||
|
|
|
@ -5,7 +5,6 @@ import {EntityCreatePacket, EntityPacket, EntityRemovePacket} from '@avocado/ent
|
|||
import {Vector} from '@avocado/math';
|
||||
import {RectangleShape} from '@avocado/physics';
|
||||
import {Resource} from '@avocado/resource';
|
||||
import {Synchronized} from '@avocado/state';
|
||||
|
||||
import {Layers} from './layers';
|
||||
import {LayerCreatePacket} from './packets/layer-create.packet';
|
||||
|
@ -24,7 +23,6 @@ const decorate = compose(
|
|||
default: [0, 0],
|
||||
track: true,
|
||||
}),
|
||||
Synchronized,
|
||||
);
|
||||
|
||||
export class Room extends decorate(Resource) {
|
|
@ -2,7 +2,6 @@ import * as I from 'immutable';
|
|||
|
||||
import {compose, EventEmitter} from '@avocado/core';
|
||||
import {Rectangle, Vector} from '@avocado/math';
|
||||
import {Synchronized} from '@avocado/state';
|
||||
|
||||
import {TileUpdatePacket} from './packets/tile-update.packet';
|
||||
|
||||
|
@ -11,7 +10,6 @@ const decorate = compose(
|
|||
Vector.Mixin('size', 'width', 'height', {
|
||||
default: [0, 0],
|
||||
}),
|
||||
Synchronized,
|
||||
);
|
||||
|
||||
export class Tiles extends decorate(class {}) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user