The first thing we want to do is create a link to our account for which character they select. It will make it much easier in following messages to look up the player so we can check inventory, check location, etc. So go ahead and add a new models.[GameName]Character to our [GameName]Account class:
import [domain].[domainname].[gamename].models.[GameName]Character;
private [GameName]Character selectedCharacter;
public void setSelectedCharacter([GameName]Character character)
{
selectedCharacter = character;
}
public [GameName]Character getSelectedCharacter()
{
return selectedCharacter;
}
Next we will want to create our handler for the selectCharacter message passed from the client in the last entry. Create it in handlers and lets call it CharacterSelectHandler:
public class CharacterSelectHandler extends BaseClientRequestHandler {
@Override
public void handleClientRequest(User u, ISFSObject data)
{
World world = RoomHelper.getWorld(this);
AegisBornAccount player = world.getPlayer(u);
EntityManager entityManager = ((AegisBornExtension) this.getParentExtension()).getEntityManagerFactory().createEntityManager();
entityManager.getTransaction().begin();
trace("got character select request for: " + data.getLong("characterID"));
Query q = entityManager.createNamedQuery("AegisBornCharacter.findById");
q.setParameter("id", data.getLong("characterID"));
try
{
AegisBornCharacter character = new AegisBornCharacter((com.cjrgaming.aegisborn.persistence.AegisBornCharacter)q.getSingleResult());
trace("found character");
if(character.getCharacter().getUserId().getId() == player.getGuardID())
{
player.setSelectedCharacter(character);
// This needs to send all the player data. from armor, to items, to location
send("characterSelected", new SFSObject(), u);
// Tell everyone the player entered the world use a smaller set of data because they shouldn't know everything the player knows.
send("characterEnteredWorld", player.getSelectedCharacter().createSFSObject(), RoomHelper.getCurrentRoom(this).getPlayersList());
}
else
{
SFSObject err = new SFSObject();
err.putUtfString("error", "That is not a valid character");
send("error", err, u);
}
}
catch(NoResultException nre)
{
trace(nre);
SFSObject err = new SFSObject();
err.putUtfString("error", "That is not a valid character");
send("error", err, u);
}
catch(Exception e)
{
trace(e);
SFSObject err = new SFSObject();
err.putUtfString("error", "That is not a valid character");
send("error", err, u);
}
trace("leaving handler");
}
}
As you can see, it follows the typical pattern of getting the world and account. From there it looks up the character using the passed in ID. if we don't get a result then that character doesn't exist at all. If the database is down or some other error occurs, the generic exception makes us send back that it isn't a valid character. We could put in further data, like "Database is down", but it comes down to how much information you want an attacker to get. If we found a single record using getSingleResult() we create a new model.Character. From this we check if the user_id matches our current user's GuardID. If that fails, it means the user doesn't have that character and someone is trying to hack into another character. We could put a warning here or flag the account in the logs to show someone is trying to hack the server for notice later, but i didn't. Baring all of that failing, we know this character belongs to this user and we can send back a message saying it was successful; thats the characterSelected message. Then we go ahead and do a generic broadcast to ALL users that a new player entered the world. Here is where you would start doing lookups, such as where the user is, and only send this message to players nearby and then do friend lookups on players logged in and inform them that a friend logged in.
The last thing we need to do is add our handler to the extension and we are set to test.
addRequestHandler("selectCharacter", CharacterSelectHandler.class);
At this point our character is set to our user for other messages and we can call this tutorial set done. we can create a user, log in, create a character, and select it and log ourselves in.
I'm going to do some serious cleanup on this code to make it better and more readable and I'll save that for another time. Thanks for stopping by!
No comments:
Post a Comment