Sending big data along with event discussion

SPF
SPF
edited February 2021 in Photon Bolt
I'm making a Hearthstone like card game with Bolt. The basic model works fine until I increased the cards amount, which I'll explain later. And I had read the following docs:
can_i_send_a_huge_message_using_photon
boltpacket

In the beginning of the game the server will sync all necessary data to all player using event and tokens. The data includes both player's deck of cards. The game worked well when each player has only 8 cards. But when I increased both players' cards to 30, the bug appears. There's no "Error" but the event get sent repeatedly. If I do not stop the editor, it could increase to thousands of the messages of
sending evnt [PlayersInfoEvent playersInfoEventToken=PlayersInfoEventToken]
. I guess due to the data is too big, the events are not sent or received correctly.

The data structure looks like this:
public class PlayersInfoEventToken : IProtocolToken
{
    public List<Player> players = new List<Player>();
    public List<Slot> slots = new List<Slot>();
}

public class Slot: IProtocolToken, ICloneable
{
    public Vector2 coord;
    public int unitId;
    public byte actorId;
}

public class Player: IProtocolToken, ICloneable
{
    public string userID;
    public byte actorID;
    public int health;
    public int healthMax;
    public int mana;
    public int manaMax;
    public List<Card> deck = new List<Card>();
    public List<Card> hand = new List<Card>();
    public List<int> predrawCardsID = new List<int>();
}

public class Card: IProtocolToken, ICloneable
{
    public int id;
    public int key;
    public int cost;
    public int attack;
    public int health;
}

Right now only two players game is supported, but in the future this number may increase, but won't be more than 10.
There're 24 "Slots" per game.

My questions are:
1. How do I get how big this data is? Do I manually calculate it?
Slot = 2(Vector2) + 2(int) + 1(byte) = 5 bytes
Card = 5*2(int) = 10 bytes
Player = 2 * 20 (userID string for example 20 characters) + 1 (actorID byte) + 4 * 2(int) + 30 * 10 (deck and hand 30 cards in total) + 5 * 2(pre drawCardsID for example 5) = 359
PlayersInfoEventToken = 2 * 359(2 players) + 64 * 5(slots) = 3910 bytes

So every PlayersInfoEventToken is about only 4 KB big. According to the doc data below 10KB are perfectly fine.

2. I could break all these data apart and send them slot by slot or card by card. But that would generate about at least 200 event just in one frame. Is it encouraged to do so? My hunch tells me it's not a good way to go.

3. If I want to send data that's larger than the default 1.2KB packet size limit, how should I do it?

Please help me, thank you!

Comments

  • Hello @SPF ,
    1. How do I get how big this data is? Do I manually calculate it?

    Well, to get a general idea, you will need to calculate the size of your package manually.
    You can also convert an "IProtocolToken" into a byte array and check the final size.

    Take a look here: https://doc-api.photonengine.com/en/bolt/current/class_bolt_1_1_protocol_token_utils.html#a3d915c347b782235c6810e1c559353e6
    So every PlayersInfoEventToken is about only 4 KB big. According to the doc data below 10KB are perfectly fine.

    4Kb of transfer in a real-time scenario can be called big. So, it's always good to try to minimize the memory allocation and transfer.
    2. I could break all these data apart and send them slot by slot or card by card. But that would generate about at least 200 event just in one frame. Is it encouraged to do so? My hunch tells me it's not a good way to go.

    Yes, if you can send fewer messages, the better.
    3. If I want to send data that's larger than the default 1.2KB packet size limit, how should I do it?

    Simple, Stream System: https://doc.photonengine.com/en-us/bolt/current/in-depth/streaming-bytes

    If you don't want to serialize the data yourself, you can build the Protocol Token, convert them to byte arrays, send via stream, and convert back to a Token, also using our utility methods ( https://doc-api.photonengine.com/en/bolt/current/class_bolt_1_1_protocol_token_utils.html#a4c64f503b7a2acfd6c65a761dc6bc27e ).

    --
    Ramon Melo
    Photon Bolt Team
  • @ramonmelo Thanks a lot, very helpful! I've just studied about streaming, and seems would work and I'll try to integrate it into my project.

    Still, I'm curious about these two follow-up questions:
    1. When the doc says "If a message only get sent rarely (for example once at the start of a match), then a size of multiple KB is still fine, but we still would recommend to keep it below 10KB." Does it infer the streaming, or changing the packet size setting, or some other ways that I'm not aware of?
    2. Just to make sure, it is OK if I sent 200 events with small piece of data at once? (for example 10bytes per event)
  • Hi,
    1. When the doc says "If a message only get sent rarely (for example once at the start of a match), then a size of multiple KB is still fine, but we still would recommend to keep it below 10KB." Does it infer the streaming, or changing the packet size setting, or some other ways that I'm not aware of?

    You are reading this at the Realtime documentation, although most of it applies, Photon Bolt has a different approach to how it handles packages.

    This section of the text refers to sending an event using the LoadBalancingAPI, not really related to Bolt itself. Bolt Stream system can send any arbitrary size of data, no need to be bound to 10kb, for example.

    The Bolt package size should not be changed by any means. This is the size of the package sent encapsulated on a UDP Package, and, as Bolt does not deal with fragmentation, it can not handle a package bigger than a UDP (which should be set around 1200 bytes, the default).
    2. Just to make sure, it is OK if I sent 200 events with small piece of data at once? (for example 10bytes per event)

    The Event system works alongside the other systems (state and commands), so you need to be aware that you will be filling most of the package with only your events. Also, we highly suggest lowering the number of events, or at least send them apart, maybe using a coroutine, or similar.
    Sending several events at once is not recommended.

    --
    Ramon Melo
    Photon Bolt Team
  • @ramonmelo Thank you!
    I'm trying to implement stream to avoid sending to many events as we discussed in another post.

    Although I still got situations that it needs to send several events at once. For example, if a player play a card that cast 10 spells randomly, then the server might send up to 20 events at once to each player. This happens not very often, and latency is not a big problem since it's a turn based card game. Is this acceptable?
  • Hi,
    Although I still got situations that it needs to send several events at once. For example, if a player play a card that cast 10 spells randomly, then the server might send up to 20 events at once to each player. This happens not very often, and latency is not a big problem since it's a turn based card game. Is this acceptable?

    No, I don't see it as being a problem.

    --
    Ramon Melo
    Photon Bolt Team
  • Thank you!