diff --git a/game/src/main/org/apollo/game/model/World.java b/game/src/main/org/apollo/game/model/World.java index 29f43e3b..5deaabd7 100644 --- a/game/src/main/org/apollo/game/model/World.java +++ b/game/src/main/org/apollo/game/model/World.java @@ -1,15 +1,14 @@ package org.apollo.game.model; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; -import org.apollo.Server; import org.apollo.Service; import org.apollo.cache.IndexedFileSystem; import org.apollo.cache.decoder.ItemDefinitionDecoder; import org.apollo.cache.decoder.NpcDefinitionDecoder; -import org.apollo.cache.decoder.ObjectDefinitionDecoder; import org.apollo.game.command.CommandDispatcher; import org.apollo.game.fs.decoder.GameObjectDecoder; import org.apollo.game.fs.decoder.SynchronousDecoder; @@ -33,11 +32,9 @@ import org.apollo.util.NameUtil; import com.google.common.base.Preconditions; /** - * The world class is a singleton which contains objects like the - * {@link MobRepository} for players and NPCs. It should only contain things - * relevant to the in-game world and not classes which deal with I/O and such - * (these may be better off inside some custom {@link Service} or other code, - * however, the circumstances are rare). + * The world class is a singleton which contains objects like the {@link MobRepository} for players and NPCs. It should + * only contain things relevant to the in-game world and not classes which deal with I/O and such (these may be better + * off inside some custom {@link Service} or other code, however, the circumstances are rare). * * @author Graham */ @@ -194,8 +191,7 @@ public final class World { * @param release The release number. * @param fs The file system. * @param manager The plugin manager. TODO move this. - * @throws Exception If any definitions could not be loaded or there was a - * failure when loading plugins. + * @throws Exception If there was a failure when loading plugins. */ public void init(int release, IndexedFileSystem fs, PluginManager manager) throws Exception { releaseNumber = release; @@ -206,9 +202,7 @@ public final class World { decoder.block(); - npcMovement = new NpcMovementTask(regions); // Must be exactly here - // because of ordering - // issues. + npcMovement = new NpcMovementTask(regions); // Must be exactly here because of ordering issues. scheduler.schedule(npcMovement); manager.start(); @@ -249,7 +243,7 @@ public final class World { * * @param npc The npc. * @return {@code true} if the npc registered successfully, otherwise - * {@code false}. + * {@code false}. */ public boolean register(Npc npc) { boolean success = npcRepository.add(npc); @@ -348,8 +342,6 @@ public final class World { } } -<<<<<<< HEAD -======= /** * Adds entities to regions in the {@link RegionRepository}. By default, we * do not notify listeners. @@ -359,5 +351,4 @@ public final class World { private void placeEntities(Entity... entities) { Arrays.stream(entities).forEach(entity -> regions.fromPosition(entity.getPosition()).addEntity(entity, false)); } ->>>>>>> c3443521f43dde6310e77de16637503af54805c2 } \ No newline at end of file diff --git a/game/src/main/org/apollo/game/model/entity/Player.java b/game/src/main/org/apollo/game/model/entity/Player.java index 66501ebb..105319e0 100644 --- a/game/src/main/org/apollo/game/model/entity/Player.java +++ b/game/src/main/org/apollo/game/model/entity/Player.java @@ -57,7 +57,7 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; /** - * A {@link Player} is a {@link Mob} that a user is controlling. + * A {@link Mob} that a user is controlling. * * @author Graham * @author Major @@ -296,7 +296,7 @@ public final class Player extends Mob { * * @param username The username of the other player. * @return {@code true} if the specified username is on this player's friend - * list, otherwise {@code false}. + * list, otherwise {@code false}. */ public boolean friendsWith(String username) { return friends.contains(username.toLowerCase()); @@ -415,7 +415,7 @@ public final class Player extends Mob { * Gets the last known region. * * @return The last known region, or {@code null} if the player has never - * known a region. + * known a region. */ public Position getLastKnownRegion() { return lastKnownRegion; @@ -448,6 +448,24 @@ public final class Player extends Mob { return privilegeLevel; } + /** + * Determines the {@link RegistrationStatus} for this player. This method + * can remain lock-free since writes to the player {@link MobRepository} are + * only happening on the game thread. + * + * @return The status. + */ + public RegistrationStatus getRegistrationStatus() { + MobRepository repository = world.getPlayerRepository(); + + if (world.isPlayerOnline(getUsername())) { + return RegistrationStatus.ALREADY_ONLINE; + } else if (repository.capacity() == repository.size()) { + return RegistrationStatus.WORLD_FULL; + } + return RegistrationStatus.OK; + } + /** * Gets the player's run energy. * @@ -605,30 +623,12 @@ public final class Player extends Mob { * Checks if this player is withdrawing noted items. * * @return {@code true} if the player is currently withdrawing notes, - * otherwise {@code false}. + * otherwise {@code false}. */ public boolean isWithdrawingNotes() { return withdrawingNotes; } - /** - * Determines the {@link RegistrationStatus} for this player. This method - * can remain lock-free since writes to the player {@link MobRepository} are - * only happening on the game thread. - * - * @return The status. - */ - public RegistrationStatus getRegistrationStatus() { - MobRepository repository = world.getPlayerRepository(); - - if (world.isPlayerOnline(getUsername())) { - return RegistrationStatus.ALREADY_ONLINE; - } else if (repository.capacity() == repository.size()) { - return RegistrationStatus.WORLD_FULL; - } - return RegistrationStatus.OK; - } - /** * Logs the player out, if possible. */ @@ -670,7 +670,7 @@ public final class Player extends Mob { * * @param username The username. * @return {@code true} if the player's friend list contained the specified - * user, {@code false} if not. + * user, {@code false} if not. */ public boolean removeFriend(String username) { return friends.remove(username.toLowerCase()); @@ -681,7 +681,7 @@ public final class Player extends Mob { * * @param username The username. * @return {@code true} if the player's ignore list contained the specified - * user, {@code false} if not. + * user, {@code false} if not. */ public boolean removeIgnore(String username) { return ignores.remove(username.toLowerCase()); @@ -942,7 +942,7 @@ public final class Player extends Mob { * Sets whether or not the player is withdrawing notes from the bank. * * @param withdrawingNotes Whether or not the player is withdrawing noted - * items. + * items. */ public void setWithdrawingNotes(boolean withdrawingNotes) { this.withdrawingNotes = withdrawingNotes; diff --git a/game/src/main/org/apollo/game/service/GameService.java b/game/src/main/org/apollo/game/service/GameService.java index bc7f207c..b5609850 100644 --- a/game/src/main/org/apollo/game/service/GameService.java +++ b/game/src/main/org/apollo/game/service/GameService.java @@ -26,24 +26,22 @@ import org.apollo.util.xml.XmlParser; import org.xml.sax.SAXException; /** - * The {@link GameService} class schedules and manages the execution of the - * {@link GamePulseHandler} class. + * The {@link GameService} class schedules and manages the execution of the {@link GamePulseHandler} class. * * @author Graham */ public final class GameService extends Service { /** - * The number of times to unregister players per cycle. This is to ensure - * the saving threads don't get swamped with requests and slow everything - * down. + * The amount of players to deregister per cycle. This is to ensure the saving threads don't get swamped with + * requests and slow everything down. */ - private static final int UNREGISTERS_PER_CYCLE = 50; + private static final int DEREGISTRATIONS_PER_CYCLE = 50; /** - * The number of times to register players per cycle. + * The amount of players to register per cycle. */ - private static final int REGISTERS_PER_CYCLE = 25; + private static final int REGISTRATIONS_PER_CYCLE = 25; /** * The World this Service is for. @@ -51,9 +49,9 @@ public final class GameService extends Service { protected final World world; /** - * A queue of players to remove. + * The scheduled executor service. */ - private final Queue oldPlayers = new ConcurrentLinkedQueue<>(); + private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(ThreadUtil.create("GameService")); /** * A queue of players to add. @@ -61,9 +59,9 @@ public final class GameService extends Service { private final Queue newPlayers = new ConcurrentLinkedQueue<>(); /** - * The scheduled executor service. + * A queue of players to remove. */ - private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(ThreadUtil.create("GameService")); + private final Queue oldPlayers = new ConcurrentLinkedQueue<>(); /** * The {@link MessageHandlerChainSet}. @@ -86,15 +84,6 @@ public final class GameService extends Service { init(); } - /** - * Finalizes the unregistration of a player. - * - * @param player The player. - */ - public synchronized void finalizePlayerUnregistration(Player player) { - world.unregister(player); - } - /** * Finalizes the registration of a player. * @@ -110,6 +99,15 @@ public final class GameService extends Service { } } + /** + * Finalizes the unregistration of a player. + * + * @param player The player. + */ + public synchronized void finalizePlayerUnregistration(Player player) { + world.unregister(player); + } + /** * Gets the MessageHandlerChainSet * @@ -129,6 +127,7 @@ public final class GameService extends Service { MobRepository players = world.getPlayerRepository(); for (Player player : players) { GameSession session = player.getSession(); + if (session != null) { session.handlePendingMessages(handlers); } @@ -138,33 +137,6 @@ public final class GameService extends Service { synchronizer.synchronize(players, world.getNpcRepository()); } - /** - * Shuts down this game service. - * - * @param natural Whether or not the shutdown was expected. - */ - public void shutdown(boolean natural) { - scheduledExecutor.shutdownNow(); - // TODO: Other events that should happen upon natural or unexpected - // shutdown. - } - - @Override - public void start() { - scheduledExecutor.scheduleAtFixedRate(new GamePulseHandler(this), GameConstants.PULSE_DELAY, GameConstants.PULSE_DELAY, - TimeUnit.MILLISECONDS); - } - - /** - * Unregisters a player. Returns immediately. The player is unregistered at - * the start of the next cycle. - * - * @param player The player. - */ - public void unregisterPlayer(Player player) { - oldPlayers.add(player); - } - /** * Registers a player. Returns immediately. The player is registered at the * start of the next cycle. @@ -176,26 +148,35 @@ public final class GameService extends Service { } /** - * Finalizes the unregistration of Player's queued to be unregistered. + * Shuts down this game service. + * + * @param natural Whether or not the shutdown was expected. */ - private void finalizeUnregistrations() { - LoginService loginService = context.getLoginService(); + public void shutdown(boolean natural) { + executor.shutdownNow(); + // TODO: Other events that should happen upon natural or unexpected shutdown. + } - for (int count = 0; count < UNREGISTERS_PER_CYCLE; count++) { - Player player = oldPlayers.poll(); - if (player == null) { - break; - } + @Override + public void start() { + executor.scheduleAtFixedRate(new GamePulseHandler(this), GameConstants.PULSE_DELAY, GameConstants.PULSE_DELAY, + TimeUnit.MILLISECONDS); + } - loginService.submitSaveRequest(player.getSession(), player); - } + /** + * Unregisters a player. Returns immediately. The player is unregistered at the start of the next cycle. + * + * @param player The player. + */ + public void unregisterPlayer(Player player) { + oldPlayers.add(player); } /** * Finalizes the registration of Player's queued to be registered. */ private void finalizeRegistrations() { - for (int count = 0; count < REGISTERS_PER_CYCLE; count++) { + for (int count = 0; count < REGISTRATIONS_PER_CYCLE; count++) { Player player = newPlayers.poll(); if (player == null) { break; @@ -205,13 +186,28 @@ public final class GameService extends Service { } } + /** + * Finalizes the unregistration of Player's queued to be unregistered. + */ + private void finalizeUnregistrations() { + LoginService loginService = context.getLoginService(); + + for (int count = 0; count < DEREGISTRATIONS_PER_CYCLE; count++) { + Player player = oldPlayers.poll(); + if (player == null) { + break; + } + + loginService.submitSaveRequest(player.getSession(), player); + } + } + /** * Initializes the game service. * * @throws IOException If there is an error accessing the file. * @throws SAXException If there is an error parsing the file. - * @throws ReflectiveOperationException If a MessageHandler could not be - * created. + * @throws ReflectiveOperationException If a MessageHandler could not be created. */ private void init() throws IOException, SAXException, ReflectiveOperationException { try (InputStream input = new FileInputStream("data/messages.xml")) { diff --git a/game/src/main/org/apollo/game/session/GameSession.java b/game/src/main/org/apollo/game/session/GameSession.java index d42779de..4c817a8b 100644 --- a/game/src/main/org/apollo/game/session/GameSession.java +++ b/game/src/main/org/apollo/game/session/GameSession.java @@ -109,6 +109,15 @@ public final class GameSession extends Session { context.getGameService().finalizePlayerUnregistration(player); } + /** + * Determines if this player is reconnecting. + * + * @return {@code true} if reconnecting, {@code false} otherwise. + */ + public boolean isReconnecting() { + return reconnecting; + } + @Override public void messageReceived(Object message) { if (messages.size() >= GameConstants.MESSAGES_PER_PULSE) { @@ -118,13 +127,4 @@ public final class GameSession extends Session { } } - /** - * Determines if this player is reconnecting. - * - * @return {@code true} if reconnecting, {@code false} otherwise. - */ - public boolean isReconnecting() { - return reconnecting; - } - } \ No newline at end of file diff --git a/game/src/main/org/apollo/game/session/LoginSession.java b/game/src/main/org/apollo/game/session/LoginSession.java index e5df58a3..4be9cd9d 100644 --- a/game/src/main/org/apollo/game/session/LoginSession.java +++ b/game/src/main/org/apollo/game/session/LoginSession.java @@ -51,17 +51,6 @@ public final class LoginSession extends Session { } - /** - * Handles a login request. - * - * @param request The login request. - * @throws IOException If some I/O exception occurs. - */ - private void handleLoginRequest(LoginRequest request) throws IOException { - LoginService service = context.getLoginService(); - service.submitLoadRequest(this, request); - } - /** * Handles a response from the login service. * @@ -87,7 +76,7 @@ public final class LoginSession extends Session { rights = 0; status = registration == RegistrationStatus.ALREADY_ONLINE ? LoginConstants.STATUS_ACCOUNT_ONLINE - : LoginConstants.STATUS_SERVER_FULL; + : LoginConstants.STATUS_SERVER_FULL; } else { GameSession session = new GameSession(channel, context, player, request.isReconnecting()); channel.attr(ApolloHandler.SESSION_KEY).set(session); @@ -107,7 +96,7 @@ public final class LoginSession extends Session { channel.pipeline().addBefore("messageEncoder", "gameEncoder", new GamePacketEncoder(randomPair.getEncodingRandom())); channel.pipeline().addBefore("handler", "gameDecoder", - new GamePacketDecoder(randomPair.getDecodingRandom(), context.getRelease())); + new GamePacketDecoder(randomPair.getDecodingRandom(), context.getRelease())); channel.pipeline().addAfter("gameDecoder", "messageDecoder", new GameMessageDecoder(release)); channel.pipeline().remove("loginDecoder"); @@ -124,4 +113,15 @@ public final class LoginSession extends Session { handleLoginRequest((LoginRequest) message); } } + + /** + * Handles a login request. + * + * @param request The login request. + * @throws IOException If some I/O exception occurs. + */ + private void handleLoginRequest(LoginRequest request) throws IOException { + LoginService service = context.getLoginService(); + service.submitLoadRequest(this, request); + } } \ No newline at end of file diff --git a/game/src/main/org/apollo/game/session/Session.java b/game/src/main/org/apollo/game/session/Session.java index a9f19deb..9fa0233f 100644 --- a/game/src/main/org/apollo/game/session/Session.java +++ b/game/src/main/org/apollo/game/session/Session.java @@ -29,6 +29,14 @@ public abstract class Session { */ public abstract void destroy(); + /** + * Processes a message received from the channel. + * + * @param message The message. + * @throws Exception If some error occurs. + */ + public abstract void messageReceived(Object message) throws Exception; + /** * Gets the channel. * @@ -38,12 +46,4 @@ public abstract class Session { return channel; } - /** - * Processes a message received from the channel. - * - * @param message The message. - * @throws Exception If some error occurs. - */ - public abstract void messageReceived(Object message) throws Exception; - } \ No newline at end of file