• Create Account

### #ActualKylotan

Posted 22 January 2013 - 07:33 PM

When serialising the game state, would it make sense to join all entity, team, global data into a single "state" type, or should I dedicate a type for each component?
I don't have a specific answer for you, but when talking about serialisation or persistence, the real question is never "what should I write" but "how will I read". Reading is the harder problem, because you don't have all the type information yet, just a bunch of bytes. So, figure out what would be the ideal reading process for your data - then work out how to structure the writes accordingly.

You go on to talk about events and packets - I'm not sure why you have joined these 2 concepts. Further up we were talking about events just in the context of separating client/server specific code from generic code, but now you're talking about events as something to do with the networked messages themselves. I don't understand why you're doing this so my answers below may seem strange to you.
It seems almost logical that you would add a special event for each different state member.
I would have one event - StateChanged. The payload would tell me what exactly has changed, and to what value(s).
There are two forms of prioritisation I am referring to here:
• Event prioritisation - Which events must be sent when they are requested, and which can be pushed to the next available packet? I think that in most cases this system would simply determine the order of the events sent, and would rarely interfere with the sending of a packet until the state data as we would say that it is needed most network ticks. Here we could assign certain events a higher priority so that entity packets are sent before score packets.
• Entity prioritisation - Which entities must be sent first, such as vehicles, close players to receiving player. I'm not too sure how I would fit this in with the above [2]
For the first point, in practice you rarely ever want to send events out of order. If something is 'eventful' then it needs sending and often the order is important.

For the second point, this is not a prioritisation issue but a frequency issue. There is no point reordering the data if you're still sending it all. A data stream of "ABCDABCDABCDABCDABCD" is not going to be noticeably better at giving you A's information than "DCBADCBADCBADCBADCBA". So you're doing the wrong thing here.

If I were concerned about such an optimisation, I'd implement it this way:
• changes to entities set a 'dirty' flag on the property to mark it as having changed
• each server-side observer polls entities periodically to collect changed properties, the frequency of such polling being relative to how important the entity is to this observer, sends a state change message, and clears the dirty flag
• Obviously each observer needs its own copy of the dirty flags, which in practice either means you have multiple copies of the world state, one per observer (I know of at least one MMO that basically does this), or you simplify (eg. just have one flag per entity saying 'it has changed' and send all the state - this works for simpler games, like first person shooters where you really have little state to talk of).

The rest of this looks a bit like you overthinking it and getting seriously into the realm of premature optimisation.

"I would now have to increase overhead to 1 byte per entity." - that's ok, most computers can send a million of those per second now.

"It sort of moves away from having dedicated state packets to a fragmented event dump." - Your individual messages can live inside an 'envelope message' which is trivial enough, being just a message that contains other messages. But it's uninteresting.

"When the game starts, the network layer is initialised with a certain depth of packets, something like this:
self.packet = Packet(child=Packet(child=Packet()))
" Why? When a message comes in, check its type and read it. If it's a container for other messages, open it up and call the read recursively. No big deal.

Some of the best shooters out there did an amazing job of literally sending out a flat copy of a single struct to everybody 10 times a second. The fact that you're going through all this complex design to achieve the same effect should be a warning sign, in my opinion.
[/list]

### #2Kylotan

Posted 22 January 2013 - 07:32 PM

When serialising the game state, would it make sense to join all entity, team, global data into a single "state" type, or should I dedicate a type for each component?
I don't have a specific answer for you, but when talking about serialisation or persistence, the real question is never "what should I write" but "how will I read". Reading is the harder problem, because you don't have all the type information yet, just a bunch of bytes. So, figure out what would be the ideal reading process for your data - then work out how to structure the writes accordingly.

You go on to talk about events and packets - I'm not sure why you have joined these 2 concepts. Further up we were talking about events just in the context of separating client/server specific code from generic code, but now you're talking about events as something to do with the networked messages themselves. I don't understand why you're doing this so my answers below may seem strange to you.
It seems almost logical that you would add a special event for each different state member.
I would have one event - StateChanged. The payload would tell me what exactly has changed, and to what value(s).
There are two forms of prioritisation I am referring to here:
• Event prioritisation - Which events must be sent when they are requested, and which can be pushed to the next available packet? I think that in most cases this system would simply determine the order of the events sent, and would rarely interfere with the sending of a packet until the state data as we would say that it is needed most network ticks. Here we could assign certain events a higher priority so that entity packets are sent before score packets.
• Entity prioritisation - Which entities must be sent first, such as vehicles, close players to receiving player. I'm not too sure how I would fit this in with the above [2]

For the first point, in practice you rarely ever want to send events out of order. If something is 'eventful' then it needs sending and often the order is important.

For the second point, this is not a prioritisation issue but a frequency issue. There is no point reordering the data if you're still sending it all. A data stream of "ABCDABCDABCDABCDABCD" is not going to be noticeably better at giving you A's information than "DCBADCBADCBADCBADCBA". So you're doing the wrong thing here.

If I were concerned about such an optimisation, I'd implement it this way:
• changes to entities set a 'dirty' flag on the property to mark it as having changed
• each server-side observer polls entities periodically to collect changed properties, the frequency of such polling being relative to how important the entity is to this observer, sends a state change message, and clears the dirty flag
• Obviously each observer needs its own copy of the dirty flags, which in practice either means you have multiple copies of the world state, one per observer (I know of at least one MMO that basically does this), or you simplify (eg. just have one flag per entity saying 'it has changed' and send all the state - this works for simpler games, like first person shooters where you really have little state to talk of).

The rest of this looks a bit like you overthinking it and getting seriously into the realm of premature optimisation.

"I would now have to increase overhead to 1 byte per entity." - that's ok, most computers can send a million of those per second now.

"It sort of moves away from having dedicated state packets to a fragmented event dump." - Your individual messages can live inside an 'envelope message' which is trivial enough, being just a message that contains other messages. But it's uninteresting.

"When the game starts, the network layer is initialised with a certain depth of packets, something like this:
self.packet = Packet(child=Packet(child=Packet()))
" Why? When a message comes in, check its type and read it. If it's a container for other messages, open it up and call the read recursively. No big deal.

Some of the best shooters out there did an amazing job of literally sending out a flat copy of a single struct to everybody 10 times a second. The fact that you're going through all this complex design to achieve the same effect should be a warning sign, in my opinion.

### #1Kylotan

Posted 22 January 2013 - 07:32 PM