I´m planning to create a WebGL-based, realtime strategy game, where players are able to play together. I´ll use Node.js to create the game server, and websockets for realtime connections.
I´ve broken my mind about what would be the best concept to synchronize the clients.
One possibility would be to send only the orders of the users (moving units, building buildings etc.) to the server, which sends them to all other clients. But here, I have the problem of the delay. I think that the games would get async this way.
Another possibility would be to calulate the game on the server. The clients still send the instructions to the server, but the server sends now all changed states of all units&buildings to the clients in a high interval. The problem is here the high amount of data and how fast this can be...
Do you have some other ideas or improvement proposals?
Thanks!
Basically you have to decide between speed vs security.
Letting the client do the job and the calculations is faster but the data is at risk because the client can manipulate the data.
On the other side, having the server do all the job is slower but the data is more secure.
You could opt for a dual approach, decide to let the client calculate only some data, synchronize and then check for its validity, and let the rest being executed on the server.
It also depends on how fast the game runs, the amount of data to calculate, the speed of the server and band/connections, etc...
You should prototype both methods and try some tests to emulate the client and servers load.
If the game is small I would opt for a more server-side work. On the other hand, for a much complex game probably sharing more work to the client is best. Anyway I think a tradeoff is always needed.
Here are a few links you may find useful
Multiplayer Game Programming Introduction
Real time strategy networking
Multiplayer Programming thread (old but still with many useful links)
Lag Compensation
Prevent Multiplayer Cheating
The first link has helped me a lot back in the days and imho is still one of the best resources avaiable on the subject.
Books
Multiplayer Game Programming
I would suggest to watch these resources regarding browser based game development concepts:
Multiplayer Gaming with HTML5: Are We Ready?
Realtime HTML5 Multiplayer Games with Node.js
HTML5 Games 0.3: Seeing the Future
Unfortunately I have no experiences in WebGL based online games, but usually it is a good approach to let the game logic be executed on the client side, and synchronize the results.
In this approach it is important to keep track of what game object is "owned" by what client. Clients only send updates (creation, update, deleteion) from their own objects and receive the updates of the other game objects from the other clients.
Additionally you can set up a messaging framework to deliver additional messages like "Player has entered/left" or something like that.
This concept has proven useful for a game I created, and I hope it is as useful to you.
You should have the game state and logic on the server, otherwise your game is wide open to cheating. The server is the ultimate authority the game state.
Not sure about WebGL, but to my understanding following approach will be good.
Initialize all objects (which are common across players) on server and run them
On client start, it will request all renderer (related to specific client) for the objects running on server.
client will render the objects on UI for all recieved renderer.
When client make any update on UI, changes will be notified to server, and server will update the object accordingly
When objects common between players are modified by one player, each player (client) will be notified to make UI changes.
This approach will be specific to common objects not UI / client specific objects.
For security reasons, all the logic should be on servers side, and all the data update is on server.
But the client is able to predict some logic and play animation first, which is called client prediction.
The server side is in charge of verify the client logic, if there is no cheating, all done.
If there is someone cheating, the server can tell the client to go back to right state.
If you are using node.js for server, there is an open source framework , pomelo .
And there is also a full source code demo and online demo for it: lordofpomelo
Related
Being relatively new to the web world, I encountered a (pretty common?) problem.
Developping a multiplayer game, I'm having trouble handling disconnections. Server and clients communicate through websockets, so whenever a client is disconnected, he misses on the notifications sent by the other clients (routed by the server). Which means that :
whenever a client is disconnected, I need to record all changes happening afterwards.
when he connects back, I need to send him all this info
the client then needs to be able to replay these records to sync with the server state.
I was wondering if there was some kind of design pattern to handle this problem (rather than an implementation specific solution). I believe it's kind of what React, Vue etc... are meant for (?), but I'd rather avoid using any heavy framework.
Any ressource/doc would also be appreciated ;)
Transaction in Distributed Systems is a related technique (but it is not categorized as a design pattern.)
Memento pattern provides the ability to restore an object to its previous state, so it's also somehow related.
The approach you described in the question seems to be good. Maybe you don't need a pattern to fit in.
I've been pecking away creating a multiplayer game where I used python for the server (with Twisted Framework) and javascript for the frontend (web game).
I'm a bit stumped at how I can start players in tine with others. For example, the server sends the players a new map, which starts a countdown from 3, then they can race to the finish.
The issue is if someone has poor latency and another doesn't, the better connection would give them a head start, which is unfair.
I'm stumped as to how to at the very least limit this. What measures can I take or look into? I don't believe I can rely on ping time as that will fluctuate quite often.
Usually, when developing multiplayer features, the engine that run the game run both on clients and server.
When the server receive client data (along with their game clock) the state of the clients game prediction is reconciled with the server's one (the only source of truth).
You can find a very interesting introduction article about the topic here.
Notice also that some protocols, like UDP, are by far more suitable than other for multiplayer realtime data exchange.
The basics
Right now a few of my friends and I are trying to develope a browser game made in nodejs. It's a multiplayer top-down shooter, and most of both the client-side and server-side code is in javascript. We have a good general direction that we'd like to go in, and we're having a lot of fun developing the game. One of our goals when making this game was to make it as hard as possible to cheat. Do do that, we have all of the game logic handled server-side. The client only sends their input the the server via web socket, and the server updates the client (also web socket) with what is happening in the game. Here's the start of our problem.
All of the server side math is getting pretty hefty, and we're finding that we need to scale in some way to handle anything more than 10 players (we want to be able to host many more). At first we had figured that we could just scale vertically as we needed to, but since nodejs is single threaded, is can only take advantage of one core. This means that getting a beefier server won't help that problem. Our only solution is to scale horizontally.
Why we're asking here
We haven't been able to find any good examples of how to scale out a nodejs game. Our use case is pretty particular, and while we've done our best to do this by ourselves, we could really benefit from outside opinions and advice
Details
We've already put a LOT of thought into how to solve this problem. We've been working on it for over a week. Here's what we have put together so far:
Four types of servers
We're splitting tasks into 4 different 'types' of servers. Each one will have a specific task it completes.
The proxy server
The proxy server would sit at the front of the entire stack, and be the only server directly accessible from the internet (there could potentially be more of these). It would have haproxy on it, and it would route all connections to the web servers. We chose haproxy because of its rich feature set, reliability, and nearly unbeatable speed.
The web server
The web server would receive the web-requests, and serve all web-pages. They would also handle lobby creation/management and game creation/management. To do this, they would tell the game servers what lobbies it has, what users are in that lobby, and info about the game they're going to play. The web servers would then update the game servers about user input, and the game server would update the web servers (who would then update the clients) of what's happening in the game. The web servers would use TCP sockets to communicate with the game servers about any type of management, and they would use UDP sockets when communicating about game updates. This would all be done with nodejs.
The game server
The game server would handle all the game math and variable updates about the game. The game servers also communicate with the db servers to record cool stats about players in game. This would be done with nodejs.
The db server
The db server would host the database. This part actually turned out to be the easiest since we found rethinkdb, the coolest db ever. This scales easily, and oddly enough, turned out to be the easiest part of scaling our application.
Some other details
If you're having trouble getting your head around our whole getup, look at this, it's a semi-accurate chart of how we think we'll scale.
If you're just curious, or think it might be helpful to look at our game, it's currently hosted in it's un-scaled state here.
Some things we don't want
We don't want to use the cluster module of nodejs. It isn't stable (said here), and it doesn't scale to other servers, only other processors. We'd like to just take the leap to horizontal scaling.
Our question, summed up
We hope we're going in the right direction, and we've done our homework, but we're not certain. We could certainly take a few tips on how to do this the right way.
Thanks
I realize that this is a pretty long question, and making a well thought out answer will not be easy, but I would really appreciate it.
Thanks!!
Following my spontaneous thoughts on your case:
Multicore usage
node.js can scale with multiple cores as well. How, you can read for example here (or just think about it: You have one thread/process running on one core, what do you need to use multiple cores? Multiple threads or multiple processes. Push work from main thread to other threads or processes and you are done).
I personally would say it is childish to develop an application, which does not make use of multiple cores. If you make use of some background processes, ok, but if you until now only do work in the node.js main event loop, you should definitely invest some time to make the app scalable over cores.
Implementing something like IPC is not that easy by the way. You can do, but if your case is complicated maybe you are good to go with the cluster module. This is obviously not your favorite, but just because something is called "experimental" it does not mean it's trashy. Just give it a try, maybe you can even fix some bugs of the module on the way. It's most likely better to use some broadly used software for complex problems, than invent a new wheel.
You should also (if you do not already) think about (wise) usage of nextTick functionality. This allows the main event loop to pause some cpu intensive task and perform other work in the meanwhile. You can read about it for example here.
General thoughts on computations
You should definitely take a very close look at your algorithms of the game engine. You already noticed that this is your bottleneck right now and actually computations are the most critical part of mostly every game. Scaling does solve this problem in one way, but scaling introduces other problems. Also you cannot throw "scaling" as problem solver on everything and expect every problem to disappear.
Your best bet is to make your game code elegant and fast. Think about how to solve problems efficiently. If you cannot solve something in Javascript efficiently, but the problem can easily be extracted, why not write a little C component instead? This counts as a separate process as well, which reduces load on your main node.js event loop.
Proxy?
Personally I do not see the advantage of the proxy level right now. You do not seem to expect large amount of users, you therefore won't need to solve problems like CDN solves or whatever... it's okay to think about it, but I would not invest much time there right now.
Technically there is a high chance your webserver software provides proxy functionality anyway. So it is ok to have it on the paper, but I would not plan with dedicated hardware right now.
Epilogue
The rest seems more or less fine to me.
Little late to the game, but take a look here: http://goldfirestudios.com/blog/136/Horizontally-Scaling-Node.js-and-WebSockets-with-Redis
You did not mention anything to do with memory management. As you know, nodejs doesn't share its memory with other processes, so an in-memory database is a must if you want to scale. (Redis, Memcache, etc). You need to setup a publisher & subscriber event on each node to accept incoming requests from redis. This way, you can scale up x nilo amount of servers (infront of your HAProxy) and utilize the data piped from redis.
There is also this node addon: http://blog.varunajayasiri.com/shared-memory-with-nodejs That lets you share memory between processes, but only works under Linux. This will help if you don't want to send data across local processes all the time or have to deal with nodes ipc api.
You can also fork child processes within node for a new v8 isolate to help with expensive cpu bound tasks. For example, players can kill monsters and obtain quite a bit of loot within my action rpg game. I have a child process called LootGenerater, and basically whenever a player kills a monster it sends the game id, mob_id, and user_id to the process via the default IPC api .send. Once the child process receives it, it iterates over the large loot table and manages the items (stores to redis, or whatever) and pipes it back.
This helps free up the event loop greatly, and just one idea I can think of to help you scale. But most importantly you will want to use an in-memory database system and make sure your game code architecture is designed around whatever database system you use. Don't make the mistake I did by now having to re-write everything :)
Hope this helps!
Note: If you do decide to go with Memcache, you will need to utilize another pub/sub system.
I am using Flask and I want to show the user how many visits that he has on his website in realtime.
Currently, I think a way is to, create an infinite loop which has some delay after every iteration and which makes an ajax request getting the current number of visits.
I have also heard about node.js however I think that running another process might make the computer that its running on slower (i'm assuming) ?
How can I achieve the realtime updates on my site? Is there a way to do this with Flask?
Thank you in advance!
Well, there are many possibilites:
1) Polling - this is exactly what you've described. Infinite loop which makes an AJAX request every now and then. Easy to implement, can be easily done with Flask however quite inefficient - eats lots of resources and scales horribly - making it a really bad choice (avoid it at all costs). You will either kill your machine with it or the notification period (polling interval) will have to be so big that it will be a horrible user experience.
2) Long polling - a technique where a client makes an AJAX request but the server responds to that request only when a notification is available. After receiving the notification the client immediately makes a new request. You will require a custom web server for this - I doubt it can be done with Flask. A lot better then polling (many real websites use it) but could've been more efficient. That's why we have now:
3) WebSockets - truely bidirectional communication. Each client maintains an open TCP connection with the server and can react to incoming data. But again: requires a custom server plus only the most modern browsers support it.
4) Other stuff like Flash or Silverlight or other HTTP tricks (chunked encoding): pretty much the same as no 3). Though more difficult to maintain.
So as you can see if you want something more elegant (and efficient) than polling it requires some serious preparation.
As for processes: you should not worry about that. It's not about how many processes you use but how heavy they are. 1 badly written process can easily kill your machine while 100 well written will work smoothly. So make sure it is written in such a way that it won't freeze your machine (and I assure you that it can be done up to some point defined by number of simultaneous users).
As for language: it doesn't matter whether this is Node.js or any other language (like Python). Pick the one you are feeling better with. However I am aware that there's a strong tendency to use Node.js for such projects and thus there might be more proper libraries out there in the internets. Or maybe not. Python has for example Twisted and/or Tornado specially for that (and probably much much more).
Websocket is an event-driven protocol, which means you can actually use it for truly real-time communication.
Kenneth Reitz wrote an extension named Flask-Sockets that is excellent for websockets:
Article: introducing-flask-sockets
Github: flask-sockets
In my opinion, the best option for achieving real time data streaming to a frontend UI is to use a messaging service like pubnub. They have libraries for any language you are going to want to be using. Basically, your user interfaces subscribe to a data channel. Things which create data then publish to that channel, and all subscribers receive the publish very quickly. It is also extremely simple to implement.
You can use PubNub and specifically PubNub presence meant especially for online presence detection. It provides key features like
Track online and offline status of users and devices in realtime
Occupancy to monitor user and machine presence in realtime
Join/Leave Notification for immediate updates of all client connections
Global Scale with synchronized servers across the PubNub Data Stream Network
PubNub Presence Tutorial provides code that can be downloaded to get presence up and running in a few minutes. Five Ways You Can Use PubNub Presence shows you the different ways you can use PubNub presence.
You can get started by signing up for PubNub and getting your API keys.
I was thinking a little whiteboard web app would be a nice way to improve my node.js and JavaScript skills. I've seen a few on the web, which makes sense as it seems ideal for this kind of stack.
Just taking a moment to think, however, I was wondering about the roles of both client and server in this kind of web application. Stumbling upon node-canvas, I became even more confused. What, specifically, should the client and server be responsible for?
If the server is capable of rendering to a canvas, should it accept and validate input from the clients and then broadcast it to all other connected users via socket.io? This way, the server keeps a master-canvas element of sorts. Once a new user connects, the server just has to push out its canvas that client - bringing it up to pace with whatever has been drawn.
Any guidance on implementation - specific or philosophical - is appreciated.
Thanks!
I wrote http://draw.2x.io, which uses node-canvas (previously node-cairo, which I wrote myself) along with socket.io.
The way I've designed my application, the client essentially does all the stroke generation from user input. These are in turn processed by a canvas abstraction, which supports a subset of operations and parameters which I've defined myself. If this layer accepts whatever input the painting modules produce, they are also shipped, via socket.io, to the server.
On the server I've got the same kind of canvas layer wrapping node-canvas. This will thus replicate the input from the user in memory there, eventually making it possible to send a state image to new clients. Following this, the strokes will -- pending parameter / context validation by the server application -- be published to other connected clients, which will repeat the same procedure as above.
A company I work for implemented a whiteboard app with node.js (but did not use node-canvas) and socket.io. Unfortunately, I cannot give you code or even a website since it has not been released.
Your implementation seems very similar. Clients connect to our server and update the server whenever the whiteboard is drawn to (JSON data w/(x,y) coordinates) through socket.io. The server then updates the rest of the clients and keeps a copy of all the (x,y) coordinates so that new clients who join can see what has already been drawn.
Good luck with your app. I've been programming with node.js a lot lately and boy do I love it.
here's a multiuser whiteboard tutorial written in javascript/html5, all source available:
http://www.unionplatform.com/?page_id=2762
it's not node on the server-side, but the client-side code should still be useful if you want to adapt it to a node backend.