Is it best to communicate between two scrabble boards on separate computers by creating a cloud with a SQL table, simulating the board. And every time I move is made you contact the server and update the local board?
Sounds good to me. Scrabble doesn't require real-time millisecond precision, so using database transactions to consummate the board moves sounds like a good approach.
In your shoes, I'd try to formalize my states a bit more. If you think of it, a Scrabble game consists of:
A board
The coordinates on that board that give bonuses (x2 letter, x3 word, etal.)
The set of available letters, and the amounts of each letter available, and the point-score for each letter
A profile for each player
The set of letters in each Player's possession
The words each player has played, and where they are on the board
The player's current score
A dictionary of allowable words (for challenges)
A lot of this can be stored in an SQL database - for instance, a player's name and score. But an SQL DB might be too heavy for things like the board coordinates and how various bonuses map to various coordinates. If you think of it, these are static, read-only attributes that will never change from game to game. It might make sense to represent them as a serialized 2-D array, or something similar. Same goes for the dictionary of allowable words. In your shoes I'd be tempted to read the dictionary from a text file on server start-up, store the strings into a non-mutable array, and hand-code an ultra-fast binary search rather than suffer through the overhead of database calls to an indexed table.
Likewise the grab-bag of letters: do you really need a database for this? Maybe you do. Maybe you decide that, since the grab-bag represents mutable state that's going to be shared between all connected clients, you want to take advantage of your DB's locking mechanisms. Or maybe speed becomes an issue, so you find that an array or a list serves you better, and you're comfortable managing the thread-state yourself.
The point is that you won't know what to choose until you spell out what you're doing with some degree of precision. Then you can begin to consider the trade-offs.
Storing the board state in a central DB is fine - and good design. It's unclear how you are planning on having each client handle communications, you have a couple of options:
client 1 make a move, send details to server (persisting state in DB)
server pings client 2 notifying them that it is their move (use a remoting technology to ping)
Same as step 1 but for client 2.
Or
client 1 make a move, send details to server (persisting state in DB)
client 2 polls server until it notices that it is it's turn.
Same as step 1 but for client 2.
So, you have to consider whether you want 2-way client-server communication (client calls server, server calls client) or whether you want 1-way client server communication (clients calls server, including polling to determine when state has changed).
There are some good answers here but I would say it really all depends on what you have available. If you can assume that there is a central server available, then using it to keep track of game state would be a good idea, as it would not lock down the clients to any particular machine - they can go from one to another during the game if they wish. There would also be some extra security here, as you can detect clients that are trying to make illegal moves. And I'm sure there are other benefits too. The most obvious downside would be that this requires a server (i.e. a third piece of hardware, along with a web address and hosting, etc.).
If you can't make that assumption, there's really nothing wrong with making one client the 'server'. It just comes with different pros and cons.
As for using an SQL table, rtperson made some very good observations.
Related
I'm making a java 2D online game. I use a tiledmap and I've been thinking about a way to prevent map hack.
My idea is to send the player's map file (compressed) which contains all cells and collision cells to the server and to compare it with the original one (on the server).
If they are equals, the player can connect.
This way, the player can't remove collisions cells on their map.
Is it a good idea ? Is there better alternatives ?
This kind of approach to preventing cheating is as common as it is naive. How would your idea prevent a map hack? A hacked client could send the original map data but use the compromised map data. In general, a hacked client can fake any data you request from it, and there's nothing you can do about it.
If you want to validate player actions, you have to do it on the server side. If you want to limit player knowledge, you have to keep the information on the server and transmit only what the player should know. If this won't meet your performance requirements, then you have to make compromises and accept that there could be some cheating.
I have a general question about programming the client/server communication on a network game.
I use TCP as protocol, and the communication ... works, but I'm not sure, if it is a efficient way.
In general , actions that happen on the client-side will go throught all this steps:
Some action (eg. a Fireball is cast)
[*]For this action i defined a string (eg. #F#270#130#, which means the 'F' says it's a fireball and 270 is (for example) the degree of the angle, 130 - the speed of the fireball that is shoot.)
String goes into outputpuffer of Client & waitingqueue
String is sent
String is received by server
[*] Server needs a lineinterpreter that can detect the meaning of the string (here : what means F? It is a fireball!) & adds a unique identity, based on, from which client the command was received.
[*]The Server needs to calculate logic, based on the action happened (fireball does damage to someone, does it hit someone (immediately) or does it just fly first?)
Server sends an (updated) string of the action(s) that occur to all clients. (eg. maybe the fireball is slowed down in speed for some reason - here will be an updated string (#F#12345#270#90# - 12345 is the unique player identity)
clients receive string
[*] clients resolve string to a command + handle it (fire an animationsequence...)
client that originaly sent the command compares received string with string in waitingqueue - when equal, do nothing (to smoothe out some action, otherwise through connection problems /delay, some action would occur twice or jump from location to location, based on ping
Is it really necessary to go through all these steps? At all steps marked with [*] i need to define new lineinterpreters/action for each command, so i'm coding each action twice, client & server-side.
I read something about sending serializable objects, but in genereal the idea seems to be the same to me, i send an object, that has to be interpreted+handled and i send an object back...
Any hints? To solve the whole communication more elegant, with less coding ? Or a bit more sorted - all these #F# #M# #H# tags for different actions are making it more and more complicated :)
(In fact i actually have the following handlers/actions:
-move
-look/rotate
-hpchange
-firearrow
-spawn/disconnect
...)
Hope you understand what I mean - I know, I could just continue coding like that, and it would work somehow, but it just seems too complicated as it could be.
Thanks!
You could do it in a more OO way if you:
Define an object called Action or something like that, which has all of the above parameters - type of action, direction of action (or
target), damage dealt, etc..
Create those Action objects as your game normally executes
Use ObjectOutputStream chained to your TPC Socket to output the whole Action object to the server/ pass it back to the client.
On the server, interpret what happens by examining the recieved object from ObjectInputStream.
I think this way would be cleaner and more flexible in case you add more logic, than just analyzing strings, but not as fast (since objects going into ObjectOutputStream need to be serialized).
You need to look at several factors before you decide if your game requires any changes.
Firstly, is TCP the best communication channel? Have you compared it to UDP. Would it be better to implement the networking using UDP? Would it matter if a few packets went missing? What happens if the network is slow?
Secondly, look at how often you are polling/pushing to the server. Can this be reduced? Does the game have to be in real-time. Do all parts of a game have to be in realtime. Perhaps certain things can be non-realtime. A fireball will continue in a straight path so you dont have to keep updating the server about its position, you can just tell it about its direction and speed. What other aspects of the game can be non real-time. The only thing that needs sending is, players locations and actions. Most other things like collision detection can be offloaded to the client.
Thirdly, does every keypress need to be sent to the server? If the user is against the wall and wants to move further, the client knows that they cannot and thus will not send those keypresses to the server. If the user has moved to a new valid location, then update the server. Can certain things be buffered and sent to the server in one go, instead of sending several queries to the server. i.e. if I move forward, jump and throw a fireball, thats 3 keypresses on the client side, can they be buffered and sent at the next 500th millisecond?
If you are worried about the networking overhead, you should be working at the bit level. Instead of sending a long string "#F#270#130#" - which is 11 bytes long, would it make sense to send 3 consecutive bytes (24 bits).
7 bits represent the action (127 different actions).
9 bits will represent the angle (1-512), but you only need it up to 0-360 degrees.
8 bits represent the force.
This or any other byte format is shorter and easier to use over the network, and produces tighter code. Also binary comparison is faster, so writing your action parser on the server is now made easier. I.e. instead of a large switch case looking for #F#, you just look at the first 7 bits and compare it to an int.
Can you reduce other networking overheads, instead of force being decided by the client, can the server decide this. i.e. a standard force, or 2 levels of force (much better as this can be represented by 1 bit). Which stops the client and malicious users sending rubbish data across to the server (like force of 999), now the force can either be a 0 or a 1, i.e. speed of 10 or 20, nothing silly.
I'm quite new to Java and have just started Networking so I apologize in advance for any stupid questions. I have a basic game in which a player (or bot) can move around a map until it finds items and exits, but using networking I'd like to be able for the player and the bot to play on the same map simultaneously over a server.
I have 5 classes:
GameRules - Controls the game logic/rules
Map - Contains the map.
Player - Represents a player.
Bot - Plays the game as a bot.
PlayGame - Controls the interaction with the game through CLI.
I'm pretty sure GameRules and Map would be on the server side, and PlayGame would be on the client side, however I'm not sure where Bot and Player class stand? And also, do I merge GameRule and Map into one class, or put a socket in each class?
Thanks a lot.
Most models in a client-server game should reside both on client and server.
The client needs the models to visualize the data they are holding;
The server needs them to modify them according to business logic - the intermediate results are then sent to the clients to have their models updated. The server must do this because that is the reason for its existence: keeping the game's state consistent by being the only node that can alter the game state.
You can always try to keep all models at the clients but imagine what coding horror you'll get yourself into when you want to make a game with N clients. They all have to have a consistent state. It is far more safe to have one node (server) make decisions and then the other nodes must follow instructions.
Please note that in more advanced implementations, like realtime games, the client also implements some prediction behavior to hide the client-server delay, and thus temporarily alters the game state, but the server commands always overrule the client's decisions. You also can code the client in such a way that he is always able to keep playing even when he didn't receive a confirmation yet for the previous "moves" from the server - you have to implement rollback/correction functionality when some moves are denied by the server.
Depending on the complexity of the business logic and synchronization timing needed, it's entirely possible to keep most everything at the client level, and just use the server as a broker for updates. Imagine a 2-player online chess game. The rules are so standard and the timing is simply back-and-forth, so a "server" of this game need only pass each move back and forth from one player to the other. Would be like replacing the mail in your grandfather's chess match with a socket. Each (client) side knows exactly how to process the move and what new moves are valid.
I'm trying to write multiplayer game for Android with java back-end using sockets, but I don't know how to do some things.
For example, I have to players. First player pushed "UP" button and his avatar moving up. How can I tell about it to all other players?
I can send message, that user with some ID changed his coordinates to new X and Y, but I will need to do that for every millisecond while he moving. Is that right?
Or I can send message that user with some ID pushed UP button and after that new message that user released UP button. Using time difference between this two events and movement speed I can calculate new coordinates of user, but in this case will be problems with latency (time difference calculation will be not enough accurate)
How I can do that?
You can do it in lot of ways and all will have drawbacks like you already found. I guess there is no "best" way to do that.
A common way for games is to have a "game server". The server recieves input from all clients and decides about the resulting state.
Clients could for example just transmit the keypresses and the server tells them about their location and location of other clients that need to be drawn. Clients do the same math locally and display this state while waiting for confirmation from the server. But that's just a prediction.
When it lags you can observe yourself jumping between positions in a lot of games because actual server calculated position and your prediction got out of sync.
The other advantage of server-side state decisions is that clients can't cheat that easily. It's no foolproof way to prevent every cheat. Aim-bots for example simply simulate a perfectly aiming user by moving the mouse for them and that's basically not detectable. Map hacks / wall hacks (anything where you can see things that you would not see) on the other hand can be prevented by simply not telling the client about currently invisible things. Only the server needs to know the full state.
The server approach can also be used without a dedicated game server. Instead, one of the clients will have the role of the server and decide about the game state. That responsibility can in some games even switch between clients if the original host drops out. A smooth handover if that happens is rather tricky though.
If there is no server and all clients are equally responsible you will have to think about schema which defines which client is responsible for validating which action. For example in a shooter, A shoots in a certain direction, and thinks B is still there but B already moved a bit further and now A thinks "B was hit" and B thinks "shot missed" -> Either the one shooting or the one being hit should decide what happens.
A schema with multiple decision making parties might not work for every game and it is a very complicated task. Not just for games but distributed computing in general
Java and Sockets are just tools here. The actual problem is one where you should take pen and paper and think about a schema that works for your scenario.
Regarding coordinates every milisecond: you could also send messages like "I will be at point X,Y at time Z" and other clients interpolate the path of that player so you don't have to transmit every position.
As part of a learning experiment, I want to make a network application. I'm still learning about multithreading, and I've made a simple multithreaded "game" that involves drawing sprites on the screen, where the player can move them.
For this new project, I want to make something simple, just for the experience and learning. I want to create a server, where multiple clients can connect to it. The server will contain "game objects", which is just an object containing an x and y position, a string name, an ID to identify it, and velocity (dx and dy).
The "server" application will feature things like a worker thread updating the position of the objects (using their velocity), and it will also send the client the "state" of all game objects, so the clients can draw them for the players to see.
The clients will also send the server data whenever the player presses a button on the keyboard and generates a KeyEvent. The server will read this data and process it by updating the player's game object. For example, if the player presses the left arrow key, the client will send the server data indicating that the left key was pressed, the server will find the game object associated with the client (maybe I will store the objects in a Map like ?)
The problem is how to do this. I've never done any networking of this scale before. The most I've made so far is a buggy 2 player tic tac toe game. Since that is turn based, it is very different the application that I am now trying to make. As research, I read the entire Concurrency lesson on Oracle. I also read this tutorial on NIO. I've never used NIO before but I was recommended by multiple people to use it. I learned a lot about multithreading and concurrency from reading the code and figuring out how it works.
Since the SocketChannels communicate using ByteBuffers, one strategy I thought of is to take a List of GameObjects and serialize it to a byte array. Then create a ByteBuffer with the ByteArray and send it to the client. The client will then get all the GameObjects loaded in the server, and be able to draw all of them based on their type and states. One problem with this is that the byte array could get very large. I tested it with 256 GameObjects, and got a byte array of up to 9KB. If I compress the byte array, the size will be around 96 bytes. Still, I don't know if this is too big to be sent to the client 15 times a second.
Another option that I know of is to send the info byte by byte. For example, the first byte sent could identify what type of game object I am sending (example: cat, car, person), the next two bytes could identify the X position, then the next two the Y position, then the last byte used to identify the state of the object. Using this data, the client can just draw a sprite on the position received.
A big problem with all that I've said is that the client won't be able to interact with any of the objects. The client will just be able to send simple commands to the server, and "view" the game objects' sprites at its position. If the server wanted to tell the a game object to do a specific action, it would be hard to draw it since I will just be drawing static sprites to a screen, instead of interacting with the sprites.
I also am not sure whether or not NIO is the best idea. Most people I've talked to recommend it, but I don't quite understand the practical difference between implementing a non blocking NIO server and a multithreaded regular java.net.* server. My guess is that the non blocking server has better performance than a multithreaded one, and I would run into much less problems with just 1 thread rather than multiple threads per connection.
And finally, I've gotten mixed advice whether or not to use TCP or UDP. I've never used UDP before either. Some strongly suggest TCP, while others strongly suggest UDP.
As you can see, I am pretty unorganized and not sure on what to do. I feel like I have read a lot about networking and concurrency, and I already know enough about Swing to make graphical games. I just don't know how to put it all together.
Perhaps consider using Netty. I have found it extremely useful for rapid application development and fast enough for most server and client applications. You can get faster with a raw implementation of the reactor design pattern with Java NIO, but it will take a lot more work and code that is hard to debug.