Udp server too slow? - java

So im doing an MMO, i was progressing alot, 6 months progrramming this thing.
The problem is that i was testing offline my game, today i have the brilliant idea to port foward my server and make it online, i knew it was gonna be slighty slower, but its awful! too much lag!!! the game is unplayable.
Im managing my packets like so....
Player wants to move up, client send movePacket to the server, the server recieve it, move the player in the server and send the new position to all clients...
Each time a monster move, the server send a the new position to all clients...
I thought i was over sending packets, but i test it just with the movement of the player... it seems to have a significant delay to recieve the packet and sending them to the client....
Im I doing this whole thing wrong?

Lag is always a problem with online games. While your current method is the standard way of doing things, as your finding out the lag becomes unbearable (a common problem in 1990's and early 2000's games). The best approach to take is the same approach that almost all modern games take which is do as much as you can client side and only use your authoritative server to resolve differences between predictions that clients make. Here are a some helpful ways of reducing perceived lag:
Client-side prediction
For an MMO this may be all you need. The basic idea of client-side prediction is to locally figure out what to do. In your game when Player wants to move up he sends a packet that says [request:1 content:moveup] then BEFORE receiving a response from the server, the client displays Player moving up one (unless there you can already tell that such a move is invalid i.e. moving up would mean running into a wall). If your server is really slow then Player may also move right before receiving a response so your packet next packet may look like [request:2 content:moveright] at which point in time you show your player to the right. Keep in mind at this point Player has already moved up and right before the server has even confirmed that moving up is a valid move. Now if the server responds that the new player position after packet 1 should be up and the position after packet 2 should be right then all is well. However, if lets say another player steps happens to be above Player then the server may respond with the player in a new location. At this point Player will 'teleport' to wherever the server tells him he's supposed to be. This doesn't happen often but when it does happen it can be extremely noticeable (you've probably noticed it in commercial fps games).
Interpolation
At this point your probably fine for a MMO game but in case it isn't (or for future reference) interpolation is your next step. Here the idea is to send more data regarding rates at which values change to help make the movement of other players smoother. This is the same concept as using a taylor series in mathematics to predict values for a function. In this case you may send position as well as velocity and maybe even acceleration data for all the entities in the game. This way the new position can be calculated as x = x + v*t + 0.5*att where t is the frame rate. Again, you show the player's predicted position before the server actually confirms that this is the correct position. When the next packet from the server comes, you'll inevitably be wrong most of the time but the more rate data you send, the less you'll be off by and thus the smaller the teleportation of other entities is.
If you want a more detailed outline of how to deal with lag in online games read the mini bible on multiplayer games: http://www.gabrielgambetta.com/fast_paced_multiplayer.html

Related

Should game logic be on client or server?

I'm creating a simple multiplayer turn-based game.
I can't decide where to draw the line between putting all the logic on the client or on the server.
Should the client be used just to send input to the server and print/display the responses?(This is my current solution, but seems to make the client too "stupid")
If not, how do I decide what goes on which side?
The game is very simple so I do think I could have any lag or bandwidth problems in any case.
You should always put all the game logic you can in the server, as clientside can be modified and cheat. Never trust the client.
Think of the server as the "game" and the client as the "player". Keep the client as minimal as possible. Restrict the client's influence on the game as much as you can. The client should really only be able to ask to do this and do that, it shouldn't be able to decided for itself what the result of a move be.
A real world example where the client behaved as the server was Halo 3 multiplayer where the game chose a player, part of the match, as the host (server).
Cons:
Players could lag switch other players and cause them to lag. Those players couldn't do anything and the host player just killed them and won the match.
Players chosen as hosts had bad internet and so everyone lagged to the point where a new host had to be selected.
If the host player left the game the match would stop and try to find another host (player) which wasn't always successful or take minutes.

Syncing Two Metronomes In Java using Bluetooth for Android

I have a bit of a unique issue. I'm collaborating with several other Computer Science Majors at my university on an Android Metronome app that allows two users with the app to sync metronomes. Right now, I can send the desired beats per minute of the metronome from one phone to the other and both phones will start to play their respective metronomes. Due to the latency of Bluetooth, the metronomes are only in sync about 20% of the time.
So, here's where the problem is. We're trying to make it so both of the metronomes will start at the exact same time. One way I've thought of doing this is once the first user presses the send button on their phone, a time stamp will be created. This time stamp will be exactly two seconds after the user presses the send button. The time stamp will then be sent to the second phone and the phone will utilize this time stamp to start it's metronome at the same exact time as the first phone. I've tried accomplishing this by putting UTC time in a while loop and then constantly checking the time, to no avail. Does anyone have any ideas as to how we can go about implementing this? I couldn't find any similar problem on StackOverflow, or any other website for that matter.
It's a bit late probably for your project, but if interested. This is a bit long, it's more like a case study.
If your project was about syncing two device clocks remotely, then this won't help you, but if it was about syncing the metronomes, then this may be a start.
First, getting millisecond accurate timings and callbacks in android using java is next to impossible, since android is not a real time system ( All sleep methods and timer might not execute on the exact millisecond you're expecting ). You may want to go with NDK for triggering your beat events, because native threads in android can achieve that, but if you're happy with your single metronome implementation, then that's good enough to read the rest of this .
Full disclosure :
I am the author of JAM the app referenced in the answer I just published a few days ago.
I ran into the same problem when developing the app.
And whether this answer will help you or not, depending on your situation.
and if you're going down the "clock sync" route ( Which I do plan on exploring to improve my app down the road with more features ) but the solution that I found did not involves time sync.
I will mention my approach and then state what I found as advantages/disadvantages for each of the methods .
Instead of syncing clocks ( A very difficult problem, especially for what the app was supposed to do , and that is trigger ticks on multiple devices at the "same" time ) I opted for a subscribe/publish model, where multiple devices can "subscribe" to a host device via bluetooth, and the host device controls and "publishes" the metronome beats.
most times sending a few hundred bytes ( Enough information about each beat ) via bluetooth takes less than 2ms , it could spike up to 10 and sometimes even 30, but that rarely seems to happen .
That approach took care of the syncing problem, now I can send beat events from one device to another in 2ms , and if some sort of delay happened, it will self correct once the interference is gone, because the other event comes in time.
However that approach does require constant connection, you can't start and separate the devices later on, but it's much easier to implement.
Now the interesting part, the problem I never thought of when starting this, and that was the Android 10 millisecond audio path latency problem. I'm not affiliated with superpowered, but I did use their engine in my app to deal with that problem .
To summarize :
Metronome sync over bluetooth in Android has two issues :
1 - triggering beat events simultaneously ( or within acceptable latency )
2 - The beat event should trigger sound events with minimal delay after the beat event is received
#1 is related to the original question, #2 I thought was an important addition to the original problem this question is asking.
I would use (S)NTP to check the clock drift to a public time server. After that I would just send the interval and a start time and let the devices calculate the interval individually. So you just need to sync changes and relay on the clocks of the individual devices. Together with the now known clock drift you can fix this error.

Java Game Networking with Kryonet: Bare-bones packet transfering

I'm using Opengl and Jbox2d to write a real-time 2d game in Java.
I want to start coding the networking components.
Although it uses box2d, my game is very small and I want to create a bare-bones architecture using the Kryonet library.
The program itself is a 'match game' like chess. The most logical system I can think of would be to have dedicated server that stores all player data.
PlayerA and PlayerB will connect with the dedicated server which will facilitate a TCP link between their computers.
When the match is complete, both players will communicate the resulting data back to the dedicated server, which will authenticate and then save over their respective player data.
For those familiar, Diablo2 implemented a similar setup.
I want this TCP connection to simply send the shape coordinates Vector data from the host (lets say playerA) to the client (player B) which the client will then render on its own.
Then I want the client to send mouse/keyboard data back to the host. All of the processing will be run on the host's computer.
My first question: Are there any flaws in this network logic?
My second question: How does one implement barebones server/client packet transferring (as described) using Kryonet?
Note: I have done this exact type of packet transferring in C++ using a different library. The documentation/tutorials I've found for Kryonet are terrible. Suggesting another library with good support is an acceptable answer.
I know this is an old question, and I'm sure OP has gotten their answer one way or another, but for fun I thought I'd respond anyway. This exact question has been on my mind since I've been playing around with game development using Kryonet very recently.
Some early network games, such as Bungie's Marathon (1994) seemed like they did exactly this: each player's events would be sent using UDP to other players. Thus, if a player moved or fired a shot, the player's movement or shot's direction, velocity, etc. would be sent to other players. There are some problem with this approach. If one of the player's actions are temporarily lost over the network, a player or players appeared to be out of sync with everyone else. There was no "truth" or "reconciliation" of game state in such situations.
Another approach is to have the players compute their movements and actions client-side and send the updated positions to the dedicated server. With a server receiving all player state updates, there is an opportunity to reconcile them. They also do not become out of sync permanently if some data is lost on the network.
To compare with the previous example, this would be equivalent of each player sending their positions to the server, and then having the server send each player's position to all the other players. If one of these updates gets lost for some reason, a subsequent update will correct for it. However, if only key presses are sent, a single lost keypress throws the game out of sync because all clients are computing the other clients' positions separately.
For action games you can use a hybrid approach to minimize apparent lag. I've been using Kryonet successfully in this manner for an action game. Each player sends their state to the server at every render tick (though this is probably excessive and should be optimized). The state includes position, number of shots left, health, etc. The player also sends the shots they take (starting velocity and position.)
The server simply echos these things back to clients. Whenever a shot is received by a client it is computed client-side, including whether or not the shot hits the receiving player. Since the receiving player only computes their own state, everything appears to stay in sync from their own point of view. When they are hit, they feel the hit. When they hit another player, they believe they've hit the other player. It is up to the player "receiving" a shot to update their health and send that info back to the server.
This does mean that a shot could theoretically lag or "get lost" and that a player may think their shot has hit another player, while on the other player's screen no hit occurred. But in practice, I've found this approach works well.
Here's an example (pseudocode, don't expect it to compile):
class Client {
final Array<Shot> shots;
final HashMap<String, PlayerState> players; // map of player name to state
final String playerName;
void render() {
// handle player input
// compute shot movement
// for shot in shot, shot.position = shot.position + shot.velociy * delta_t
// if one of these shots hits another player, make it appear as though they've been hit, but wait for an update in their state before we know what really happened
// if an update from another player says they died, then render their death
// if one of these shots overlaps _me_, and only if it overlaps me, deduct health from my state (other players are doing their own hit detection)
// only send _my own_ game state to server
server.sendTCP(players.get(playerName));
}
void listener(Object receivedObject) {
if(o instanceOf PlayerState) {
// update everyone else's state for me
// but ignore my own state update (since I computed it.)
PlayerState p = (PlayerState)o;
if(!p.name.equals(playerName) {
players.add(p.name, p);
}
} else if (o instanceof Shot) {
// update everyone else's shots for me
// but ignore my own shot updates (since I computed them.)
Shot s = (Shot)o;
if(!s.firedBy.equals(playerName) {
shots.add(s);
}
}
}
}
class Server {
final HashMap<String, PlayerState> players; // map of player name to
void listener(Object receivedObject) {
// compute whether anybody won based on most recent player state
// send any updates to all players
for(Connection otherPlayerCon : server.getConnections()) {
otherPlayerCon.sendTCP(o);
}
}
}
I'm sure there are pitfalls with this approach as well, and that this can be improved upon in various ways. (It would, for example, easily allow a "hacked" client to dominate, since they could always send updates that didn't factor in any damage etc. But I consider this problem out-of-scope of the question.)

Identifying threads in game (TCP related also)

This is a school project, please do not provide any code, I am only looking for hints to guide me in the right direction.
Write and test a game server that clients subscribe to. Once subscribed, the client receives
a list of games (the same game, just different 'instances' of it) currently in play. The client may then elect to join a game or start a new
one. A game must have at least two players before actually starting. The system must support multiple clients all playing one game, or multiple clients playing multiple games.
The objective of this project is to gain experience in Java, TCP, and threading.
My current design and implementation has 2 files: server.java and client.java
The server file has 3 classes: Server, Lobby and Game
The client file has 1 class: Client.
The implementation of the "game" is trivial, I am fine with that.
Currently, the server class establishes the TCP connection with the client class.
Each time a client is instantiated, the socket is accepted in the server class, and the program continues.
Continuing on, the server class creates the lobby class.
The lobby class is where I am having trouble with. By default, I am creating 1 "game" object, and passing in the clientSocket:
game g = new game(clientSocket, playerID);
g.start();
The game class extends thread, which I think is the correct way of doing it. Each "game" will be a separate thread, so to speak, so players A and B can share 1 thread, and players C and D can start a new game with another thread.
I am new to threads, but this is the best implementation I could think of. I ruled out having multiple threads for lobby's, since that doesn't really make sense, and multiple threads for clients is pointless too, so I think multi-threading the games class is ideal.
Right now, when I create 2 instances of the client, they are both joining the same 'thread' (they are both in the same game and can talk to each other).
How am I supposed to do it so that, a new player can type "new" or whatever in the lobby and create a new "game", where it's a new thread.
I'm sure I mis-understood certain parts about threading or whatnot, but I appreciate any help.
I wouldn't map games to threads. Instead, map clients to threads. Each client will have their own thread that does work initiated by the receipt of commands from that client. When you need to create a new game, just create a new object in a shared collection of games. Track, in the client instance, which game, if any, it's associated with.
If you find you really do need a thread to manage a game, then you can create one. When a client sends a command to a particular game, just put that command on a queue of commands that's read by the thread managing that game. The game thread only needs to know which game it's managing. It can terminate itself when that game is finished.
Firstly, I would suggest you read on multiplayer game development and networking in Java (UDP/TCP). I am no game-developer but simply happenned to take a Java networking course in college and had a similar project (a networked game).
Secondly, dealing with multiple threads is proportional to complexity. You want to minimize complexity. I would suggest to abandon an "I have to find a place to use threads" mentality. (Don't force a square peg in a round hole ;))
Continuing, following through the requirements:
Write and test a game server that clients subscribe to.
IIRC, this is fairly straightforward (and you're probably past this part).
Once subscribed, the client receives a list of games (the same game, just different 'instances' of it) currently in play
This should be fairly straightforward as well since a TCP connection between the server and client have been established already.
However, there are a couple of things to understand at this point. The most important, perhaps, is that there will be a single central server that will hold information on all connected clients and existing games. This consequently means that it has to be the one to deal with the state of the system (e.g. tracking currently existing gamerooms), client requests (to create/join gamerooms), as well as updating clients with relevant info on the system's state (e.g. created/closed gamerooms).
Another consideration at this point is the scope of client's functionality in the system. A typical implementation would probably be a fat-server, thin-client architecture. Basically, this means that a client does no real processing of data (from user input) and instead relies on the server. Most of the time, then, the client is only waiting for input from user or a response from the server. On the otherhand, the server deals with the processing of data from clients, updating the system state (including individual game states), and notifying concerned client of relevant changes in the system/game state.
The client may then elect to join a game or start a new one
What actually happens here is a client sending data "I elect to join a game" or "I elect to create a game" to the server. The server acts on this and notifies concerned clients (I say concerned and not all since some clients could possibly be playing and do not need to know whether new games have spawned).
A game must have at least two players before actually starting.
-
The system must support multiple clients all playing one game, or multiple clients playing multiple games.
Again depending on the client-server architecture, either the server will be doing all the processing (fat-server, thin-client) or the clients (thin-server, fat-client) do the processing while the server mainly serves as a relay point to other clients. I have no definite (or even confident) suggestion on this, however, as I am simply overwhelmed by the sheer number of possible implementations and their consequences. Thus, I can't really encourage enough to read more on networking and game development. Individually, those 2 topics are incredibly vast, much more when combined.
Lastly, with regards to the use of threads. IIRC, dispatching separate threads for opened sockets are useful in preventing the application from getting blocked waiting for input. I don't really agree with your idea of "hosting" a game in a thread but since you're in school I can only admire your trying things out.
This may help you further: Lesson: All About Sockets. And you might perhaps also be interested in UDP.

Server providing real time game status updates

Currently my game server is small (one area and ~50 AI) and each time it sends out state update packets (UDP), it sends out a complete state to each client. This creates a packet size of ~1100 bytes. Pretty much all it sends is the following information for all entities:
int uid
int avatarImage
float xPos
float yPos
int direction
int attackState
24 bytes
Edit: More efficient structure
int uid
byte avatarImage
float xPos
float yPos
byte direction & attackState
14 bytes
but I am going to need to send more information eventually for the entities. For instance I am adding to this:
float targetXPos
float targetYPos
float speed
As more data is needed to be sent for each entity, I am fast approaching and most likely already passed the maximum size of the packet. So I am trying to think of a few possible ways to fix my problem:
1) Just build up the status update packet until I run out of room and then leave out the rest. Very bad client view. Not really an option.
2) Only send the data for the N closest entities to a client. This requires that each state update I calculate the closest N for each client. This could be very time consuming.
3) Some how design the packets so that I can send multiple for the same update. Currently, the client assumes the packets are in the following structure:
int currentMessageIndex
int numberOfPCs
N * PC Entity data
int numberOfNPCs
N * NPS Entity data
The client then takes this new data and completely overwrites its copy of the state. Since the packets are complete self contained, even if the client miss a packet, it will be ok. I am not sure how I will implement the idea of multiple packets for the same update, because if I miss one of them, what then? I can't overwrite the complete, outdated state with a update, partial state.
4) Only send the actual variables that change. For instance, for each entity I add one int that is a bit mask for each field. Things such as speed, target, direction, and avatarImage won't need to be sent every update. I still come back to the issue of what happens if the client misses a packet that did actually need to update one of these values. I am not sure how critical this would be. This also requires a little more computation on both the client and server side for creating/reading the packet, but not too much.
Any better ideas out there?
I would go with number 4 and number 2.
As you have realized, it is usually better to only send updates instead of a complete game state. But make sure you always send absolute values and not deltas, so that no information is lost should a packet be dropped. You can use dead reckoning on the client side to make animations as smooth as possible under crappy networking conditions.
You have to design carefully for this so that it is not critical if a packet is lost.
As for number 2, it does not has to be time consuming if you design for it. For example, you can have your game area divided into a grid of squares where each entity is always in exactly one particular square and let the game world keep track on this. In that case, calculating the entities in the 9 surronding grids is a O(1) operation.
This type of system is commonly solved using a Dead Reckoning or predictive contract algorithm. You can't depend on all clients getting updates at the same time, so you need to predict positions based on previously known values and then validate these predictions against server-generated results.
One problem I ran into sending delta updates (basically your 4th option), is that the data can be out of order or just old, depending on how concurrent your server is, basically race conditions of multiple clients updating the server at the same time.
My solution was to send an update notification to all the clients, with a bitmask setting a bit for each item that has been updated.
Then the client requests the current value of the specific data based on the bitmask, This also allows the client to only request data it is interested in.
The advantage of this is it avoids race conditions and the client always gets the latest value.
The disadvantage is it requires a roundtrip to get the actual value.
UPDATE to demonstrate the point I am trying to make.
Presume 4 clients A,B,C,D.
A and B send simultaneous updates to a mutable state X on the server Xa and Xb. As B gets in somewhat later than A the final state of X on the server is X= Xb.
The server sends out the updated status as it gets it to all clients, so C and D get the updated status of X, as the order of delivery is indeterminant C gets Xa then Xb and D gets Xb then Xa, so at this point the clients C and D have different ideas of the state of X, one reflects what the server has the other doesn't, it has deprecated (or old) data.
On the other hand if the server just sends out a notification that X has changed to all the clients, C and D will get two status change notifications for X. They both make requests for the current state of X, and they both end up with the final state of X on the server which is Xb.
As the order of the status notification is irrelevant as there is no data in it, and the clients issue a request for the updated state on each notification they both end up with consistent data,
I hope that is more clear as to the point I was trying to make.
Yes it does increase the latency, but the designer has to decide what is more important, the latency or having all clients reflecting the same state of mutable data. This will depend on the data and the game.

Categories