Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (581)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  Questions on Network Implementation  (Read 4638 times)
0 Members and 1 Guest are viewing this topic.
Offline dgallowscalibrator

Innocent Bystander





« Posted 2012-11-13 04:21:48 »

So I am going to make a Live Action Networked Game (or at least a template for one) and would like some guidelines for how to implement it in theory.

Here's what I've gotten from the things I've read so far -

You have a server with an authoritative game state from some time in the past Si. At set intervals, for any period of time in which it has inputs from all of its clients, it will simulate the game state to a new authoritative state at time Sf, and then send this to all of its clients.

The clients will then revert their game states to Sf, discard all cached inputs before Sf, and then use the remaining ones to interpolate the game state up to time N, the actual current game time. To simulate the other client players, they will simply guess based on the last input given to them.

Whenever the clients update, they will continue to cache inputs for that period of time, and also send their inputs to the server.


So does that sound about right? Is there anything I can do to improve how a client guesses what the other clients are doing? Or just improve it in general?

Additionally, I am not sure whether or not I should use UDP or TCP. I know UDP is generally faster. However the server always needs to guarantee that it receives every client input, so I do not think UDP all by itself is reliable enough. Would it be worth it to implement some sort of reliability layer on top of UDP, or to just use TCP instead? And if so, what would be the best way to go about this? Is there a good library for Java that handles this kind of thing already?

Thanks in advance.
Offline Jimmt
« League of Dukes »

JGO Kernel


Medals: 118
Projects: 4
Exp: 3 years



« Reply #1 - Posted 2012-11-13 05:27:49 »

http://www.java-gaming.org/topics/udp-vs-tcp-ip/608/view.html
Interesting discussion, but the first couple of pages are a bit outdated.
For ease of use I would suggest just using TCP. It's not like it's that slow.
Offline Agro
« Reply #2 - Posted 2012-11-15 05:21:51 »

TCP is 99.99% reliable as far as I know. Its a bit slower because its guaranteed to reach the endpoint. However, datagram sockets(UDP) are just shipped off and never thought about again.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Jimmt
« League of Dukes »

JGO Kernel


Medals: 118
Projects: 4
Exp: 3 years



« Reply #3 - Posted 2012-11-15 05:41:00 »

Basic summarization of UDP:
If you are ok with data disappearing forever then use it.
Offline sproingie
« Reply #4 - Posted 2012-11-15 08:26:18 »

UDP is also great matter order if of doesn't packets your the

Offline Roquen
« Reply #5 - Posted 2012-11-15 08:31:02 »

The only thing that's changed is network speeds.  The base issues of UDP vs. TCP are the same now as always.
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #6 - Posted 2012-11-16 01:40:16 »

UDP is also great matter order if of doesn't packets your the
Ha! I was confused for a while there then I noticed the pun....nicely played Smiley

Offline Alan_W

JGO Knight


Medals: 8
Projects: 3


Java tames rock!


« Reply #7 - Posted 2012-11-16 04:28:08 »

Having dabbled a bit, some thoughts based on my limited experience...

UDP is good for peer-peer, as you can use UDP punch-thru to get through the NAT in routers.  For real-time games, my choice is for each client to maintain a database of objects including position, velocity and last update time.  The positions are locally updated based on velocity.  When a UDP packet arrives for that object, the position data in that object is adjusted based on the velocity in that incoming object, for the time difference between the server and the client.  The local database is then updated with the corrected position and the (unchanged) in-coming velocity.

Measuring Lag is a problem. It's required for real-time games for lag-compensation. It is possible to measure round-trip delay to a server and use that to lock local time to a common time source.  This really needs incoming packets to be time-stamped immediately on receipt, which is a problem if the OS sticks them in a FIFO with a large random delay before the user process gets them.  My mileage has varied a bit here.  This also pre-disposes that lag is symmetrical upstream and downstream, which is unlikely, particularly if you are using a satellite dish for receive.  Anyone know how to do this better?

The problem with UDP comes when you have one-off event data to transmit around.  The choice is either to use TCP, or to implement your own guaranteed delivery service over UDP.  For a client-server implementation, then TCP works well, and would be my choice for turn based games (non real time).  For anything that does peer-peer then it's a case of grow-your-own on top of UDP, so as to be able to use UDP punch-thru.

Incidentally peer-peer sucks for security.  To reduce hacking, all decision logic must be on a server, which tends to mandate a thin client approach.  Of course you have to pay for the server bandwidth, so this is more appropriate for play-to-play games.  My hobby efforts have focused more on peer-peer with distributed decision making, and limiting server bandwidth to a time server and NAT punch-thru introducer.  That way uses less server bandwidth.  However a regular keep-alive ping is still required to keep track of game joiners/leavers.

I also had a go at LANplay, using multicasting.  That works peer-peer and you don't have to worry about NAT as you are all on the same segment.   No need for lag compensation either.  However in these internet gaming days, no one can be arsed to take their computers over to a friends and set up an impromptu net for LANplay, so really it's more of historical interest.

Time flies like a bird. Fruit flies like a banana.
Offline Roquen
« Reply #8 - Posted 2012-11-16 07:48:48 »

TCP is for receiving nominally reliable datagrams which are seen in order.

UDP is for everything else since you can build whatever functionality ontop of it.

The best way to choose between them is to use a library which meets your needs.
Online Nate

JGO Kernel


Medals: 129
Projects: 3
Exp: 14 years


Esoteric Software


« Reply #9 - Posted 2012-11-16 10:23:13 »

Flow control. Use TCP.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline princec

JGO Kernel


Medals: 284
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #10 - Posted 2012-11-16 11:11:10 »

Riven and I have been having a very interesting time making a networked multiplayer game. We're about 2.5-3 months in to it, although Riven only started full time maybe 6-7 weeks ago, when we really started solving the problems. I say "problems" but really most of it is "design"; "problems" are what comes when "design" isn't right Smiley

For the first few weeks I was just mostly prototyping and experimenting with designs on my own with a lot of input from Riven which I kinda ignored so that I could, well, experiment. It turns out though that he was basically right on a number of things.

Firstly, UDP is hard to do. Especially if you're going to actually do it how you're meant to do it, which generally involves sending a delta against some known state that we understand the client has. It turns out that keeping track of the known state of a client is quite tricky if you're never sure exactly what data has been received and when it was received. I eventually solved this problem, using a system very much like the "Quake 3 networking model", but I have to say, the code was so complex and nasty I did not like the look of it one bit, and it was very hard to maintain and refactor.

So eventually we switched to TCP on Riven's advice; and it's worked out much more simple for us, as we now no longer have to worry about out-of-order packets and resending ourselves; instead TCP takes care of that, in the actually rare circumstances in which packets actually get lost these days. All we've really got to be careful about is not sending so much data that a backlog starts to grow between server and client that it can never empty. The whole design of the system got a whole lot simpler from this point onwards as a result of the net code being so much easier. We've implemented something that looks a bit like half-duplex RMI, but extremely efficiently implemented.

These days over broadband the actual overhead of a TCP packet is almost irrelevant compared to the overall efficiency of the protocol and design itself. The only reason we had for using UDP was that we could implicitly discard stale state and just keep sending deltas versus some known state, however as we discovered that actually making deltas is a massive, massive problem in itself, solved completely simply by using reliable data delivery, TCP was the way to go. Latency is excellent - certainly barely noticeably any different from UDP - and we're also free to send "big data" without confusion eg. map chunks.

Cas Smiley

Offline Alan_W

JGO Knight


Medals: 8
Projects: 3


Java tames rock!


« Reply #11 - Posted 2012-11-16 22:26:02 »

One thing to remember is that if you use TCP/IP and send 10 packets, of which packet 1 is lost, then packets 2 through 9 are held up on the stack, while the missing packet 2 is re-requested and re-transmitted.  If you send stuff over the internet it goes through a number of IP stacks, any of which can cause lag to a whole series of packets due to a single packet loss.  It's really a horses for courses thing, nether UDP not TCP/IP is better overall.

Time flies like a bird. Fruit flies like a banana.
Offline sproingie
« Reply #12 - Posted 2012-11-16 22:29:35 »

Packet loss in TCP starts to becomes an issue under severe congestion, but it should also be noted that under those same conditions, packet loss for UDP tends to be catastrophic.
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #13 - Posted 2012-11-16 22:37:09 »

I still prefer using UDP for real time networking though and I used a lot of ideas from this article by Valve.

Offline matheus23

JGO Kernel


Medals: 98
Projects: 3


You think about my Avatar right now!


« Reply #14 - Posted 2012-11-16 22:54:11 »

I still prefer using UDP for real time networking though and I used a lot of ideas from this article by Valve.

You wrote a real time networking game with UDP?  persecutioncomplex not bad.

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #15 - Posted 2012-11-16 22:55:47 »

Well it wasn't a full featured game, it was just a bunch of players armed with guns. It worked surprisingly well with people from all over the US and Europe! Smiley

Offline Agro
« Reply #16 - Posted 2012-11-16 23:18:26 »

Just a question, its probably extrapolation, but what is the best way to send "positions" to a server to make it as much as sync as possible?

Offline matheus23

JGO Kernel


Medals: 98
Projects: 3


You think about my Avatar right now!


« Reply #17 - Posted 2012-11-16 23:22:19 »

Well it wasn't a full featured game, it was just a bunch of players armed with guns. It worked surprisingly well with people from all over the US and Europe! Smiley

This could be very useful code, you know! and... ...  Roll Eyes ... Grin  Roll Eyes

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #18 - Posted 2012-11-16 23:28:01 »

Just a question, its probably extrapolation, but what is the best way to send "positions" to a server to make it as much as sync as possible?
You cannot send positions from the client to the server simply because you cannot trust the client. You would have to send input data to the server that makes sure they are valid and applies them.

Offline Agro
« Reply #19 - Posted 2012-11-17 00:13:50 »

Well, yeah, I got that part, but what would be the most efficient way to get the most synchronized position over a network as possible?

Offline Alan_W

JGO Knight


Medals: 8
Projects: 3


Java tames rock!


« Reply #20 - Posted 2012-11-17 00:16:34 »

Packet loss in TCP starts to becomes an issue under severe congestion, but it should also be noted that under those same conditions, packet loss for UDP tends to be catastrophic.

I was trying to say that for a real time game, those delayed TCP/IP packets may as well be dropped because they are too late to be useful.  Provided each UDP packet is useful as a stand-alone update, it is possible to design to withstand packet loss.  When a packet is lost, the screen object has to continue on a bit longer on dead reckoning.

Edit: You can see this in my 2011 Mage Wars entry for Java4k (Source code available), although being a 4k game, it's not very well structured.

Time flies like a bird. Fruit flies like a banana.
Online theagentd
« Reply #21 - Posted 2012-11-17 01:58:18 »

My philosophy here: I will need reliable data transfer somewhere in my game, and I don't think my lone brain is superior to the sum of all brains that have worked on TCP, so reimplementing TCP over UDP sounds pretty stupid when there's a perfectly fine solution just sitting there that's easier to use and has been improved/perfected since before I was born.

Myomyomyo.
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #22 - Posted 2012-11-17 02:12:39 »

My philosophy here: I will need reliable data transfer somewhere in my game, and I don't think my lone brain is superior to the sum of all brains that have worked on TCP, so reimplementing TCP over UDP sounds pretty stupid when there's a perfectly fine solution just sitting there that's easier to use and has been improved/perfected since before I was born.
What about reliable unordered data transfer? I had an article around here that explained how to do it.....

EDIT: AHA! http://gafferongames.com/networking-for-game-programmers/
Amazing tutorials explaining lots of stuff about networking and physics and both at the same time!

Offline sproingie
« Reply #23 - Posted 2012-11-17 02:17:56 »

What about reliable unordered data transfer?

SCTP would have been a nice contender for that, had it ever gained enough momentum.  I'd say at this point it's too late for SCTP to go anywhere though. Sad

Offline Alan_W

JGO Knight


Medals: 8
Projects: 3


Java tames rock!


« Reply #24 - Posted 2012-11-17 08:46:04 »

What about reliable unordered data transfer? I had an article around here that explained how to do it.....

EDIT: AHA! http://gafferongames.com/networking-for-game-programmers/
Amazing tutorials explaining lots of stuff about networking and physics and both at the same time!

Thanks, great article. I didn't know the bit about parallel TCP streams increasing UDP packet loss and the section on reliable UDP communication is gold dust.  I had been assuming that the best solution would be to use parallel UDP and TCP/IP streams so as to get the best of both worlds.  I'm bookmarking this for a more thorough read.

Edit:  The TCP/IP Sync causing UDP packet loss is interesting.  However I think it might not matter so much if a parallel TCP/IP connection was only used for low bandwidth reliable data (e.g. inventory changes).  It looks like using TCP/IP for dynamically downloading map segments, whilst simultaneously using UDP for real-time play, is a poor idea.  It's also interesting to see that UDP packet loss increases massively once the packet size reaches 160 bytes.  There is clearly a trade off between packet overhead and packet loss.

Edit 2: The comments on the article make an interesting read too. Several people note that MMORPGs often use TCP/IP.  That does make sense considering they are heavily event driven.  However I used to play WoW several years ago and the lag was something awful, when an area got busy.

Time flies like a bird. Fruit flies like a banana.
Offline Roquen
« Reply #25 - Posted 2012-11-17 13:31:13 »

NETWORKING: One more reason to run simulations at fixed rates.  As if the list wasn't long enough.  Note, attempting to be FP deterministic is crazy.
Online theagentd
« Reply #26 - Posted 2012-11-17 22:06:32 »

Note, attempting to be FP deterministic is crazy.
Huh? Is that really so difficult with Java? strictfp anyone?

Myomyomyo.
Offline ClickerMonkey

JGO Coder


Medals: 20


Game Engineer


« Reply #27 - Posted 2012-11-18 00:59:40 »

I love this topic!

Firstly, I want to briefly talk about a protocol on top of UDP I've created that I think is useful.
Secondly, I made a simple networked game (using UDP) all in a few hours last night with interpolation and extrapolation - I'll post some code.

A few concepts:
  • Multiple "channels" can be setup to differentiate between reliability and order.
  • A channel is marked as unreliable or reliable, and ordered or unordered.
  • A command is sent through a channel, has a retry count, a priority, has a determinable size in bytes, and can be read/written to a ByteBuffer
  • A packet is formatted [protocolId][sequence][ack][ackuence][command id+channel][command data][command id+channel][command data...]
    Where sequence is the remote packet sequence, ack is the last packet sequence received by the remote address, ackuence is 32-bits which stores which of the past 32 packets have been received by the remote address.

The strength of this system lies in the amount of data you send that you don't care about. The more of that there is, the better this system performs over TCP (plus TCP acks one at a time, this does 32).
This is a library I've developed for my game engine, I'm going to have it available separately however.

Anyway, onto my experimentation last night!

The world consists of ships with position, velocity, direction:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public class Player extends SteerSprite
{
   public byte id;
   public String name;
   public long lastUpdateTime;
   public float ping;
   public float time;
   public Tween<Vec2f> tweenPosition = new Tween<Vec2f>( new Vec2f(), new Vec2f() );
   public Tween<Vec2f> tweenVelocity = new Tween<Vec2f>( new Vec2f(), new Vec2f() );
   public Tween<Vec2f> tweenDirection = new Tween<Vec2f>( new Vec2f(), new Vec2f() );
   public Vec2f position = new Vec2f();
   public Vec2f velocity = new Vec2f();
   public Vec2f direction = new Vec2f();
}


When I get the command that someone has joined, I do this:

1  
2  
3  
4  
5  
6  
Player p = new Player();
p.id = joined.id;
p.name = joined.name;
p.lastUpdateTime = System.currentTimeMillis();
p.time = 0;
p.ping = INTERVAL_CLIENT * 0.001f; // expected (INTERVAL_CLIENT = 50 which means 20 packets per second)


When I get the command that someone has updated, I do this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
long lastUpdateTime = p.lastUpdateTime;
p.lastUpdateTime = System.currentTimeMillis();
p.time = 0;
p.ping = (p.lastUpdateTime - lastUpdateTime) * 0.001f;  
// important for smoothness, the beginning of the tween should start in the players current position
p.tweenPosition.start.set( p.position );
p.tweenDirection.start.set( p.direction );
p.tweenVelocity.start.set( p.velocity );
// the most recent position, velocity, and direction
p.tweenPosition.end.set( update.x, update.y );
p.tweenDirection.end.set( update.dx, update.dy );
p.tweenVelocity.end.set( update.vx, update.vy );


And most importantly, here's my update code:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
p.time += gameState.seconds; // deltatime
           
if ( p.time <= p.ping )
{
   // Interpolate
  p.tweenPosition.set( p.position, p.time / p.ping ); // basically p.position = (p.tweenPosition.end - p.tweenPosition.start) * (p.time / p.ping ) + p.tweenPosition.start
  p.tweenDirection.set( p.direction, p.time / p.ping );
   p.tweenVelocity.set( p.velocity, p.time / p.ping );  
}
else
{
   // Extrapolate
  Vec2f subp = Vec2f.sub( p.tweenPosition.end, p.tweenPosition.start );
   Vec2f subd = Vec2f.sub( p.tweenDirection.end, p.tweenDirection.start );
   Vec2f subv = Vec2f.sub( p.tweenVelocity.end, p.tweenVelocity.start );
           
   p.position.add( subp, gameState.seconds ); // deltatime
  p.direction.add( subd, gameState.seconds );
   p.velocity.add( subv, gameState.seconds );
}


Results in perfectly smooth movement! However, the state of the ship you see on screen is out of date... but its worth the smoothness.

Hopefully this is helpful to someone....

Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #28 - Posted 2012-11-18 01:34:51 »

Note, attempting to be FP deterministic is crazy.
Huh? Is that really so difficult with Java? strictfp anyone?
Yup, it's quite important to use strictfp in multiplayer games. It's very slightly slower but less pain in your ass.

Offline Roquen
« Reply #29 - Posted 2012-11-18 08:36:00 »

Note, attempting to be FP deterministic is crazy.
Huh? Is that really so difficult with Java? strictfp anyone?
Actually it is harder than that.  And worse is not a good idea...if fact it's a terrible idea except in some very narrow scientific computations which won't be using primitive types anyway.  Bit-exact FP = higher errors & slower performance (over prims).
Pages: [1] 2
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (64 views)
2014-04-15 18:08:23

BurntPizza (62 views)
2014-04-15 03:46:01

UprightPath (75 views)
2014-04-14 17:39:50

UprightPath (58 views)
2014-04-14 17:35:47

Porlus (76 views)
2014-04-14 15:48:38

tom_mai78101 (101 views)
2014-04-10 04:04:31

BurntPizza (161 views)
2014-04-08 23:06:04

tom_mai78101 (256 views)
2014-04-05 13:34:39

trollwarrior1 (209 views)
2014-04-04 12:06:45

CJLetsGame (216 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!