Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Zoidcom

This thread is locked; no one can reply to it. rss feed Print
Zoidcom
Albin Engström
Member #8,110
December 2006
avatar

Multiplayer... you sexy thing.

Question 1: What platforms does Zoidcom support?
Question 2: Is there a better alternative to Zoidcom?
Question 3: Remember worms? Remember the destroyable ground? MHM, i'm planing on implementing that, but as my game is going to be multiplayer i need to make sure everyone gets the same information about impacts and such, so i should go with a server and client system right?, as i can't send bitmaps from the server to the clients. i guess my question is: how do i make udp safe and fast? (i feel like i've asked this before... deja vu!)

Thanks in advance No, i'm not going to thank someone for something they haven't done - -. i'll thank you afterwards.

orz
Member #565
August 2000

1: Windows & Linux, with plans for more, according to the docs. I haven't used it.
2: I generally implement game networking on top of lower-level primitives.
3: UDP is already as fast as it gets. You make it safer by wrapping it in something that resends data that got lost. The standard wrapper for doing this is known as TCP, but there are a bunch of other UDP wrappers out there if you won't like TCP. (technically, TCP is not a UDP wrapper because it uses a different protocal number, but in all other respects it's a UDP wrapper, so that's just a technicality).

Kibiz0r
Member #6,203
September 2005
avatar

I am a big advocate of ZoidCom.

You could do destroyable ground in a few ways... The best way I can think is to use ZCom's message system. There are different message flags that you can set that determine how fast vs. how secure a message will be.

They can be any combination of
Reliable -- meaning that the message will always be sent with the correct information (error-checking)
Ordered -- when a message has to arrive before or after another message, use this and messages that arrive out of order will be tossed and requested to be resent

Both of these, together, essentially form TCP. What you probably want is just Reliable. It'll be fast, but accurate.

Since you seem to be a novice to network programming, I would suggest making a few small network apps to experiment with and develop an architecture you like before putting it into this game you're working on. If you dive in headfirst, you will be prone to making spaghetti code.

Albin Engström
Member #8,110
December 2006
avatar

orz: nice, huh?(what's lower leverl primitives?) and hmm.. thanks :P.

Kibiz0r: ok ^^', fast vs secure? so both = no no? :P.
I think both Reliable and Ordered seems important.. but i have a feeling i shouldn't listen to myself.. :/.. so why would i not want ordered? i've heard UDP is the way to go in games, but what do i do when information gets lost or comes in... a random order? (um..). And i will definitely make a few(note few :)) network apps before i try to use it, right now i'm just honing my skills and i though multiplayer would be awesome addition to my knowledge... :P.

orz
Member #565
August 2000

I use raw sockets, but by "lower-level primitives" I mean anything where you explicitly generate your own packets. A brief googling finds the following networking libraries used in games:
enet low-level
RakNet low-level + some higher level helpers
HawkNL low-level?
ZIG high level
ACE high level (w/ some low-level?)
GNE high level
ZoidCom high level
DyConnect high level layer & low level layer
openTNL high level layer & low level layer
SDL_net low-level (I've tried this one and dislike it)
clan_net low-level?
NeL high level

Kibiz0r
Member #6,203
September 2005
avatar

You don't need ordered for keeping track of destruction of the game world because it's only going to happen once and it ought to not have an effect on anything on the client's screen other than that part of the map being gone. The reason for this is that all calculations are done on the server.

Myrdos
Member #1,772
December 2001

The reason most games don't want ordered reliable communications is because they don't want to resend stale data. If your server is sending a player's coordinates to the client, and the packet was dropped by the network, why resend the old coordinates? If you're going to send coordinates, you'd might as well send a new packet with the current ones.

In TCP if a packet is dropped, it automatically gets resent whether you like it or not, increasing game lag.

Quote:

but what do i do when information gets lost or comes in... a random order?

UDP is like the mail. Each packet can be thought of like a letter. It gets sent to a router, which reads the address, and sends it to a closer router, until finally the packet reaches you. Not all packets will necessarily take the same path through the network. So it's possible that packets can arrive out of order, though this is rare if there's a delay between send times. (say if you're sending updates to clients once every 100 ms) TCP automatically orders packets, but of course you must wait for the out-of-order packet to arrive, increasing lag.

Other topics you'll want to look into are dead reckoning and smoothing algorithms, though these are not necessary if your game is turn-based. The lockstep algorithm is the traditional way of synchronizing very large amounts of data using low bandwidth, but it can be quite difficult to implement and debug. gamedev.net has some good tutorials on these.

If your game is turn based, I'd recommend using TCP. Whenever the game state changes, the server can send the changes to the clients (or just the command that caused the change), and you'll at least know that it was received.

Quote:

DyConnect high level layer & low level layer

If you're going to use DyConnect, wait until Monday. I have inside information that there's going to be a new release between now and then.:)

__________________________________________________

Albin Engström
Member #8,110
December 2006
avatar

orz: raw sockets? (i think i have a lot to learn..).. generate my own packets? i like the sound of that, i read in the description of zoidcom that you "register objects and zoidcom then synchronizes them" something like that, what exactly do they mean by that? sounds like you share variabels or something...

Kibiz0r: hmm, i'm not sure i understand.. the game in my head = fast paced multiplayer sidescrolling rpg.. monsters spawn and you kill em,, "simple".. what calculations should be done by the server?, i felt like the server should just keep track of movement and send information to the clients, and as i plan to use "destroyable ground" i thought the server couldn't possibly handle and update such information.. i'm not sure i'm thinking right.. i've never done multiplayer or anything network related :/.

David McCallum: but isn't loss of data extremely bad? if the server don't have information about one client.. won't they get out of sync unless you do some coding which i don't want to.. (i'm thinking: OMG! IM GOING TO SHOOT THIS BASTARD IN THE FACE!!! lagg(lag?), no, he stopped like a half second ago but that information didn't get through... suprise! BANG!!!) one time per 100ms.. i don't think i could do with that ^^'.
what's a good refresh rate for this kind of situation? i thought i should optimize this game for lan.. and i would like the refresh to cover a lot of screen refresh rates. atleast a hundred times per second...

have mercy..

Kibiz0r
Member #6,203
September 2005
avatar

Quote:

what calculations should be done by the server?

Physics, game events, that's about it.

For the destroyable ground, I would just write a deterministic function and send an event to the client when ground is destroyed that includes the coordinates.

projectile update causes explosion where ground should be destroyed
server sends ground_destroyed x y
client receives ground_destroyed x y
client updates game view appropriately (removes whatever pixels it needs to based on the parameters of the ground_destroyed message)

Edit:
(regarding your ZoidCom replication question)

ZoidCom Reference said:

void ZCom_Node::addReplicationInt ( zS32 * _ptr,
zU8 _bits,
bool _sign,
zU8 _flags,
zU8 _rules,
zS16 _mindelay = -1,
zS16 _maxdelay = -1
)

Add an int to the data replication.

Parameters:
_ptr Pointer to the data source.
_bits The amount of relevant bits. Zoidcom will replicate no more than the relevant bits across the net link.
_sign Store the sign bit as extra information, you don't need this if _bits is set to 32 on a 32 bit value (the sign is included already in that case).
_flags Combination of Replication Flags, ORed together.
_rules Combination of Replication Rules, ORed together.
_mindelay Measured in msecs and defines how much time has to pass between two consecutive updates of this data.
_maxdelay Measured in msecs and defines how much time may pass between two consecutive updates of this data.

Attention:
Make sure that only pointers to zS32 or larger data types are passed here, since Zoidcom writes sizeof(zS32) bytes on incoming updates!
The update frequency bounds as defined by _mindelay and _maxdelay are not guaranteed. The resolution highly depends on factors like the client's connection, node priority and node relevance.

In ZoidCom, nodes are equivalent to your classes, and replicators are equivalent to data members of those classes. You just tell it what ones you want synced and how and it takes care of it for you.

Myrdos
Member #1,772
December 2001

Quote:

but isn't loss of data extremely bad? if the server don't have information about one client.. won't they get out of sync unless you do some coding which i don't want to..

Imagine this: your server handles game logic. It periodically sends updates about the game state (player coordinates, etc) to all clients. Every 100 ms the game state is put into a packet, and a copy of that packet is sent to all clients. Clients then use the packet to update their state.

Now, imagine you're a client. Your ping time to the server is 300 ms. This is the time it takes for you to send a very small packet to the server, and receive a very small packet as a reply. If a packet is lost, the TCP protocol will require at least 300 ms to notify the server about this. Meanwhile, the server has already sent two more updates (one update every 100 ms). Now a packet was dropped by the network:

The UDP protocol says: "Screw that dropped packet, more recent updates are already on the way. (Or maybe I already got them)

The TCP protocol says: "I got the most recent coordinates, but I'm going to wait for the older ones before I tell the program about it. No packet will be left behind!" Do you see how this adds lag to your program?

Quote:

what's a good refresh rate for this kind of situation?

The server should send 10-20 updates to each client per second. I believe Quake used 10. The fewer updates you send, the less bandwidth you use. However, you're introducing lag. If you're sending 10 updates/second, then you're introducing up to 100 ms of lag before clients are notified of new events.

Quote:

that at i thought i should optimize this game for lan..

If your game is intended for lan, almost anything you do will work fine. The ping time is < 10 ms, and bandwidth is plentiful.

Quote:

and i would like the refresh to cover a lot of screen refresh rates. atleast a hundred times per second...

I'm not sure what you mean here.

1) You don't need to send a network update every time you redraw the screen. The clients should be able to run game logic in the absence of updates. For example, if your character is moving at a certain speed, the client should know how far to move him every game update. When the server finally does send the coordinates, your coordinates should be very close to what the server sent. (Bear in mind you'll need a dead reckoning algorithm here to avoid jitter)

2) You should de-couple game logic from network logic. The number of times you send network updates has nothing to do with FPS or game logic updates/sec. You'll want to use a timer, and see how much time has elapsed in real-world millisecs before sending updates to clients.

__________________________________________________

Slipstream
Member #8,220
January 2007

I understand the theory behind networking very well and yet Zoidcom bamboozled me at its most basic level, I've heard its hard to begin using it but I was unable to make anything other than a simple chat client and server.

So would I be best learning raw sockets? Otherwise which UDP library would suit me best?

Albin Engström
Member #8,110
December 2006
avatar

Kibiz0r:

Kibiz0r said:

projectile update causes explosion where ground should be destroyed

and what if the packet with that information gets lost? should i let the server sent the update about that explotion continusly for one second or something? or until the server gets information from the client that the explotion has been noted?

Kibiz0r said:

In ZoidCom, nodes are equivalent to your classes, and replicators are equivalent to data members of those classes. You just tell it what ones you want synced and how and it takes care of it for you.

what's a node and a replicator?...

David McCallum said:

Imagine this: your server handles game logic. It periodically sends updates about the game state (player coordinates, etc) to all clients. Every 100 ms the game state is put into a packet, and a copy of that packet is sent to all clients. Clients then use the packet to update their state.

... AWESOME! that way less capable computes can be clients, why didn't i think about that..

David McCallum said:

Now, imagine you're a client. Your ping time to the server is 300 ms. This is the time it takes for you to send a very small packet to the server, and receive a very small packet as a reply. If a packet is lost, the TCP protocol will require at least 300 ms to notify the server about this. Meanwhile, the server has already sent two more updates (one update every 100 ms). Now a packet was dropped by the network:
The UDP protocol says: "Screw that dropped packet, more recent updates are already on the way. (Or maybe I already got them)
The TCP protocol says: "I got the most recent coordinates, but I'm going to wait for the older ones before I tell the program about it. No packet will be left behind!" Do you see how this adds lag to your program?

I totaly understand.. thanks!

David McCallum said:

The server should send 10-20 updates to each client per second. I believe Quake used 10. The fewer updates you send, the less bandwidth you use. However, you're introducing lag. If you're sending 10 updates/second, then you're introducing up to 100 ms of lag before clients are notified of new events.

ah, would it be possible to let the server choose the refresh rate? (let the creator of the server to choose the refresh rate)

David McCallum said:

dead reckoning algorithm

damn, figured something was needed... where can i learn this?

Thank you very much!

question: can i staticly link zoidcom?

Jonatan Hedborg
Member #4,886
July 2004
avatar

Quote:

question: can i staticly link zoidcom?

No. There is no source release and the License agreement says: "The use of dll 'static linking' tools is prohibited."

Albin Engström
Member #8,110
December 2006
avatar

Jonatan Hedborg: ok, but why would they want static linking not to be available?

orz
Member #565
August 2000

Quote:

I understand the theory behind networking very well and yet Zoidcom bamboozled me at its most basic level, I've heard its hard to begin using it but I was unable to make anything other than a simple chat client and server.

So would I be best learning raw sockets? Otherwise which UDP library would suit me best?

ZoidCom "layer 2" is what I would consider low-level; you won't get much better results out of raw sockets unless your problem is ZoidComs C++ified API. There is no equivalent to ZoidCom's "layer 3" and "layer 4" (nodes and replication) in any low-level sockets-like API. Of course, raw sockets have the advantage that they get used in things besides games, and by people besides game programmers, so the knowledge is potentially more portable to other uses. Still, a lot of people talk to sockets through at least a thin wrapper to avoid the stupidities and portability issues of raw sockets.

Quote:

and what if the packet with that information gets lost? should i let the server sent the update about that explotion continusly for one second or something? or until the server gets information from the client that the explotion has been noted?

You can flag messages for reliable delivery in ZoidCom. Well, you can through some of its interfaces... not sure about all of them. ZoidCom will presumably resend transparently at that point.

Quote:

what's a node and a replicator?...

I haven't actually used ZoidCom, just read the docs, but: A "node" is a ZoidCom object that is supposed to help you copy a game object from the server to the client. A node is intended to be associated with each game object I think. A "replicator" is a ZoidCom object that attaches to a node and helps send update events to clients for a particular aspect of a game object. A replicator is intended to be associated with each data member of a game object associated with a node, I think. See "layer 3" and "layer 4" of the docs respectively.

Trezker
Member #1,739
December 2001
avatar

Zoidcom may be hard to learn. But programming realtime networking features yourself is much harder. Debugging network code is one of the worst things programming has to offer.

Albin Engström
Member #8,110
December 2006
avatar

orz: ZoidCom seems really... strange.. i never thought it would be like this :P, i thought it was just a bunch of "simple" send and get functions. I've made a simple server and a client,(by looking at the example files), learned a lot about how it works mostly. but it only works on the local network, i can't get the shit to work on the internet :/, and i don't know if the router is the cause.. my dad has password protected it, and for some stupid reason he wont let me see the available ports.. after i few experiments i'm not sure it's the router.. but i have no way to tell right now.. i have to study more.

Trezker: But if you make em yourself you'll really know what you're dealing with.. and you may make it the way you want it. if i could, i would.

Myrdos
Member #1,772
December 2001

Quote:

that way less capable computes can be clients, why didn't i think about that..

Ahh... not quite! Clients still have to handle game logic to make the game run smoothly. If your server is sending one update every 100 ms, the client has to handle game logic between updates. When the update arrives, the client's state should be close to the values sent by the server.

Quote:

ah, would it be possible to let the server choose the refresh rate?

Yes.

Quote:

damn, figured something was needed... where can i learn this?

gamedev.net has some good tutorials on networking. Their networking forum is also very good. The basic idea behind dead reckoning is this: lets say the server is periodically sending updates to the client. Whenever the client gets an update from the server, it copies the values and uses them for its game state. This sounds like it should be fine, but in reality the characters will be jumping around their "correct" position.

The problem is that the time for a packet to travel from the server to a client varies widely. Imagine your character is moving forward in a straight line. If the server's update reaches the client very quickly, the character will jump ahead. If the next update reaches the client more slowly, he jumps back. (because you're receiving a coordinate from farther in the past)

So you define a 'dead reckoning threshold'. The client simulates all game logic. The client will only use the server's values if the difference between the client's and server's coordinates exceeds this threshold. Now the character seems to move smoothly, and if he gets too far out of sync, he snaps back to the correct position.

This is better, but dead reckoning is not enough by itself. If the character stops moving, his coordinates will be permanently out of sync - just not exceeding the threshold. And using the server's values causes a jerky 'jump' to the correct location, also no good. So you'll want to implement a smoothing algorithm as well. The client will slowly, gradually, move the character towards the server's coordinates, hopefully without introducing jitter or desynchronizing the game.

Designing a good smoothing algorithm is a black art. It separates nice smooth games from glitchy jerky ones.

The smoothing algorithm should be enough for normal network conditions, and the dead reckoning threshold should only be reached by clients who are lagging/dropping multiple packets.

Quote:

So would I be best learning raw sockets?

I wouldn't recommend it. I know a lot of people feel you can gain insight into networking by doing the low-level stuff yourself. But I feel that fighting with low-level APIs only gains you insight into the syntax of low-level APIs. If you do decide to write your networking from scratch, avoid Beej's Guide. It's very well written, but obsolete. Modern apps use getnameinfo and getaddrinfo for the heart of their networking.

Quote:

Debugging network code is one of the worst things programming has to offer.

Agreed. It gets worse if you want your code to be cross-platform.

__________________________________________________

Albin Engström
Member #8,110
December 2006
avatar

David McCallum: yeah,, but i could make it an option right?(the dead reckoning and smoothing algorithms) and i plan to optimize this game for lan so using the server for everything and having a very high frequent refresh rate, would that be ok?

lets say the server refreshrate is 75 times per second and i force the screen refresh rate to 75 on all computers, it would look nice right?. and there would be no need for dead reckoning and those things rigth? EDIT:(no, even better: the server gets the screen refresh rate of the clients and then send them updates according to their screen refresh rates.).

btw.. how often do packages get lost and what's the cause of these losses?

thank you. :)

Myrdos
Member #1,772
December 2001

Almost anything will work well on a LAN, though you will probably get a very little bit of jitter. If I were you, I'd have the server update rate as an adjustable setting. Then, when you can see the jitter, you can decide how to handle it. But even a very poor/simple smoothing algorithm might be enough on a LAN:

void applyServerUpdate(int serverX,
                       int serverY)
{
  clientX += (serverX - clientX) / 5;
  clientY += (serverY - clientY) / 5;
}

And now you've got some smoothing! Don't be afraid to add something simple like this, it can improve your game's latency hiding even over a LAN.

Quote:

btw.. how often do packages get lost and what's the cause of these losses?

Two causes:
1)the data in the packet is corrupted somewhere in-transit. The computer drops the packet rather than give you corrupt data. This is usually a relatively rare event, dialup suffers the worst.

2)The network is congested. There's a lot of competing traffic, or you're sending data faster than the network can handle it. Routers will start dropping packets if they can't handle them all.

[EDIT]You're probably going to want to run client-side game logic, the coding example above assumes that you are.

__________________________________________________

orz
Member #565
August 2000

Quote:

yeah,, but i could make it an option right?(the dead reckoning and smoothing algorithms) and i plan to optimize this game for lan so using the server for everything and having a very high frequent refresh rate, would that be ok?

Certainly the prediction algorithms can be optional to some degree. But client CPU used for prediction is not usually the limiting factor. Bandwidth, latency, and client graphics speeds are more common limiting factors.

Quote:

lets say the server refreshrate is 75 times per second and i force the screen refresh rate to 75 on all computers, it would look nice right?. and there would be no need for dead reckoning and those things rigth? EDIT:(no, even better: the server gets the screen refresh rate of the clients and then send them updates according to their screen refresh rates.).

Bad idea. For multiple reasons:
1. When you synchronize frequencies to the screen refresh, you end up with seriously ugly artifacts unless you also synchronize phase with the screen refresh too. Which (editted) may be diffult in this case where network variation is present. And many monitors can't do 75 hertz at many frequencies.
2. 75 updates per second means 75 packet header overheads per second. Typically the per-packet overhead is in the neighborhood of 30 or so bytes. Multiply that by 75 to get your byte overhead per second, and by 8 to convert to bits, and you get an overhead of 18 kilobits per second to 24 kilobits per second; most of the bandwidth of many analog modems. Remember that's packet header overhead alone, not counting any game data.

Quote:

btw.. how often do packages get lost and what's the cause of these losses?

This varies widely with internet connection and time. As a general rule, on any decent connection most packets will get through, and those that don't get-dropped-and-then-automatically-resent will usually have similar latency to each other (and thus be approximately in order if you're sending with at least a small delay between packets). However, when packets do get dropped, several may get dropped in a row. And the characteristics of a network connection may change over time, even in the course of a single game.
As for why it happens, because the internet is intended to work that way. Packets get sent over a mesh of routers, and don't have bandwidth preallocated for them or anything like that usually. Therefore, there's no way to tell if enough bandwidth will be available for them at transmission time, and sometimes a router somewhere on the route a packet takes just won't have enough bandwidth along the route desired to send the packet further or buffers to store it until it does.

Trezker
Member #1,739
December 2001
avatar

Quote:

But if you make em yourself you'll really know what you're dealing with

Uhm.. no. You won't know what you're dealing with until you've been working with it for years.

Zoidcom has done all the years of failure for you so you only have to worry about success. ;)

Albin Engström
Member #8,110
December 2006
avatar

David McCallum: nice,

orz: ok, ok and ok :).

Trezker: ^^' understood.

Go to: