-
export class GameStateSchema extends Schema {
@type('string') status: GameStatus = 'WAITING_PLAYER';
@type('string') type: GameType = "CLASSIC";
@type('string') mode: GameMode = "RANKED";
@type(ConsumedCardHistoryStateSchema) consumedCardHistory = new ConsumedCardHistoryStateSchema();
@type(PlayerStateSchema) playerState = new PlayerStateSchema();
@type(DeckStateSchema) deckState = new DeckStateSchema();
}
export class PlayerStateSchema extends Schema {
@type({ map: PlayerEntitySchema }) players = new MapSchema<PlayerEntitySchema>();
}
export class PlayerEntitySchema extends Schema {
@type('string') id: string;
@type('boolean') isReady: boolean = false;
@type(EmpireEntitySchema) empire: EmpireEntitySchema | undefined;
@type(PlayerStatusEntitySchema) status: PlayerStatusEntitySchema;
@type(PlayerHandEntitySchema) hand = new PlayerHandEntitySchema();
@type({ collection: BuildingQueueItemEntitySchema }) buildingQueue = new CollectionSchema<BuildingQueueItemEntitySchema>();
@type({ collection: EffectQueueItemEntitySchema }) effectQueue = new CollectionSchema<EffectQueueItemEntitySchema>();
}
export class GameRoom extends Room<GameStateSchema>{
onCreate(options: { customRoomId?: string }) {
this.setState(new GameStateSchema());
}
} In my client room.send(EMPIRE_SELECTED_EVENT.description!, {
emperor: ['ZogZog', 'ElPaquito', 'Lamastico', 'Pastafari', 'MasterCPM', 'Kiddo010'][Math.floor(Math.random() * 6)],
} as EmpireSelectedPayload);
room.state.playerState.players.onAdd((playerSchema) => {
console.log(playerSchema);
}); I get error that .onAdd cannot be called on undefined, why it's undefined? Should not the schema be already instantiated? Other weird things is that when I use listen, or change on playerState, players got the new value in collection but AFTER callback (because I try to .get on room.sessionId aka playerId and it's undefined. I think the update comes later (memory allocation of js objects)). I really need some explanations or guidelines about best practices here. Something appear weird to me. I have no problem when testing on backoffice side: describe('Feature: Battle room empire selection', () => {
let colyseus: ColyseusTestServer;
let room: Room<GameStateSchema>;
before(async () => (colyseus = await boot(testConfig)));
after(async () => await colyseus.shutdown());
beforeEach(async () => await colyseus.cleanup());
afterEach(async () => room.setState(new GameStateSchema()));
it('should select an empire', async () => {
room = await colyseus.createRoom<GameStateSchema>(GAME_TEST_ROOM_NAME.toString());
const client1 = await colyseus.connectTo(room);
const client1EmpireMessage: EmpireSelectedPayload = {
emperor: 'ZogZog',
};
const client2 = await colyseus.connectTo(room);
const client2EmpireMessage: EmpireSelectedPayload = {
emperor: 'Elrond',
};
client1.send(EMPIRE_SELECTED_EVENT.description!, client1EmpireMessage);
await room.waitForNextMessage();
client2.send(EMPIRE_SELECTED_EVENT.description!, client2EmpireMessage);
await room.waitForNextMessage();
await room.waitForNextPatch(); // Without this state is maybe not updated during assertion
assert.deepStrictEqual(
room.state.playerState.players.get(client1.sessionId).empire,
new EmpireEntitySchema().assign({
emperor: client1EmpireMessage.emperor,
}),
);
assert.deepStrictEqual(
room.state.playerState.players.get(client2.sessionId).empire,
new EmpireEntitySchema().assign({
emperor: client2EmpireMessage.emperor,
}),
);
});
}); Thank you for your help. And long life to Colyseus! |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 5 replies
-
It's maybe because I use assign when set data inside Schema? export class ColyseusStatePlayerSetup implements PlayerSetupState {
constructor(private readonly _room: Room<GameStateSchema>) {}
private get _playerState() {
return this._room.state.playerState;
}
private get _players() {
return this._playerState.players;
}
save(playerSetup: PlayerSetup): Either<Error, typeof Nothing> {
const playerSetupProps = playerSetup.snapshot;
const empireProps = playerSetupProps.empire.snapshot;
this._players.set(
playerSetupProps.playerId,
new PlayerEntitySchema().assign({
id: playerSetupProps.playerId,
isReady: playerSetupProps.isReady,
empire: new EmpireEntitySchema().assign(empireProps),
}),
);
return Right(Nothing);
}
retrieve(): Either<Error, PlayerSetup[]> {
return Right(
Array.from(this._playerState.players.entries()).map(([id, player]) =>
PlayerSetup.fromSnapshot({
playerId: id,
isReady: player.isReady,
empire: Empire.fromSnapshot({
emperor: player.empire.emperor,
}),
}),
),
);
}
retrieveOne(playerId: string): Either<Error, PlayerSetup> {
const player = this._players.get(playerId);
return Right(
PlayerSetup.fromSnapshot({
playerId,
isReady: player.isReady,
empire: Empire.fromSnapshot({
emperor: player.empire.emperor,
}),
}),
);
}
} |
Beta Was this translation helpful? Give feedback.
-
room.state.playerState.onChange(() => {
console.log(room.state.playerState.toJSON()); doing this, I got empty players map :/ |
Beta Was this translation helpful? Give feedback.
-
Ok... I thought naively that using the methods from array/collection/set/map schema was triggering a new patch for this property. But you need to assign the new value to the schema. So I change from this: this._players.set(
playerSetupProps.playerId,
new PlayerEntitySchema().assign({
id: playerSetupProps.playerId,
isReady: playerSetupProps.isReady,
empire: new EmpireEntitySchema().assign(empireProps),
}),
); to this: this._playerState.assign({
players: this._players.set(
playerSetupProps.playerId,
new PlayerEntitySchema().assign({
id: playerSetupProps.playerId,
isReady: playerSetupProps.isReady,
empire: new EmpireEntitySchema().assign(empireProps),
}),
),
}); |
Beta Was this translation helpful? Give feedback.
-
@endel I'm sorry to disturb but I'm starting to think there is an issue about mutations patch. |
Beta Was this translation helpful? Give feedback.
Increasing patch rate at 80ms is quite stable. For the game I build it's ok (card game don't need much patch rate I think than an FPS) but it seems something is buggy at higher patch rate (lower value than 80ms)