Skip to content

Commit

Permalink
closes #40
Browse files Browse the repository at this point in the history
  • Loading branch information
endel committed Oct 26, 2020
1 parent 98418f4 commit 7437255
Show file tree
Hide file tree
Showing 13 changed files with 233 additions and 27 deletions.
19 changes: 19 additions & 0 deletions example/heaps/src/Container.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// THIS FILE HAS BEEN GENERATED AUTOMATICALLY
// DO NOT CHANGE IT MANUALLY UNLESS YOU KNOW WHAT YOU'RE DOING
//
// GENERATED USING @colyseus/schema 1.0.1
//


import io.colyseus.serializer.schema.Schema;
import io.colyseus.serializer.schema.types.*;

class Container extends Schema {
@:type("map", "string")
public var testMap: MapSchema<String> = new MapSchema<String>();

@:type("array", "number")
public var testArray: ArraySchema<Dynamic> = new ArraySchema<Dynamic>();

}
14 changes: 7 additions & 7 deletions example/heaps/src/Main.hx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ class Main extends hxd.App {

// this triggers only when map or array are created with `new`
// when new value appended it is also triggered but traces just empty array
room.state.onChange = function(v) trace('Root.onChange', v);
room.state.container.onChange = function(v) trace('Root.onChange', v);

// following callbacks are never triggered
room.state.testMap.onChange = function(v, k) trace('Map.onChange', v, 'key', k);
room.state.testMap.onAdd = function(v, k) trace('Map.onAdd', v, 'key', k);
room.state.testMap.onRemove = function(v, k) trace('Map.onRemove', v, 'key', k);
room.state.container.testMap.onChange = function(v, k) trace('Map.onChange', v, 'key', k);
room.state.container.testMap.onAdd = function(v, k) trace('Map.onAdd', v, 'key', k);
room.state.container.testMap.onRemove = function(v, k) trace('Map.onRemove', v, 'key', k);

room.state.testArray.onChange = function(v, k) trace('Array.onChange', v, 'key', k);
room.state.testArray.onAdd = function(v, k) trace('Array.onAdd', v, 'key', k);
room.state.testArray.onRemove = function(v, k) trace('Array.onRemove', v, 'key', k);
room.state.container.testArray.onChange = function(v, k) trace('Array.onChange', v, 'key', k);
room.state.container.testArray.onAdd = function(v, k) trace('Array.onAdd', v, 'key', k);
room.state.container.testArray.onRemove = function(v, k) trace('Array.onRemove', v, 'key', k);

this.room = room;
});
Expand Down
13 changes: 5 additions & 8 deletions example/heaps/src/State.hx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
//
//
// THIS FILE HAS BEEN GENERATED AUTOMATICALLY
// DO NOT CHANGE IT MANUALLY UNLESS YOU KNOW WHAT YOU'RE DOING
//
//
// GENERATED USING @colyseus/schema 1.0.1
//
//


import io.colyseus.serializer.schema.Schema;
import io.colyseus.serializer.schema.types.*;

class State extends Schema {
@:type("map", "string")
public var testMap: MapSchema<String> = new MapSchema<String>();

@:type("array", "number")
public var testArray: ArraySchema<Dynamic> = new ArraySchema<Dynamic>();
@:type("ref", Container)
public var container: Container = new Container();

}
3 changes: 2 additions & 1 deletion example/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"description": "Usage Examples of Colyseus Game Server",
"main": "index.js",
"scripts": {
"start": "ts-node index.ts"
"start": "ts-node index.ts",
"schema-codegen": "schema-codegen rooms/TestRoom.ts --haxe --output ../heaps/src/"
},
"engines": {
"node": "8.9.1"
Expand Down
14 changes: 9 additions & 5 deletions example/server/rooms/TestRoom.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Schema, type, MapSchema, ArraySchema } from "@colyseus/schema";
import { Room } from "colyseus";

class State extends Schema {
class Container extends Schema {
@type({ map: "string" }) testMap = new MapSchema<string>();
@type(["number"]) testArray = new ArraySchema<number>();
}

class State extends Schema {
@type(Container) container = new Container();
}

export class TestRoom extends Room {

async onCreate(options) {
Expand All @@ -14,14 +18,14 @@ export class TestRoom extends Room {
let int: number = 0;

this.clock.setInterval(() => {
this.state.testMap.set(String(int % 3), String(int));
this.state.testArray.push(int);
this.state.container.testMap.set(String(int % 3), String(int));
this.state.container.testArray.push(int);

int++;

if (int % 10 == 0) {
this.state.testMap = new MapSchema<string>();
this.state.testArray = new ArraySchema<number>();
this.state.container.testMap = new MapSchema<string>();
this.state.container.testArray = new ArraySchema<number>();
console.log("RESET");
}
}, 1000);
Expand Down
4 changes: 2 additions & 2 deletions haxelib.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"license": "MIT",
"tags": ["multiplayer", "networking", "websockets", "netcode"],
"description": "Multiplayer Game Client for Haxe",
"version": "0.14.6",
"version": "0.14.7",
"classPath": "src/",
"releasenote": "avoid calling onChange() with empty changeset",
"releasenote": "fixes keeping nested schema callback handlers.",
"contributors": ["endel"],
"dependencies": {
"colyseus-websocket": "1.0.7"
Expand Down
19 changes: 16 additions & 3 deletions src/io/colyseus/serializer/schema/Schema.hx
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ class Schema implements IRef {
return Reflect.setField(this, this._indexes.get(fieldIndex), value);
}

public function getByIndex(fieldIndex: Int) {
public function getByIndex(fieldIndex: Int): Any {
return Reflect.getProperty(this, this._indexes.get(fieldIndex));
}

Expand All @@ -382,6 +382,20 @@ class Schema implements IRef {
public function setIndex(fieldIndex: Int, dynamicIndex: Int) {}
public function getIndex(fieldIndex: Int, dynamicIndex: Int) {}

public function moveEventHandlers (previousInstance: Dynamic) {
var previousSchemaInstance = (previousInstance: Schema);

this.onChange = previousSchemaInstance.onChange;
this.onRemove = previousSchemaInstance.onRemove;

for (fieldIndex => _ in this._childTypes) {
var childType = this.getByIndex(fieldIndex);
if (Std.isOfType(childType, IRef)) {
(childType : IRef).moveEventHandlers(previousSchemaInstance.getByIndex(fieldIndex));
}
}
}

public function decode(bytes:Bytes, it:It = null, refs: ReferenceTracker = null) {
if (it == null) { it = {offset: 0}; }
if (refs == null) { refs = (this._refs != null) ? this._refs : new ReferenceTracker(); }
Expand Down Expand Up @@ -537,8 +551,7 @@ class Schema implements IRef {
value.__refId = refId;

if (previousValue != null) {
value.onChange = previousValue.onChange;
value.onRemove = previousValue.onRemove;
(value : Schema).moveEventHandlers(previousValue);

if (previousValue.__refId > 0 && refId != previousValue.__refId) {
refs.remove(previousValue.__refId);
Expand Down
1 change: 1 addition & 0 deletions src/io/colyseus/serializer/schema/types/IRef.hx
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ interface IRef {
public function setByIndex(fieldIndex: Int, dynamicIndex: Dynamic, value: Dynamic): Void;
public function getByIndex(fieldIndex: Int): Dynamic;
public function deleteByIndex(fieldIndex: Int): Void;
public function moveEventHandlers(previousInstance: Dynamic): Void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ interface ISchemaCollection extends IRef {

public function clear(refs: ReferenceTracker): Void;
public function clone(): ISchemaCollection;
public function moveEventHandlers(previousInstance: Dynamic): Void;
}
109 changes: 109 additions & 0 deletions tests/SchemaSerializerTestCase.hx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import schema.backwardsforwards.StateV1;
import schema.backwardsforwards.StateV2;
import schema.filteredtypes.State in FilteredTypesState;
import schema.instancesharingtypes.State in InstanceSharingTypes;
import schema.callbacks.CallbacksState;

class SchemaSerializerTestCase extends haxe.unit.TestCase {

Expand Down Expand Up @@ -317,6 +318,114 @@ class SchemaSerializerTestCase extends haxe.unit.TestCase {
assertEquals(3, refs.count());
}

public function testCallbacks() {
var state = new CallbacksState();

var containerOnChange = 0;
var containerOnChangeCallback = function(changes) {containerOnChange++;};
state.container.onChange = containerOnChangeCallback;

var arrayOfSchemasOnAdd = 0;
var arrayOfSchemasOnChange = 0;
var arrayOfSchemasOnRemove = 0;

var arrayOfSchemasOnAddCallback = function(item, key) {
// trace("state.container.arrayOfSchemas.onAdd");
arrayOfSchemasOnAdd++;
};
var arrayOfSchemasOnChangeCallback = function(item, key) {
// trace("state.container.arrayOfSchemas.onChange");
arrayOfSchemasOnChange++;
};
var arrayOfSchemasOnRemoveCallback = function(item, key) {
// trace("state.container.arrayOfSchemas.onRemove");
arrayOfSchemasOnRemove++;
};

state.container.arrayOfSchemas.onAdd = arrayOfSchemasOnAddCallback;
state.container.arrayOfSchemas.onChange = arrayOfSchemasOnChangeCallback;
state.container.arrayOfSchemas.onRemove = arrayOfSchemasOnRemoveCallback;

var arrayOfNumbersOnAdd = 0;
var arrayOfNumbersOnChange = 0;
var arrayOfNumbersOnRemove = 0;

var arrayOfNumbersOnAddCallback = function(item, key) {
// trace("state.container.arrayOfNumbers.onAdd");
arrayOfNumbersOnAdd++;
};
var arrayOfNumbersOnChangeCallback = function(item, key) {
// trace("state.container.arrayOfNumbers.onChange");
arrayOfNumbersOnChange++;
};
var arrayOfNumbersOnRemoveCallback = function(item, key) {
// trace("state.container.arrayOfNumbers.onRemove");
arrayOfNumbersOnRemove++;
};

state.container.arrayOfNumbers.onAdd = arrayOfNumbersOnAddCallback;
state.container.arrayOfNumbers.onChange = arrayOfNumbersOnChangeCallback;
state.container.arrayOfNumbers.onRemove = arrayOfNumbersOnRemoveCallback;

var arrayOfStringsOnAdd = 0;
var arrayOfStringsOnChange = 0;
var arrayOfStringsOnRemove = 0;

var arrayOfStringsOnAddCallback = function(item, key) {
// trace("state.container.arrayOfStrings.onAdd");
arrayOfStringsOnAdd++;
};
var arrayOfStringsOnChangeCallback = function(item, key) {
// trace("state.container.arrayOfStrings.onChange");
arrayOfStringsOnChange++;
};
var arrayOfStringsOnRemoveCallback = function(item, key) {
// trace("state.container.arrayOfStrings.onRemove");
arrayOfStringsOnRemove++;
};

state.container.arrayOfStrings.onAdd = arrayOfStringsOnAddCallback;
state.container.arrayOfStrings.onChange = arrayOfStringsOnChangeCallback;
state.container.arrayOfStrings.onRemove = arrayOfStringsOnRemoveCallback;

state.decode(getBytes([128, 1, 255, 1, 130, 2, 131, 3, 132, 4, 133, 5]));
assertEquals(containerOnChange, 1);
assertEquals(arrayOfSchemasOnAdd, 0);
assertEquals(arrayOfSchemasOnChange, 0);
assertEquals(arrayOfSchemasOnRemove, 0);
assertEquals(arrayOfNumbersOnAdd, 0);
assertEquals(arrayOfNumbersOnChange, 0);
assertEquals(arrayOfNumbersOnRemove, 0);
assertEquals(arrayOfStringsOnAdd, 0);
assertEquals(arrayOfStringsOnChange, 0);
assertEquals(arrayOfStringsOnRemove, 0);

state.decode(getBytes([255, 1, 128, 1, 129, 163, 111, 110, 101, 255, 2, 128, 1, 255, 3, 128, 0, 6, 255, 4, 128, 0, 1, 255, 5, 128, 0, 163, 111, 110, 101, 255, 6, 128, 2]));
assertEquals(containerOnChange, 2);
assertEquals(arrayOfSchemasOnAdd, 1);
assertEquals(arrayOfSchemasOnChange, 0);
assertEquals(arrayOfSchemasOnRemove, 0);
assertEquals(arrayOfNumbersOnAdd, 1);
assertEquals(arrayOfNumbersOnChange, 0);
assertEquals(arrayOfNumbersOnRemove, 0);
assertEquals(arrayOfStringsOnAdd, 1);
assertEquals(arrayOfStringsOnChange, 0);
assertEquals(arrayOfStringsOnRemove, 0);

state.decode(getBytes([128, 7, 255, 7, 130, 8, 131, 9, 132, 10, 133, 11, 128, 2, 129, 163, 116, 119, 111, 255, 8, 128, 2, 255, 9, 128, 0, 12, 255, 10, 128, 0, 2, 255, 11, 128, 0, 163, 116, 119, 111, 255, 12, 128, 4]));
assertEquals(containerOnChange, 3);
assertEquals(arrayOfSchemasOnAdd, 2);
assertEquals(arrayOfSchemasOnChange, 0);
assertEquals(arrayOfSchemasOnRemove, 0); // FIXME: ideally, this should be 1
assertEquals(arrayOfNumbersOnAdd, 2);
assertEquals(arrayOfNumbersOnChange, 0);
assertEquals(arrayOfNumbersOnRemove, 0); // FIXME: ideally, this should be 1
assertEquals(arrayOfStringsOnAdd, 2);
assertEquals(arrayOfStringsOnChange, 0);
assertEquals(arrayOfStringsOnRemove, 0); // FIXME: ideally, this should be 1

}


}

16 changes: 16 additions & 0 deletions tests/schema/callbacks/CallbacksState.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// THIS FILE HAS BEEN GENERATED AUTOMATICALLY
// DO NOT CHANGE IT MANUALLY UNLESS YOU KNOW WHAT YOU'RE DOING
//
// GENERATED USING @colyseus/schema 1.0.1
//

package schema.callbacks;
import io.colyseus.serializer.schema.Schema;
import io.colyseus.serializer.schema.types.*;

class CallbacksState extends Schema {
@:type("ref", Container)
public var container: Container = new Container();

}
31 changes: 31 additions & 0 deletions tests/schema/callbacks/Container.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// THIS FILE HAS BEEN GENERATED AUTOMATICALLY
// DO NOT CHANGE IT MANUALLY UNLESS YOU KNOW WHAT YOU'RE DOING
//
// GENERATED USING @colyseus/schema 1.0.1
//

package schema.callbacks;
import io.colyseus.serializer.schema.Schema;
import io.colyseus.serializer.schema.types.*;

class Container extends Schema {
@:type("number")
public var num: Dynamic = 0;

@:type("string")
public var str: String = "";

@:type("ref", Ref)
public var ref: Ref = new Ref();

@:type("array", Ref)
public var arrayOfSchemas: ArraySchema<Ref> = new ArraySchema<Ref>();

@:type("array", "number")
public var arrayOfNumbers: ArraySchema<Dynamic> = new ArraySchema<Dynamic>();

@:type("array", "string")
public var arrayOfStrings: ArraySchema<String> = new ArraySchema<String>();

}
16 changes: 16 additions & 0 deletions tests/schema/callbacks/Ref.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// THIS FILE HAS BEEN GENERATED AUTOMATICALLY
// DO NOT CHANGE IT MANUALLY UNLESS YOU KNOW WHAT YOU'RE DOING
//
// GENERATED USING @colyseus/schema 1.0.1
//

package schema.callbacks;
import io.colyseus.serializer.schema.Schema;
import io.colyseus.serializer.schema.types.*;

class Ref extends Schema {
@:type("number")
public var num: Dynamic = 0;

}

0 comments on commit 7437255

Please sign in to comment.