GitHub Documentation Patreon donate button

Schema Child Objects Not Updated



  • Hello,

    Enjoying using the library for a work project so far.

    I am sending a message from the server to client:
    this.broadcast(message, { afterNextPatch: true });

    Before this line I update the servers state as follows:
    this.state.dealer.card1 = "9h"

    On the C# side after I receive the message I'd expect the rooms state to be updated but it seems to only update top level properties such as this.state.example. Is there any way to let the server know all the states properties are "dirty" and should be updated? The only workaround I've found now is to send a large copy of the state in the message itself. I thought the afterNextPatch option would ensure my state was fully updated before the message would be received?

    I'm using the Unity C# client.

    Thanks.


  • administrator

    Hi @jconradi, this is supposed to be working properly, I've just checked myself using the unity demo project.

    When using afterNextPatch the message is going to be sent right after the patch, so you can use the data in the state when evaluating that message in the client-side.

    From the server-side, all Schema structures sit behind a proxy, so whenever you update any value, they're flagged as "dirty" for the next patch.

    If you can provide an example project so I can reproduce would be nice. Cheers!



  • @endel Thanks for getting back to me :)

    I'm using a Node server and C# Unity client.

    Server Example:

    class ShortDeckState extends Schema {
    @type("string") gameState: ShortDeckGameState;
    @type("int32") gameStateCountdown: number;
    @type({ map: ShortDeckPlayer }) players = new MapSchema<ShortDeckPlayer>();
    @type(ShortDeckTable) table: ShortDeckTable = new ShortDeckTable();
    }

    class ShortDeckTable extends Schema {
    @type("string") flopCard1: string;
    @type("string") flopCard2: string;
    @type("string") flopCard3: string;

    @type("string") turnCard: string;
    @type("string") riverCard: string;
    
    @type("string") dealerCard1: string;
    @type("string") dealerCard2: string;
    

    }

    // Later in my code I receive a player message, and update the cards on the table:
    this.state.table.flopCard1 = flopCards[0];
    this.state.table.flopCard2 = flopCards[1];
    this.state.table.flopCard3 = flopCards[2];

    this.state.gameState = ShortDeckGameState.TurnWager;

    // Immediately after I send an event to the clients that gamestate has changed.
    // Before I wasn't including the table and players items in the message but I found I needed
    // it to get my data accross.
    var message = new ShortDeckWagerStateChanged();
    message.wagerState = this.state.gameState;
    message.wagerStateCountdown = this.WagerTimeoutSeconds;
    message.table = this.state.table;
    message.players = this.state.players;

        this.broadcast(message, { afterNextPatch: true });
    

    Client:
    // On the client side after I receive ShortDeckWagerStateChanged I try to access room.state.table to get the flop cards but they are always null. gameState has the correct value however

    private void OnShortDeckMessage(object message)
    {
    if (message is ShortDeckWagerStateChanged)
    {
    var wagerChangedMessage = message as ShortDeckWagerStateChanged;

          // This is always null
           var flopCard1 = this.room.State.table.flopCard1;
        }
    }
    

    I hope that illustrates the point a little bit. I copied it from my codebase with some properties removed on the main state class for brevity. Thanks for any pointers you can give me here. I'd like to be able to just use the messages to notify clients of something interesting happening (folded, bet, etc...) and then the clients query the state object for data. This way the clients joining the server in the middle or the clients in the middle of the game are querying the same state data and not having to use a bunch of messages with different properties.



  • @endel Another bit of information...my broadcast:
    this.broadcast(message, { afterNextPatch: true });

    happens in a callback to a clock setInterval. It does appear that when I update my child object (table in this case) in the servers onMessage then everything is fine and the state is updated on the client.

    However, I really need this functionality and am wondering if there is a workaround. I found this by trying to add a broadcastPatch() call inside the clocks callback but I would get a stack overflow. I'm not sure if this is a bug or something I"m doing wrong. Here's an example:

    In response to a player message this function is called:

    startAnteBetCountdown() {
    if (this.betTimeout && this.betTimeout.active) {
    return;
    }

    this.betTimeout = this.clock.setTimeout(() => {
      this.betTimeout = null;
    
      this.game.dealAnteCards();
    
      this.broadcastStateChangeMessage();
      // This next function starts another timer...
      this.startFlopBetCountdown();
    }, (this.WagerTimeoutSeconds + 1) * 1000);
    

    }

    broadcastStateChangeMessage() {
    var message = new ShortDeckWagerStateChanged();
    message.wagerState = this.state.gameState;
    message.wagerStateCountdown = this.WagerTimeoutSeconds;
    message.table = this.state.table;
    message.players = this.state.players;

    this.broadcast(message, { afterNextPatch: true });
    

    }



  • Hopped on a chat in discord with @endel. Definitely a stand up guy! I really appreciate his help and this library is working exactly as advertised.

    He discovered that my real problem was due to referencing some of properties in the rooms' state in messages that I was sending to clients. For example, earlier you can see how I am sending ShortDeckWagerStateChanged. That message has properties that references properties in my state which is wrong. From what I understand this will run the schema encoding logic and leave my state altered.

    If I really wanted to do that then Schema has a clone() method on it but I didn't investigate doing that.


 

GitHub Documentation Patreon donate button

© 2020 Endel Dreyer