What difference is there when sending a dictionary rather than a struct through Game Center? - ios

I'm implementing a multiplayer mode for my iOS game using Game Center.
It is pretty much a turn-based RPG (but it uses the real-time model), so I don't really need to send data too often.
I've noticed that most examples send data using a struct. One property being the message kind, and the other properties just extra parameters to interpret the message.
I, personally, would enjoy sending a dictionary rather than a struct for no particular reason other than ease of work (in my specific case at least).
I want to know the objective differences between sending structs and dictionaries through Game Center, so I can measure whether it is actually worth doing one over the other.
Some factors:
It's a turn-based RPG. You wait for your rival to send a message with their decision. There is little dynamism, so the data exchange is not quite frequent. If anything, I'd say that it will usually take like 5 seconds for a player to make a decision.
All my data is sent in reliable mode.
My dictionary will usually contain around 3-5 keys, where the values will usually be NSString or NSNumber instances.

Dictionaries use a lot more space than a simple struct.
With dictionaries, you have a lot of flexibility -> You can create your dictionary at run time and send it, as long as all the objects in your dictionary are serialisable. The code is also very easy to write.
Sending a dictionary is a great option, if you need to do things like send arrays, or send multiple objects that you are not aware of at compile time. In fact, if you know that all the objects that you use in your messages are serialisable, then you need just one encode / decode method that could be used for all the dictionaries.
Example: Convert nsdictionary to nsdata
Structs typically use less space.
You need to define your struct at compile time - you need to know the structure of your data that you plan to send. You can't do this dynamically.
If you need to send multiple arrays, you need to know the size before hand, since you can't send multiple variable length arrays at run time.
For your situation, if it is "turn based", and if a couple of seconds here or there won't make too much of a difference, then an NSDictionary may be more convenient for you.
If you were writing a first person shooter, or some kind of action game that needs to send data 30 or 60 times a second, then you would use the smallest format possible to send your data to avoid latency problems.
In an ideal world, regardless of whether it was turn based, or an fps, you wouldn't want to send more data than necessary, because you are wasting bandwidth, and your app will take longer to send / receive messages. The optimal method would be to create your own format where you minimise the number of wasted bits (example: if you know that a number you send will never be greater than 10, then you use only 4 bits to represent it). But in reality, it may making coding such an efficient encoding / decoding method tricky.

Related

Sending events (async data) in CANopen with more than 8 bytes of data

We are developing a typical CANbus networked system with what you could call a controller organizing a number of devices.
The devices needs configuration, which the controller writes (and might also read back) using regular object dictionary items (currently in the manufacturer specific range).
The devices also perform actions (commands) with more than 8 bytes of data and this we solve by having write only items in the device object dictionary and relying on the regular segmentation/de-segmentation of SDO's. (I don't know if this is the CANopen way of doing things, but it seems reasonable).
However, the device also produces events (say some sensor data passes a certain threshold) resulting in more than 8 bytes of asynchronous data coming up from the device. PDO's are meant to be used for sending async event data, but it can only contain 8 bytes. The devices could write the data into an object dictionary item on the controller, but this doesn't seem like the CANopen way. Am I right?
The best we've come up with is to send a PDO to the controller, informing the controller that more data are available in the object dictionary on the device.
Anyone with CANopen background that can way in on the best (CANopen) way of solving this?
Since I'm repeating 8 bytes a lot, we can safely assume that this network is not running CAN-FD.
The key of any sensible CAN network design is to consider real-time, data priorities, bus load and data amounts early on. If you find yourself with a chunk of data larger than 8 bytes, then that strongly suggests that something is wrong in this design - it should likely be split in several packages.
Generally, you shouldn't be using SDO for data at all, since they come with overhead. That includes writes to the object dictionary, which also means SDO access. Block transfers etc with SDO are meant for things like bootloaders or one-time configuration, not for live data traffic in operational mode. It can be done, but it is fishy.
You can in theory map data across several PDOs with PDO mapping, but all of this really sounds like an "XY problem" - you are convinced that you need to transmit larger chunks of data and look for a way to do it. But step 1 is to look at the fundamental network data/design and see if you actually need those large chunks or if it makes sense to split them in several. The ideal CANopen design is to have one PDO per type of data, when possible.

iOS Game Center GKScore context, how to encode information?

I'm doing my first implementation with Game Center. I'm trying to let players issue GKScore challenges to one another. My game consists of playing a certain number of levels in a random order. (Let's say, a game is 9 levels long, randomly chosen from 30 possible levels.)
When the challenge is issued, I need to be able to include which levels the challenging player played so that the receiving player can play those same levels hopefully in the same order.
I know that I can include a GKScore.context : UInt64 which will get passed back to me, but I'm having trouble figuring out how best to encode my level information to get passed along and was hoping for some pointers toward examples or other solutions/best practices.
I know that I could use bitwise flags to encode which levels should be included in the 9-level-game, but I'm not sure how I could also include the order if I did that.
I know that I could use the GKScore.context to generate a random id number, upload the game info to my server, and then fetch it back down with that same identifier, but I really do NOT want to add a server component to this game which should run entirely on device. I don't want the server load nor the server code maintenance.
What other options have you used for transmitting challenge information with the GKScore.context without relying on a server component?
Generate a random value that will fit in 64-bits. Use that to seed a random number generator and produce whatever level numbers in whatever order you need. Save the seed as the context. For the challenged player, get the seed from the context info and initialize your random number generator with the same seed. You'll get the same sequence of "random" values and hence the same level numbers in the same order. The only network stuff will be through Game Center when it has to deliver the challenge.

What is the best way to code the XNA Game Server for FPS game?

I'm writing a FPS XNA game. It gonna be multiplayer so I came up with following:
I'm making two different assemblies — one for the game logic and the second for drawing it and the game irrelevant stuff (like rocket trails).
The type of the connection is client-server (not peer-to-peer), so every client at first connects to the server and then the game begins.
I'm completly decided to use XNA.Framework.Game class for the clients to run their game in window (or fullscreen) and the GameComponent/DrawableGameComponent classes to store the game objects and update&draw them on each frame.
Next, I want to get the answer to the question:
What should I do on the server side? I got few options:
Create my own Game class on the server, which will process all the game logic (only, no graphics). The reason why I am not using the standart Game class is when I call Game.Run() the white window appears and I cant figure out how to get rid of it.
Use somehow the original XNA's Game class, which is already has the GameComponent collection and Update event (60 times per second, just what I need).
UPDATE:
I got more questions:
First, what socket mode should I use? TCP or UDP? And how to actually let the client know that this packet is meant to be processed after that one?
Second, if I is going to use exacly GameComponent class for the game objects which is stored and processed on the server, how to make them to be drawn on the client? Inherit them (while they are combined to an assembly)? Something else?
First of all, your game logic should be on the server.. Not only does that prevent cheating, but it also garantees consistency, especially over random operations. The clients should only be sending their inputs to the server
I'd recommend your keep the server's window visible to make it a debug console, you'll need it, to know what your server is doing exactly.
For a FPS, UDP is recommended. You'll be sending a lot of data and you don't really care if your packets are all received or ordered. While the packets are not garanteed to arrive ordered, you don't really have to worry about it. Most of the time, they will arrive in order anyway. Let's say you send 60 frames per second to your clients and one of your packet arrives in the wrong order: Your client will have erroneous information for 1/60th of a second, which is barely visible.
Finally, you should send a serialized representation of your game state multiple times per second to your clients. They should be able to retrieve that information and draw it the same way as your server. You could even serialize your gamecomponent and send it if you think that's appropriate. It's really up to you to decide.
Hope this helps!

Erlang in-memory linked list -- Exhausting memory?

I tried to make an Erlang in-memory datastore that would receive messages and add them to a list. Here's the current incarnation. The trouble is, I'm receiving about 200 messages per second and this easily exhausts the memory available.
Once a minute, I send a {write, Pid} message that should clear out and clean up this list, but it doesn't look like it's being garbage collected.
What am I doing wrong? I think I'm approaching this from the completely wrong direction...
datastore(Db) ->
receive
{put, Data} ->
datastore(lists:concat([Data,Db]));
{write, Responder} ->
ScratchName = "ScratchFile.dat",
{ok, ScratchDevice} = file:open(ScratchName,[write]),
file:write(ScratchDevice,Db),
ok = file:close(ScratchDevice),
Responder ! {load, ScratchName},
datastore([])
end.
First spontaneous comment is that file:open will open the file, truncate it, and then write to it. So every time in the loop will overwrite any previous data. So if the Responder is slow with its loading of the file, there could be data you did not expect in the file.
Second reaction is that you don't have to do this buffering yourself. If you open the file with the option {delayed_write, Size, Delay}, and set Size and Delay to values that fit your purpose, you get precisely what you are trying to implement here by just writing all the time.
Third reaction is that you are probably doing the wrong thing if you use a file to communicate between different parts of your system. What are you attempting to do?
ps.
If you need a new random filename, you can easily generate one with erlang:now/0 and io_lib:format/2. As an added bonus they will sort in creation order.
This is a very wrong way of buffering in Erlang. Data Structures such as ETS (http://www.erlang.org/doc/man/ets.html) have been designed to handle thousands and millions of IN-MEMORY Erlang Data Structures with ease. Please, do not use Lists or Queues for handling too much data. If a part of your code will be handling data which other parts of the application are supposed to consume and yet you know that the consumers will be doing it a slower rate as compared to the part that is generating or getting the data, then you need a more robust way of buffering (ETS Tables).
Another thing is that usually, processes are a point of failure in a system. If a process is used to buffer or hold on to very essential data, even if that data is instantaneous but critical to the system, what would happen at that time when the process exits or dies ? ETS tables have been designed in a way that they can provide data access to all processes even applications within the same VM (of type public). In this way, all processes can use the data, reading as much as they want (concurrently) but what you would do is to ensure consistency by having one writer / updater.
ETS Tables rarely fail in an application as compared to the frequency at which processes fail. Most recently, a method that helps us to redeem data in a failing ETS table has been introduced ( ets:give_away/3 ).
Another thing, in a comment above, you have mentioned that you are working for a large Company. Usually, with large teams, its better you evaluate a number of options and make intensive tests against several depending the nature of the application you are developing. To avoid side effects, its best that you identify which data structures are best to use for what. For example, for in-memory storage, capable of handling 200 messages per second, if tested properly, Lists and Files would fail against ETS Tables.

What kind of socket server protocol is efficient?

When I was writing a simple server for a simple client <> server multiplayer game, I thought of the following text-based protocol using a translation library. Basically, each command had a certain meaning, eg:
1 = character starts turning right
2 = character starts turning left
3 = character stops turning
4 = character starts moving forward
5 = character stops moving
6 = character teleports to x, y
So, the client would simply broadcast the following to inform that the player is now moving forward and turning right:
4
1
Or, to teleport to 100x200:
6#100#200
Where # is the parameter delimiter.
The socket connection would be connected to the player identifier, so that no identifier has to be broadcasted with the protocol to know what player the message belongs to.
Of course all data would be validated server side, but that is a different subject.
Now, this seems pretty efficient to me, only 2 bytes to inform the server that I am moving forward and turning right.
However, most "professional" code snippets I saw seemed to be sending objects or xml commands. This seems to require a lot more server resources to me, doesn't it?
Is my unexperienced logic of why my text based protocol would be efficient flawed? Or what is the recommended protocol for real-time action multiplayer games?
I want to setup a protocol that is as efficient as possible, because I do not want to use multiple clusters/servers to cover excessive amounts of bandwidth for my 2D multiplayer game, and to safe synchronization problems and hassle.
However, most "professional" code
snippets I saw seemed to be sending
objects or xml commands. This seems to
require a lot more server resources to
me, doesn't it?
Is my unexperienced logic of why my
text based protocol would be efficient
flawed? Or what is the recommended
protocol for real-time action
multiplayer games?
Plain text is more expensive to send than a binary format containing the same information. For example, if you only send 1 byte, you can only send 10 different commands, digits 0 to 9. A binary format can send as many different commands as there are different values you can fit into a byte, ie. 256.
As such, although you are thinking of objects as being large, in actual fact they are almost always smaller than the plain text representation of that same object. Often they are as small as is possible without compression (and you can always add compression anyway).
The benefits of a plain text format are that they are easy to debug and understand. Unfortunately you lose those benefits if you put your own encoding in there (eg. reducing commands down to single digits instead of readable names). The downside is that the format is bigger, and that you have to write your own parser. XML formats eliminate the second problem, but they can't compete with a binary format for pure efficiency.
You are probably overthinking this issue at this stage, however. If you're only sending information about events such as the commands you mention above, bandwidth will not be a concern. It's broadcasting information about the game state that can get expensive - but even that can be mitigated by being careful who you send it to, and how frequently. I would recommend working with whatever format is easiest for now, as this will be the least of your problems. Just make sure that your code is always in a state where you can change the message writing and reading routines later if you need.
You need to be aware of the latency involved in sending your data. "Start turning"/"stop turning" will be less effective if the time between the receipt of those packets is different than the time between sending them.
I can't speak for all games, but when I've worked on this sort of code we'd send orientation and position information across the wire. That way the receiver could do smoothing and extrapolation (figure out where the object should be "now" based on data that I have that is already known to be old). Different games will want to send different data, but generally speaking you will need to figure out how to make the receiver's display of the data match the sender's, so you'll need to send data that is resilient in the face of networking problems.
Also, many games use UDP for this sort of data transfer instead of TCP. UDP is unreliable, so you may not get all of your packets. That means that "stop moving now" or "start moving now" may not be received in pairs. When coding on top of UDP then it's even more important to send "this is the state right now" every so often so that clients get ample opportunity to sync up.
The common way is to use a binary format, not text, not xml. So with only one byte you can represent one of 256 different commands.
Also use UDP and not TCP. The game will be a lot more responsive with UDP in case of packet loss. In case of packet loss you can still extrapolate the movements. With each packet send a packet number so that the server knows when the command was sent.
I highly recommend that you download the Quake source code where you can learn more about network programming in modern multiplayer games. It's really easy to read and understand.
edit:
I almost forgot..
Google's Protocol Buffers can be of great help when sending complex data structures.
I thought I would give my two cents and provide a practical application to what is being referred to as Binary Serialization. The concept is actually incredibly simple, yet only seems complicated on the outside.
You can actually send XMLs and have a server that processes the data within the XML to different functions within the server itself. You can also just send the server a single number that is stored within the server as a variable. After that, it can process the rest of the data and choose the correct course of actions.
As an example, some rough code:
private const MOVE_RIGHT:int = 0;
private const MOVE_LEFT:int = 1;
private const MOVE_UP:int = 2;
private const MOVE_DOWN:int = 3;
function processData(e:event.data)
{
switch (e)
{
case MOVE_RIGHT:
//move the clients player to the right
case MOVE_LEFT:
//move the clients player to the left
case MOVE_UP:
//move the clients player to the up
case MOVE_DOWN:
//move the clients player to the down
}
}
This would be a very simple example, and would need to be modified but as you can see you merely just store the variables encoded with whole numbers that you transmit in strings of numbers. You can parse these and create headers of information to organize them into different sections of data that needs to be transmitted.
Also, it is better to do a UDP setup for games because just missing a packet should NOT halter the gaming experience, but instead should be able to handle it client-side AND server-side.

Resources