Use only with websockets / TCP sockets

202 views
Skip to first unread message

normanp...@gmail.com

unread,
Aug 19, 2013, 9:42:03 AM8/19/13
to action...@googlegroups.com
Hi, I just saw the framework an seems pretty solid and well structured, but my doubts are how can use this framework to develop a realtime multiplayer game, just need to use sockets and identify users by they socket Id, after they connect to the server.

There is a way to only allow the server run on websockets / TCP sockets and idenfity the user by their connection id (provided by socket server) ?

Regards

PD: I'm still reading the documentation to see if there is any example or explanation.

Evan Tahler

unread,
Aug 19, 2013, 5:18:37 PM8/19/13
to action...@googlegroups.com, normanp...@gmail.com
If I understand correctly, actionHero should be able to help you out.  All connections a specific actionHero node/instance has are kept in api.connections.connections. It's a hash with the connection IDs as the keys.  For example, you can create a task to send a message to all connected clients every second like this:

exports.task = {
  name: "chatty",
  description: "chatty",
  scope: "any",
  frequency: 1000 * 1,
  toAnnounce: true,
  run: function(api, params, next){
    if(params == null){ prams = {}; }
    var error = null;
  
    for(var id in api.connections.connections){
      var connection = api.connections.connections[id];
      var message = {
        yourId: id,
        time: new Date().getTime(),
        message: "hi",
      };
      connection.sendMessage(JSON.stringify(message));
    }

    next(error, true);
  }
};

However, as you might have more than one node/server running, it's usually best to have a "chat room" for each client, so you can address them no matter what server they reside on.  This is how actionHero's web socket implementation works.   Clients can be subscribed to more than one chatroom, so I usually have a "realm" room the user is in, and a subscription to a "user" room as well.  You can send messages to specific chat rooms like so:

api.chatRoom.socketRoomBroadcast({room: "user123891231"},"Hello user");

normanp...@gmail.com

unread,
Aug 26, 2013, 3:44:14 PM8/26/13
to action...@googlegroups.com, normanp...@gmail.com
The chat part isn't an issue yet, but thanks for the advice about creating a room for every player, I've got a question, how can I manage/query data from redis (map related, objects, npcs, enemies, etc). I was thinking about creating zones and save the zones in redis, like

Supposing the zone its something like:

var zone = {
.....
updatedAt: date...
}

I call it with (x-width-y-height)

api.cache.save('__zones-xwyh', { ... });

And in the action sent from the client the last updated time from the zone so I just compare if there is a new version and sent it, but this must be overwhelming the server with request (30 per second, per client). Dunno if this is the only way or using some emit/on methods to send/listen events.

Is there is a book / tutorial that you recommend me to read? (If you know some).

Regards

Evan Tahler

unread,
Aug 27, 2013, 12:25:57 AM8/27/13
to action...@googlegroups.com, normanp...@gmail.com

While not really about actionHero, I think your question is about game servers in general:


Folks looking to design a game server coming with experience creating webistes or other REST APIs often make the mistake of thinking they can operate their game servers statelessly as well.  I've made this mistake a number of times :D  A good rule of thumb is "if your game requires "real time" communication, you probably can't afford to hit a DB on each request".  It is vey appealing to try to make your game entirely database-driven (great recovery, no locking problems, etc), but in reality it is often too slow.


The reason I brought up "chat" is that the major pattern most MMOs, shooters, and other "fast" online games use is what I call the "keyframe and diff" method of synchronization.  I don't mean "chat" as in two people talking to each other (although it can be used for that), but rather the sever chatting with the client.  


Keyframes are large blocks of data that represent the state of the game world at a moment in time.  This is, I think, what you have in mind with your `var zone = {}`.  This data is large and is usually out of date by the time it reaches the client.  Diffs are changes between the state the user got before and now.  Diffs are "player #3's health is now 99 or npc #42 is at position [x,y]"  These diffs are the type if information you should be sending to your clients as soon as they happen (to help prevent collisions where 2 players conflict, like ending up in the same place).  


In actionHero, you can have the "playerUpdatePosition" action re-broadcast any information it receives into a chat room for that realm.  This information can then be sent down to the clients, and now no one needs to poll for updates at all.  You can create initializers (server-side code that also listens to evens on channels, and you can use them to process NPC movement and other things like player v player activity).  You can also create tasks that do some action on the game state every-so-often by once again, broadcasting on these "chat rooms".


While actionHero strives to allow any client to connect to any server and join the relevant chat rooms (thanks Faye!), you will probably end up having only one actionHero node/server processing a realm at a time.  You will need to figure out a way to coordinate this between all your nodes, but acitonHero will help you to ensure that getting and sending data will always work for all your clients.  


Getting back to databases, you should always back up your games' state (in a non-blocking way) to redis or some other DB, but I would suggest that you don't use it for every client's request. 

Reply all
Reply to author
Forward
0 new messages