Smartfox card game timer logic
Smartfox card game timer logic
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?
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.
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.
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))
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))
Ok, I misunderstood youarun8483 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?
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: 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 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 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))
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);
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);
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?
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?
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.
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,
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:
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) {
}
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:
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) {
}
That is ok. You should send your join room and create room requests to zone extension.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?
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?
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?
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,......)?
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?