arjanfrans / realtime-multiplayer-in-html5

:computer::earth_africa::computer: Realtime multiplayer game in the browser.
MIT License
22 stars 10 forks source link

Exchange protocol too verbose for real world use #10

Open jgamedev opened 8 years ago

jgamedev commented 8 years ago

For production deployment it's paramount that data exchange between the client and the server is kept to a minimum. Currently there seems to be zero optimization on this area. For reference here's an example of an exchange payload with only 1 user inside the game room:

"onServerUpdate",{"serverTime":30.091000000001493,"ownPlayer":{"id":"a8061581-7929-4b37-9477-c472e8959634","name":"jay","lastInputSeq":"121","position":{"x":156.355,"y":119.995},"fireing":false,"reloading":false},"players":[],"events":[]}] as {"type":2,"nsp":"/","data":["onServerUpdate",{"serverTime":30.091000000001493,"ownPlayer":{"id":"a8061581-7929-4b37-9477-c472e8959634","name":"jay","lastInputSeq":"121","position":{"x":156.355,"y":119.995},"fireing":false,"reloading":false},"players":[],"events":[]}]}

Here's a few ways in which I believe this could be optimized:

1) Rounding-off time to a meaningful precision: this is the most obvious one. For instance: ' ' 30.091000000001493 could be sent as 30.091 or (maybe 30.02?) and specially the rounding off of positions could be a benefit in a scenario where there are +20 players in the same room.

1) Client UIDs should not be included on frequent exchanges: UIDs should be only be included in meaningful, one-time-off events such as joining rooms, etc. After that a much shorter id can be used that can be mapped to the actual client UID whenever that is needed

2) Avoid sending 'state of the world' types of updates inside of frequent exchanges: instead only "diffs" should be send.

arjanfrans commented 8 years ago

Thanks for pointing out!

jptosso commented 8 years ago

I would use binary data like agar.io On 3 Jul 2016 14:24, "Arjan Frans" notifications@github.com wrote:

Thanks for pointing out!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/arjanfrans/realtime-multiplayer-in-html5/issues/10#issuecomment-230167608, or mute the thread https://github.com/notifications/unsubscribe/ABLfznfu82wWAkW4f7S-ucl8RIP8UnQuks5qR_5wgaJpZM4JD60N .

jgamedev commented 8 years ago

@asdfuken : that sounds awesome but how does it affect your debugging capabilities? Do you have a way to revert back to normal characters when running in test mode?

jptosso commented 8 years ago

I have made a huge modification to messaging, but I would have to documentate the changes :C http://pastebin.com/hCBvk8q7 this is how it's made

2016-07-03 14:42 GMT-04:00 jgamedev notifications@github.com:

@asdfuken https://github.com/asdfuken : that sounds awesome but how does it affect your debugging capabilities? Do you have a way to revert back to normal characters when running in test mode?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/arjanfrans/realtime-multiplayer-in-html5/issues/10#issuecomment-230168455, or mute the thread https://github.com/notifications/unsubscribe/ABLfzs1AyU6DEZoWcnMx7_cojITpLxUhks5qSAJ6gaJpZM4JD60N .

jgamedev commented 8 years ago

@asdfuken , thanks for sharing! I translated the comments in your pastebin into English in case any non-spanish speaking ppl are interested: (http://pastebin.com/nesHjmxZ)

jgamedev commented 8 years ago

@asdfuken , I like how you use ws, I think you have moved away from socket.io, if that's the case can you comment on that?

Here's some more information I have been able to collect about binary protocols:

jptosso commented 8 years ago

My protocol is based on that http://agar.gcommer.com/index.php?title=Protocol I use binary because I wont transfer blops data, binary is enough :) For Strings I use this function

var Uint32ArrayToString = function(data, offset)
{
  var s = "";
  for(var i = offset; i< data.length;i++)
  {
    s += String.fromCharCode(data[i]);
  }
  return s;
}

And I init the server with

var WebSocketServer = require('ws').Server
  , wss = new WebSocketServer({ port: 8001 });
wss.binaryType = 'arraybuffer'; //IMPORTANT!!!!!

Those are ascii encoded

arjanfrans commented 8 years ago

I am thinking about some sort of compress function that transforms the original object to the most minimal possible and then only send the diff. Then on the other side a decompress function will convert it back to a usable object and it then applies the diff to the previously received state.

jgamedev commented 8 years ago

@arjanfrans , binary has a extremely small footprint so you would not need to diff it, unless you need to reduce message frequency as opposed to payload size.

jgamedev commented 8 years ago

@arjanfrans , binary has a extremely small footprint so you would not need to diff it, unless you need to reduce message frequency as opposed to payload size.

arjanfrans commented 8 years ago

I tried something with sending the diffs only and converting those to binary.

https://github.com/arjanfrans/realtime-multiplayer-in-html5/pull/13/commits/6141375f1167426ed142ce8b354da4c09898bbf4