Smartfox card game timer logic

Need help with SmartFoxServer? You didn't find an answer in our documentation? Please, post your questions here!

Moderators: Lapo, Bax

Malini
Posts: 4
Joined: 15 Oct 2011, 03:53

Smartfox card game timer logic

Post by Malini »

I am working on a card turn based game and there is a timer running for each player when they get their turn.... Currently I am implementing the timer in the client side ...just want to make sure that this process is right or wrong... Should we implement the timer in client or server side?
Sarevok
Posts: 75
Joined: 12 Apr 2011, 22:12

Post by Sarevok »

Server side of course. Client should be a very dumb application. You usually want client to be responsible only for user input (that is sending requests to server) and for displaying information it gets from server.

So, basically you send a request to server to make a move (making a bet in poker for example). When server gets request it will process it, notify all players about the move, and notify them who is next on move. At the same time server will schedule a time triggered task to be executed for some predefined time (lets say 20 second). And after that we have two scenarios:

a) If next player makes a move within that period server will cancel that task, process the move just like it did before, notify all players about move, tell them who is next, and schedule a new time triggered task associated with next player.

b) If next player didn't make move within that period, scheduled task will be executed, and what it will do depends of the game. If it is poker, server will count it as player folded, so server will notify other players about folding, and tell them who is next. He will also schedule new time triggered task associated with next player.
arun8483
Posts: 33
Joined: 15 Dec 2010, 02:35
Contact:

Post by arun8483 »

Hi Sarevok,
I have 3 questions regarding this...

1) So, When timer runs in the server side say for 10 sec, each sec should we send response to the client side to display the timer running?

2) Like poker,,,each room will be having its own game running...so to do this whether I should create a single zone level extension or room level extension to handle room level card decks and other room level game logic?

3) In smartfox how do we create room level java extension? I h've tried this logic
Game game = new Game(); //room level extension
newRoom.getExtManager().add("game", game); // adding to room level extension manager
Is this logic correct?
If its correct, how do we start this room level extension? How do we make this room level extension listen from the client side? Should we have to call game.init() manually or is there any method in Zone/Helper classes to automatically initialize by the server itself. Because after calling game.init() handleInternalEvent for room level is not getting called at all. But when I call extensionManager.reloadExtension("game") handleInternalEvent method is getting called. But I dont this is the right way to do it, Because I am creating 10 rooms in the begining and at the same time I am allocating room level extensions as I shown above, now When I try to login/userjoin from client side to the main Zone level extension I am getting serverside userjoin/loginrequest calls for the room level extensions 10 times. This is my client side userjoin call (smartfox.sendXtMessage("rummy", "joinRoom", [roomName], "str", smartfox.activeRoomId))
Sarevok
Posts: 75
Joined: 12 Apr 2011, 22:12

Post by Sarevok »

arun8483 wrote: 1) So, When timer runs in the server side say for 10 sec, each sec should we send response to the client side to display the timer running?
Ok, I misunderstood you :) I thought that by timer you mean timed events, and not a literal timer :) The timer you are talking about will be on client side of course. It is part of the displaying process. So, when server notify clients who is next on the move, in the data it sends there is a value that tells how many seconds player have to play a move. On the client side you start the countdown timer using that value (There is no need for server to make this countdown since it would generate too many data traffic with no real reason). Since there is always a bit of lag between client and server, there is many ways to compensate for that lag in order for timing to be very precise. The easiest way is to just ignore the lag, it will be a bit imprecise, but it usually is not that important since we are talking about tenths of milliseconds imprecision. If you really want to be precise, server can send additional value (together with number of seconds player have to make a move) telling you exact time when task was scheduled. If client time is synchronized with the server you will have exact move ending time. But you have to take into account that there is lag in other direction too, so if client makes his move in last moment, it may happen that his request will come to server a bit too late, since task will already be fired. Anyway, as I already said, it is not very important for card based game, since milliseconds are hardly observable by the human, so you can go for easiest implementation ignoring the both direction of lag completely, or allowing a client a little less time for move than it really have to compensate for this lag.
arun8483 wrote: 2) Like poker,,,each room will be having its own game running...so to do this whether I should create a single zone level extension or room level extension to handle room level card decks and other room level game logic?
You can do it both ways, and both ways have its own pros and cons regarding performance, memory usage, ease of organization/implementation/maintenance. In this case I would go for room level extensions. (each game room running its own instance of extension).

arun8483 wrote: 3) In smartfox how do we create room level java extension? I h've tried this logic
Game game = new Game(); //room level extension
newRoom.getExtManager().add("game", game); // adding to room level extension manager
Is this logic correct?
If its correct, how do we start this room level extension? How do we make this room level extension listen from the client side? Should we have to call game.init() manually or is there any method in Zone/Helper classes to automatically initialize by the server itself. Because after calling game.init() handleInternalEvent for room level is not getting called at all. But when I call extensionManager.reloadExtension("game") handleInternalEvent method is getting called. But I dont this is the right way to do it, Because I am creating 10 rooms in the begining and at the same time I am allocating room level extensions as I shown above, now When I try to login/userjoin from client side to the main Zone level extension I am getting serverside userjoin/loginrequest calls for the room level extensions 10 times. This is my client side userjoin call (smartfox.sendXtMessage("rummy", "joinRoom", [roomName], "str", smartfox.activeRoomId))
You don't create them manually. You must call server API to do that for you. Check the javadoc for ExtensionHelper class. It has createRoom() methods, and one of parameters for that method is your extension class. After calling this method server will bind instance of that extension for that particular room.
arun8483
Posts: 33
Joined: 15 Dec 2010, 02:35
Contact:

Post by arun8483 »

thanks a lot Sarevok....I will do that...
arun8483
Posts: 33
Joined: 15 Dec 2010, 02:35
Contact:

Post by arun8483 »

Hi Sarevok,
I have implemented that..and everything is working fine. But I have one more issue
userJoin and userLost server internal events are getting called for both zone level extension and room level extension for the below call

smartfox.joinRoom(roomId, "", false, false, smartfox.activeRoomId);
arun8483
Posts: 33
Joined: 15 Dec 2010, 02:35
Contact:

Post by arun8483 »

Hi Sarevok,
One more doubt regarding room/zone level variable synchronization

1) Lets assume this scenario... 1000 people trying to join the same room at the same point of time ( this room has an extension associated with it )
In userJoin event I am trying to start the card game when there are more than 1 user joined.
if( room.getAllPlayers().length > 1) {
if( !gameRunning ) {
gameRunning = true;
createTask();
}
}

In this scenario, since there are lots of users trying to join at the same point of time and since its multithreaded its possible that these lines of code execute in parallel, So its possible that createTask() method might be called more than once. Eventhough I am checking for gameRunning boolean value, when things starts to run in parallel, first two line of code may execute multiple times before executing the third line, If it happens then it will be a worse scenario. So Do I have to use synchronization block in this place?
Sarevok
Posts: 75
Joined: 12 Apr 2011, 22:12

Post by Sarevok »

I don't recognize the signature of that join room method. Are you calling it from the server or client side? I guess it must be client side, since I never saw that signature :)

What is your room layout in config file? What do you do in the zone extension? Is zone extension attached to some rooms in config file?

Try send request to join room through extension. In your zone level extension for example you could handle request from users to join particular room. Client will send request to extension, and extension will be responsible for joining user to room. That way you get fine control over who is allowed to join certain rooms. When you let clients to join rooms through client API you have no control over that process, and clients are easily hacked. When I make my own application I disable all client API comands, and force them to make all request through my extensions.
Sarevok
Posts: 75
Joined: 12 Apr 2011, 22:12

Post by Sarevok »

I just saw your second question. Yes, you have to use synchronization block.
arun8483
Posts: 33
Joined: 15 Dec 2010, 02:35
Contact:

Post by arun8483 »

Hi Sarevok,
All my rooms are dynamic. I have configured only one room in config.xml and that is for lobby. This is the place where all users who logs in joins in the first place by default and they can see all game rooms in a grid, from there they can select and join any game room. Is this process correct?

The below code is for creating rooms in the zone extension. My Zone extension name is "main", So should I send the joinRequest to zone extension or to room extension to join in a particular room? When I pass room extension name("game") in the below client side call I am getting exception in the server side ( jvm 1 | 04:59:04.395 - [ WARNING ] > it.gotoandplay.smartfoxserver.exceptions
.MissingExtensionException: Unrecognized extension name: [ game ]! Zone: main,
Room: 8)


Client Side:
smartfox.sendXtMessage("main", "joinRoom", [roomName], "str", smartfox.activeRoomId);

Server Side Room Creation:
HashMap map = new HashMap();
map.put("name", String.valueOf("Room" + lobby.getId()));
map.put("pwd", "");
map.put("maxU", String.valueOf(lobby.getMaxPlayers()));
map.put("maxS", "10");
map.put("isGame", "true");
map.put("uCountUpdate", "true");
map.put("xtName", "game");
map.put("xtClass", "com.lhd.rummyserver.roomextension.Game");
try {
Chips chips = lobby.getChips();
newRoom = helper.createRoom(currZone, map, null, true, true);
newRoom.setVariable("amount", RoomVariable.TYPE_STRING, String.valueOf(chips.getValue()), true, true, null, true);
trace("newRoom creation checking=" + newRoom);
newRoom.setVariable("gameStatus", RoomVariable.TYPE_STRING, GAME_STATUS_OPEN, true, true, null, true);
} catch (ExtensionHelperException ehe) {
}
Sarevok
Posts: 75
Joined: 12 Apr 2011, 22:12

Post by Sarevok »

arun8483 wrote:Hi Sarevok,
All my rooms are dynamic. I have configured only one room in config.xml and that is for lobby. This is the place where all users who logs in joins in the first place by default and they can see all game rooms in a grid, from there they can select and join any game room. Is this process correct?
That is ok. You should send your join room and create room requests to zone extension.
arun8483
Posts: 33
Joined: 15 Dec 2010, 02:35
Contact:

Post by arun8483 »

I have one more question regarding synchronization scenario I mentioned above. If we use the below code, Do we really require sync there?

if (room != null) {
if (room.getAllPlayers().length == MIN_PAYERS_REQUIRED) {
synchronized (this) { // Is this sync block really required here?
if (!gameRunning) {
gameRunning = true;
startGame();
}
}
}
}
In this block, regardless of parallel access, that if condition will be satisfied only for 2 players so the entire if cond block will be executed only for 2 players, so sync block is not required here right?
arun8483
Posts: 33
Joined: 15 Dec 2010, 02:35
Contact:

Post by arun8483 »

Sarevok wrote:I don't recognize the signature of that join room method. Are you calling it from the server or client side? I guess it must be client side, since I never saw that signature :)

What is your room layout in config file? What do you do in the zone extension? Is zone extension attached to some rooms in config file?

Try send request to join room through extension. In your zone level extension for example you could handle request from users to join particular room. Client will send request to extension, and extension will be responsible for joining user to room. That way you get fine control over who is allowed to join certain rooms. When you let clients to join rooms through client API you have no control over that process, and clients are easily hacked. When I make my own application I disable all client API comands, and force them to make all request through my extensions.

Hi, Sarevok
Even after sending the joinRequest to zone extension.... handleInternalEvent method is called in both zone aswell as in the room extension... can you check my room creation logic I posted there... is it because of the main zone I am passing as the argument in createRoom(main zone,......)?
Sarevok
Posts: 75
Joined: 12 Apr 2011, 22:12

Post by Sarevok »

No, you must pass that argument, so it is ok. I am not sure why is that a problem? Can't you just ignore that event? I am not sure if it is default server behavior to send that event to zone extension, but even if it does you can just ignore it. Can you explain why is firing of that event in zone extension a problem to you?
arun8483
Posts: 33
Joined: 15 Dec 2010, 02:35
Contact:

Post by arun8483 »

aahh if its default server behaviour then ok... Yes I am actually ignoring that event now...just curious to know whether any problem with my config logic or something else... :).... and regarding that previous sync post?
Post Reply