Page 1 of 1
createGame() problems
Posted: 14 Nov 2010, 01:24
by ericheimburg
Hi, I'm trying to use the Game API's createGame() on the server to create a new game. However, calling createGame() crashes with a Null Pointer Exception:
Code: Select all
Exception: java.lang.NullPointerException
Message: *** Null ***
Description: Error while handling client request in extension: { Ext: WteSfsPlugin, Type: JAVA, Lev: ZONE, { Zone: WteLo
bby }, {} }
Extension Cmd: arena.practice
+--- --- ---+
Stack Trace:
+--- --- ---+
java.util.concurrent.ConcurrentHashMap.containsKey(Unknown Source)
com.smartfoxserver.v2.entities.managers.SFSRoomManager.containsRoom(SFSRoomManager.java:407)
com.smartfoxserver.v2.entities.managers.SFSRoomManager.validateRoomName(SFSRoomManager.java:632)
com.smartfoxserver.v2.entities.managers.SFSRoomManager.createRoom(SFSRoomManager.java:88)
com.smartfoxserver.v2.entities.SFSZone.createRoom(SFSZone.java:230)
com.smartfoxserver.v2.api.SFSApi.createRoom(SFSApi.java:607)
com.smartfoxserver.v2.api.SFSGameApi.createGame(SFSGameApi.java:122)
com.smartfoxserver.v2.api.SFSGameApi.createGame(SFSGameApi.java:76)
wte.plugins.ArenaCmdHandler.handleClientRequest(ArenaCmdHandler.java:57)
com.smartfoxserver.v2.extensions.SFSExtension.handleClientRequest(SFSExtension.java:187)
com.smartfoxserver.v2.controllers.ExtensionController.processRequest(ExtensionController.java:137)
com.smartfoxserver.bitswarm.controllers.AbstractController.run(AbstractController.java:96)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I assume I'm not providing a value it needs, but none of the parameters I pass it are null, and I filled in all the documented members of the CreateSFSGameSettings() object, so I don't know what it's missing.
Posted: 14 Nov 2010, 02:33
by ericheimburg
Ah, I found it. The documentation is not very complete here so in case others are trying to get this function to work, here's how I got it to work. In this case, it's a command handler that responds to the command "arena.practice". It creates a "practice" game where the user plays alone against the AI, but you can easily change the parameters to require/invite more people.
Code: Select all
package wte.plugins;
import com.smartfoxserver.v2.SmartFoxServer;
import com.smartfoxserver.v2.annotations.MultiHandler;
import com.smartfoxserver.v2.api.CreateRoomSettings.RoomExtensionSettings;
import com.smartfoxserver.v2.api.ISFSGameApi;
import com.smartfoxserver.v2.entities.SFSRoomRemoveMode;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.exceptions.SFSCreateRoomException;
import com.smartfoxserver.v2.extensions.BaseClientRequestHandler;
import com.smartfoxserver.v2.extensions.SFSExtension;
import com.smartfoxserver.v2.game.CreateSFSGameSettings;
import java.util.ArrayList;
@MultiHandler
public class ArenaCmdHandler extends BaseClientRequestHandler
{
static volatile int nextGameID = 1;
@Override
public void handleClientRequest(User user, ISFSObject params)
{
//WteSfsPlugin plugin = (WteSfsPlugin)getParentExtension();
SFSExtension plugin = getParentExtension();
ISFSGameApi gameApi = SmartFoxServer.getInstance().getAPIManager().getGameApi();
String requestId = params.getUtfString(SFSExtension.MULTIHANDLER_REQUEST_ID);
plugin.trace("ArenaCmdHandler called! Command is " + requestId);
if (requestId.equals("practice"))
{
ISFSObject inviteParams = new SFSObject();
inviteParams.putUtfString("Type", "practice");
ArrayList<User> invitees = new ArrayList<User>();
invitees.add(user);
// invite other people who should be in game here
CreateSFSGameSettings settings = new CreateSFSGameSettings();
settings.setInvitationExpiryTime(30);
settings.setInvitationParams(params);
settings.setInvitedPlayers(invitees);
settings.setMinPlayersToStartGame(1);
settings.setGamePublic(false);
settings.setExtension(new RoomExtensionSettings("WteSfsPlugin", "wte.plugins.GameManagerPlugin"));
settings.setName(user.getName()+"'s practice #" + nextGameID++);
settings.setMaxUsers(1);
settings.setMaxVariablesAllowed(10);
settings.setMaxSpectators(0);
settings.setAutoRemoveMode(SFSRoomRemoveMode.WHEN_EMPTY);
try
{
gameApi.createGame(plugin.getParentZone(), settings, user);
}
catch (SFSCreateRoomException ex)
{
plugin.trace("Could not create practice room! Error " + ex.getMessage());
}
}
}
}
Posted: 14 Nov 2010, 02:46
by ericheimburg
OTHER THINGS TO KNOW: this causes an Invitation to be sent to the invitees -- not too surprising, I know, but it even sends an Invitation to the room's owner! You have to catch this and not let the user reject this invitation.
The docs don't show how to actually HANDLE an Invitation on the client. Here's how (in C#):
Code: Select all
using Sfs2X.Entities.Invitation;
// during setup...
sfs.AddEventListener(SFSEvent.INVITATION, OnInvitation);
private void OnInvitation(BaseEvent evt)
{
SFSInvitation invite = (SFSInvitation)evt.Params["invitation"];
esProxy.Engine.Send(new InvitationReplyRequest(invite,
InvitationReply.ACCEPT));
}
NOTE THE MINOR EXPLOIT SCENARIO: There is a design flaw (as far as I can tell) with the Game system. If none of the invitees ever accept the ticket, not even the "owner" of the game, then the new room can never die, no matter what you set its AutoRemoveMode to.
This means that if a user hacked their game client, or if your game has a bug, then users can create PERMANENT empty rooms on your system. Depending on how you architect your rooms, it may be possible to create an infinite number of permanent empty rooms, jamming the system up good.
The only work-around I've found is to have the extension notice when a room remains empty a long time, and clean it up.
(In the code above, I use an auto-incrementing integer in the room's name. This doesn't fix the exploit -- in fact it makes it worse because now people don't even need to log out/log back in repeatedly to make infinite rooms -- but it did make testing easier while developing the client invitation-handling code.)
Posted: 14 Nov 2010, 16:54
by Lapo
OTHER THINGS TO KNOW: this causes an Invitation to be sent to the invitees -- not too surprising, I know, but it even sends an Invitation to the room's owner! You have to catch this and not let the user reject this invitation.
I don't follow your observation. In your code you are creating a Game Room for one player only and you are inviting the creator of the room itself. So, of course, the invitation goes to the Room owner, as requested... but it doesn't make sense because the user is auto-joined in the GameRoom.
The docs don't show how to actually HANDLE an Invitation on the client. Here's how (in C#):
We do in the Actionscript 3 example, called GameLobby. The example can be run in the browser right away after the installation and you can check the sources of the client there, the GameLobby.as file. Actionscript 3 is very similar to JScript and C#
NOTE THE MINOR EXPLOIT SCENARIO: There is a design flaw (as far as I can tell) with the Game system. If none of the invitees ever accept the ticket, not even the "owner" of the game, then the new room can never die, no matter what you set its AutoRemoveMode to.
I think there is some confusion here.
The owner of the Game is immediately joined in the Room right after the creation and he does not need to invite himself. The invitations should only be sent to the other players.
Hope it helps
Posted: 14 Nov 2010, 22:02
by ericheimburg
Well, using the code above, the user is NOT moved into the room on their own. They just aren't, until they respond to the invitation.
I can't leave them out of the Invite list, either, because then the createGame function fails: Something like "There is not enough invitees for the minimum number of players". So it seems you MUST invite the owner if they are going to be a player.
Posted: 16 Nov 2010, 04:25
by ericheimburg
Seems this works fine for multiplayer games, the game owner IS moved into the room.
But I still have to put the game owner into the Invite list, so that the right number of users are in the game and it will start. If there's something else I'm supposed to be doing, please let me know.
Posted: 16 Nov 2010, 08:12
by Lapo
The user creating the game is always joined in the Room without the need to send any invitations to him. He doesn't need to invite himself

He his the one who's starting the game.
Seems this works fine for multiplayer games, the game owner IS moved into the room.
Ehm...
yes this is done only for multiplayer games. SFS2X is a multiplayer game server.
Did you check the SFS2X-GameLobby example in Flash that we provide? It shows exactly how to work with API, setting up invitations, handling responses and all that. Please take a moment to study that example