/** * Sets the room this player is currently in. If the room given is null, marks the player as not * in any room. * * <p> * * @param room the room this player should be in, or {@code null} */ protected void setRoom(SwordWorldRoom room) { DataManager dataManager = AppContext.getDataManager(); dataManager.markForUpdate(this); if (room == null) { currentRoomRef = null; return; } currentRoomRef = dataManager.createReference(room); }
/** * Sets the current <code>UserID</code> for this <code>Player</code>, which changes from session * to session. Typically this is called when the player first logs again, and not again until the * player logs out and logs back in. * * @param uid the player's user identifier */ public void setCurrentSession(ClientSession session) { DataManager dataMgr = AppContext.getDataManager(); dataMgr.markForUpdate(this); currentSessionRef = dataMgr.createReference(session); // Also inform the client of the session ID // FIXME, this is hacked in as the only non-channel message // for ease of porting -JM BigInteger sid = currentSessionRef.getId(); byte[] bytes = sid.toByteArray(); session.send(ByteBuffer.wrap(bytes)); }
/** * Called when the player joins a channel. In this system, the player only joins a new channel in * the context of joining a new game, and the player is never on more than one channel. * * @param cid the new channel */ public void userJoinedChannel(UtilChannel newChannel) { DataManager dataManager = AppContext.getDataManager(); dataManager.markForUpdate(this); channelRef = dataManager.createReference(newChannel); }
/** * Mark this player as logged in on the given session. * * @param session the session this player is logged in on */ protected void setSession(ClientSession session) { DataManager dataMgr = AppContext.getDataManager(); dataMgr.markForUpdate(this); currentSessionRef = dataMgr.createReference(session); logger.log(Level.INFO, "Set session for {0} to {1}", new Object[] {this, session}); }
/** * This method takes a <code>StreamTokenizer</code> that is setup at the start of a single dungeon * file, and loads all the data, creating the AIs, stitching together all connectors between * levels, etc. At the end a single <code>Connector</code> is provded as an entry point to the * dungeon. * * <p>FIXME: we should make the aggregator real, or remove it and go back to use of the PDTimer * directly. * * @param stok the stream to tokenize * @param gameName the name of the dungeon this is being loaded into * @param impassableSprites the set of identifiers that are impassable * @param lobbyRef a reference to the lobby * @param eventAg an aggreagator for all AI tasks * @return a reference to a <code>GameConnector</code> that is the connection between the dungeon * and the lobby * @throws IOException if the stream isn't formatted correctly */ public static GameConnector loadDungeon( StreamTokenizer stok, String gameName, Set<Integer> impassableSprites, Game lobby) throws IOException { DataManager dataManager = AppContext.getDataManager(); // the prefix for all level names String levelPrefix = gameName + ":" + SimpleLevel.NAME_PREFIX; // details about where we enter the dungeon String entryLevel = null; int entryX = 0; int entryY = 0; // the collection of boards and levels HashMap<String, SimpleBoard> boards = new HashMap<String, SimpleBoard>(); HashMap<String, ManagedReference<SimpleLevel>> levelRefs = // simplelevel new HashMap<String, ManagedReference<SimpleLevel>>(); // the various kinds of connectors HashSet<ConnectionData> connections = new HashSet<ConnectionData>(); HashSet<ConnectionData> oneWays = new HashSet<ConnectionData>(); HashSet<ConnectionData> playerConnectors = new HashSet<ConnectionData>(); // the collection of Monster (AI) and NPC characters // to AICharacterManager HashMap<String, HashSet<ManagedReference<AICharacterManager>>> npcMap = new HashMap<String, HashSet<ManagedReference<AICharacterManager>>>(); HashMap<String, HashSet<ManagedReference<AICharacterManager>>> aiMap = new HashMap<String, HashSet<ManagedReference<AICharacterManager>>>(); // first, parse the data file itself while (stok.nextToken() != StreamTokenizer.TT_EOF) { if (stok.sval.equals("EntryPoint")) { // an Entry is LEVEL X_POS Y_POS stok.nextToken(); entryLevel = levelPrefix + stok.sval; stok.nextToken(); entryX = (int) (stok.nval); stok.nextToken(); entryY = (int) (stok.nval); } else if (stok.sval.equals("DefineLevel")) { // levels are handled separately by SimpleLevel stok.nextToken(); String levelName = levelPrefix + stok.sval; boards.put(levelName, new SimpleBoard(stok, impassableSprites)); } else if (stok.sval.equals("Connection")) { connections.add(readConnection(stok, levelPrefix)); } else if (stok.sval.equals("OneWayConnection")) { oneWays.add(readConnection(stok, levelPrefix)); } else if (stok.sval.equals("PlayerConnection")) { playerConnectors.add(readConnection(stok, levelPrefix)); } else if (stok.sval.equals("NPC")) { // an NPC is LEVEL NAME ID MESSAGE_1 [ ... MESSAGE_N ] stok.nextToken(); String levelName = levelPrefix + stok.sval; stok.nextToken(); String npcName = stok.sval; stok.nextToken(); int id = (int) (stok.nval); stok.nextToken(); int count = (int) (stok.nval); String[] messages = new String[count]; for (int i = 0; i < count; i++) { stok.nextToken(); messages[i] = stok.sval; } // create the manager for the NPC and the NPC itself AICharacterManager aiCMR = AICharacterManager.newInstance(); NPCharacter npc = new NPCharacter(id, npcName, messages, aiCMR); aiCMR.setCharacter(npc); // put it into a bucket for the given level, creating the // bucket if it doesn't already exist // to AICharacterManager HashSet<ManagedReference<AICharacterManager>> set = npcMap.get(levelName); if (set == null) { set = new HashSet<ManagedReference<AICharacterManager>>(); npcMap.put(levelName, set); } set.add(dataManager.createReference(aiCMR)); } else if (stok.sval.equals("Monster")) { // a Monster is LEVEL TYPE ID stok.nextToken(); String levelName = levelPrefix + stok.sval; stok.nextToken(); String type = stok.sval; stok.nextToken(); int id = (int) (stok.nval); // create the manager and get the right instance AICharacterManager aiCMR = MonsterFactory.getMonster(id, type); // put the monster into a bucket for the given level, creating // the bucket if it doesn't already exist HashSet<ManagedReference<AICharacterManager>> set = aiMap.get(levelName); if (set == null) { set = new HashSet<ManagedReference<AICharacterManager>>(); aiMap.put(levelName, set); } set.add(dataManager.createReference(aiCMR)); } else { throw new IOException("Unknown type: " + stok.sval + " on line " + stok.lineno()); } } // next, create a GLO for each of the levels for (String levelName : boards.keySet()) { SimpleLevel level = new SimpleLevel(levelName, gameName); String gloName = Game.NAME_PREFIX + levelName; dataManager.setBinding(gloName, level); levelRefs.put(levelName, dataManager.createReference(level)); } // with the levels in place, we can generate the connectors and // assign them to their board spaces for (ConnectionData data : connections) { // create a connector and register it SimpleConnector connector = new SimpleConnector( levelRefs.get(data.level1).get(), data.level1X, data.level1Y, levelRefs.get(data.level2).get(), data.level2X, data.level2Y); // notify both boards of the connector boards.get(data.level1).setAsConnector(data.level1X, data.level1Y, connector); boards.get(data.level2).setAsConnector(data.level2X, data.level2Y, connector); } // we also get the player connectors for (ConnectionData data : playerConnectors) { // create a connector and register it PlayerConnector connector = new PlayerConnector( levelRefs.get(data.level1).get(), data.level1X, data.level1Y, levelRefs.get(data.level2).get(), data.level2X, data.level2Y); // notify both boards of the connector boards.get(data.level1).setAsConnector(data.level1X, data.level1Y, connector); boards.get(data.level2).setAsConnector(data.level2X, data.level2Y, connector); } // same for the one-ways, except that we only set one side for (ConnectionData data : oneWays) { // create the connector and register it OneWayConnector connector = new OneWayConnector(levelRefs.get(data.level2).get(), data.level2X, data.level2Y); // notify the source board of the connector boards.get(data.level1).setAsConnector(data.level1X, data.level1Y, connector); } // also generate the entry connector, register it, and set it for // the entry board GameConnector gameConnector = new GameConnector(lobby, levelRefs.get(entryLevel).get(), entryX, entryY); boards.get(entryLevel).setAsConnector(entryX, entryY, gameConnector); // with all the connectors in place, notify the levels for (ManagedReference<SimpleLevel> levelRef : levelRefs.values()) { SimpleLevel level = levelRef.get(); level.setBoard(boards.get(level.getName())); } TaskManager taskManager = AppContext.getTaskManager(); // now that the levels are all set, add the NPC characters to the // levels and the timer for (String levelName : npcMap.keySet()) { Level level = levelRefs.get(levelName).get(); for (ManagedReference<AICharacterManager> mgrRef : npcMap.get(levelName)) { AICharacterManager mgr = mgrRef.get(); taskManager.schedulePeriodicTask(mgr, 0, 1700); // eventAg.addCharacterMgr(mgr); level.addCharacter(mgr); } } // add the Monsters too for (String levelName : aiMap.keySet()) { Level level = levelRefs.get(levelName).get(); for (ManagedReference<AICharacterManager> mgrRef : aiMap.get(levelName)) { AICharacterManager mgr = mgrRef.get(); taskManager.schedulePeriodicTask(mgr, 0, 1100); // eventAg.addCharacterMgr(mgr); level.addCharacter(mgr); } } // finally add, the items // FIXME: support items in file format // return the game connector, which is all the Dungeon needs to // interact with everything we've setup here return gameConnector; }