From ed160ef70e2d2418047e7a7a6b45818393005a7f Mon Sep 17 00:00:00 2001 From: Major- Date: Mon, 24 Aug 2015 14:41:19 +0100 Subject: [PATCH] Fix travelback implementation. --- .../org/apollo/game/GamePulseHandler.java | 8 +- .../message/handler/WalkMessageHandler.java | 6 +- .../main/org/apollo/game/model/Direction.java | 53 ++-- .../org/apollo/game/model/entity/Player.java | 83 +++-- .../game/model/entity/WalkingQueue.java | 297 +++++++----------- .../game/scheduling/impl/NpcMovementTask.java | 4 +- .../org/apollo/game/service/GameService.java | 62 ++-- .../sync/task/PlayerSynchronizationTask.java | 26 +- .../task/PrePlayerSynchronizationTask.java | 45 +-- 9 files changed, 264 insertions(+), 320 deletions(-) diff --git a/game/src/main/org/apollo/game/GamePulseHandler.java b/game/src/main/org/apollo/game/GamePulseHandler.java index 8807dde8..fc53f6c5 100644 --- a/game/src/main/org/apollo/game/GamePulseHandler.java +++ b/game/src/main/org/apollo/game/GamePulseHandler.java @@ -13,7 +13,7 @@ import org.apollo.game.service.GameService; public final class GamePulseHandler implements Runnable { /** - * The logger for this class. + * The Logger for this class. */ private static final Logger logger = Logger.getLogger(GamePulseHandler.class.getName()); @@ -23,7 +23,7 @@ public final class GamePulseHandler implements Runnable { private final GameService service; /** - * Creates the game pulse handler object. + * Creates the GamePulseHandler. * * @param service The {@link GameService}. */ @@ -35,8 +35,8 @@ public final class GamePulseHandler implements Runnable { public void run() { try { service.pulse(); - } catch (Throwable reason) { - logger.log(Level.SEVERE, "Exception occured during pulse!", reason); + } catch (Throwable throwable) { + logger.log(Level.SEVERE, "Exception occurred during pulse!", throwable); } } diff --git a/game/src/main/org/apollo/game/message/handler/WalkMessageHandler.java b/game/src/main/org/apollo/game/message/handler/WalkMessageHandler.java index 5efdd45f..21140d84 100644 --- a/game/src/main/org/apollo/game/message/handler/WalkMessageHandler.java +++ b/game/src/main/org/apollo/game/message/handler/WalkMessageHandler.java @@ -30,15 +30,13 @@ public final class WalkMessageHandler extends MessageHandler { for (int index = 0; index < steps.length; index++) { Position step = steps[index]; if (index == 0) { - if (!queue.addFirstStep(step)) { - return; // ignore packet - } + queue.addFirstStep(step); } else { queue.addStep(step); } } - queue.setRunningQueue(message.isRunning() || player.isRunning()); + queue.setRunning(message.isRunning() || player.isRunning()); player.getInterfaceSet().close(); if (queue.size() > 0) { diff --git a/game/src/main/org/apollo/game/model/Direction.java b/game/src/main/org/apollo/game/model/Direction.java index e3123e94..85e49902 100644 --- a/game/src/main/org/apollo/game/model/Direction.java +++ b/game/src/main/org/apollo/game/model/Direction.java @@ -58,48 +58,43 @@ public enum Direction { public static final Direction[] EMPTY_DIRECTION_ARRAY = new Direction[0]; /** - * Creates a direction from the differences between X and Y. + * Gets the Direction between the two {@link Position}s.. * - * @param deltaX The difference between two X coordinates. - * @param deltaY The difference between two Y coordinates. + * @param current The difference between two X coordinates. + * @param next The difference between two Y coordinates. * @return The direction. */ - public static Direction fromDeltas(int deltaX, int deltaY) { + public static Direction between(Position current, Position next) { + int deltaX = next.getX() - current.getX(); + int deltaY = next.getY() - current.getY(); + if (deltaY == 1) { if (deltaX == 1) { - return Direction.NORTH_EAST; + return NORTH_EAST; } else if (deltaX == 0) { - return Direction.NORTH; + return NORTH; + } else if (deltaX == -1) { + return NORTH_WEST; } - return Direction.NORTH_WEST; } else if (deltaY == -1) { if (deltaX == 1) { - return Direction.SOUTH_EAST; + return SOUTH_EAST; } else if (deltaX == 0) { - return Direction.SOUTH; - } - return Direction.SOUTH_WEST; - } else { - if (deltaX == 1) { - return Direction.EAST; + return SOUTH; } else if (deltaX == -1) { - return Direction.WEST; + return SOUTH_WEST; + } + } else if (deltaY == 0) { + if (deltaX == 1) { + return EAST; + } else if (deltaX == 0) { + return NONE; + } else if (deltaX == -1) { + return WEST; } } - return Direction.NONE; - } - - /** - * Checks if the direction represented by the two delta values can connect two points together in a single - * direction. - * - * @param deltaX The difference in X coordinates. - * @param deltaY The difference in X coordinates. - * @return {@code true} if so, {@code false} if not. - */ - public static boolean isConnectable(int deltaX, int deltaY) { - return Math.abs(deltaX) == Math.abs(deltaY) || deltaX == 0 || deltaY == 0; + throw new IllegalArgumentException("Difference between Positions must be [-1, 1]."); } /** @@ -112,7 +107,7 @@ public enum Direction { * * @param intValue The direction as an integer. */ - private Direction(int intValue) { + Direction(int intValue) { this.intValue = intValue; } 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 6fb51f9a..6c7b312a 100644 --- a/game/src/main/org/apollo/game/model/entity/Player.java +++ b/game/src/main/org/apollo/game/model/entity/Player.java @@ -67,16 +67,36 @@ public final class Player extends Mob { AttributeMap.define("run_energy", AttributeDefinition.forInt(100, AttributePersistence.PERSISTENT)); } - /** - * The player's appearance. - */ - private Appearance appearance = Appearance.DEFAULT_APPEARANCE; - /** * This player's bank. */ private final Inventory bank = new Inventory(InventoryConstants.BANK_CAPACITY, StackMode.STACK_ALWAYS); + /** + * This player's credentials. + */ + private final PlayerCredentials credentials; + + /** + * This player's interface set. + */ + private final InterfaceSet interfaceSet = new InterfaceSet(this); + + /** + * The Set of DynamicGameObjects that are visible to this Player. + */ + private final Set localObjects = new HashSet<>(); + + /** + * A temporary queue of messages sent during the login process. + */ + private final Deque queuedMessages = new ArrayDeque<>(); + + /** + * The player's appearance. + */ + private Appearance appearance = Appearance.DEFAULT_APPEARANCE; + /** * The privacy state of this player's public chat. */ @@ -87,11 +107,6 @@ public final class Player extends Mob { */ private Deque clicks = new ArrayDeque<>(); - /** - * This player's credentials. - */ - private final PlayerCredentials credentials; - /** * A flag which indicates there are npcs that couldn't be added. */ @@ -122,11 +137,6 @@ public final class Player extends Mob { */ private List ignores = new ArrayList<>(); - /** - * This player's interface set. - */ - private final InterfaceSet interfaceSet = new InterfaceSet(this); - /** * Whether or not the player is skulled. */ @@ -137,11 +147,6 @@ public final class Player extends Mob { */ private Position lastKnownRegion; - /** - * The Set of DynamicGameObjects that are visible to this Player. - */ - private final Set localObjects = new HashSet<>(); - /** * The MembershipStatus of this Player. */ @@ -157,11 +162,6 @@ public final class Player extends Mob { */ private PrivilegeLevel privilegeLevel = PrivilegeLevel.STANDARD; - /** - * A temporary queue of messages sent during the login process. - */ - private final Deque queuedMessages = new ArrayDeque<>(); - /** * A flag indicating if the region changed in the last cycle. */ @@ -506,11 +506,6 @@ public final class Player extends Mob { return worldId; } - @Override - public int hashCode() { - return credentials.hashCode(); - } - /** * Indicates whether or not the player with the specified username is on this player's ignore list. * @@ -539,6 +534,11 @@ public final class Player extends Mob { return regionChanged; } + @Override + public int hashCode() { + return credentials.hashCode(); + } + /** * Increments this player's viewing distance if it is less than the maximum viewing distance. */ @@ -790,15 +790,6 @@ public final class Player extends Mob { this.chatPrivacy = chatPrivacy; } - /** - * Sets the value denoting the client's modified version. - * - * @param version The client version. - */ - public void setClientVersion(int version) { - attributes.set("client_version", new NumericalAttribute(version)); - } - /** * Sets the friend {@link PrivacyState}. * @@ -939,6 +930,12 @@ public final class Player extends Mob { } } + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("username", getUsername()).add("privilege", privilegeLevel) + .toString(); + } + /** * Toggles the message filter. * @@ -953,16 +950,10 @@ public final class Player extends Mob { */ public void toggleRunning() { running = !running; - walkingQueue.setRunningQueue(running); + walkingQueue.setRunning(running); send(new ConfigMessage(173, running ? 1 : 0)); } - @Override - public String toString() { - return MoreObjects.toStringHelper(this).add("username", getUsername()).add("privilege", privilegeLevel) - .toString(); - } - /** * Initialises this player. */ diff --git a/game/src/main/org/apollo/game/model/entity/WalkingQueue.java b/game/src/main/org/apollo/game/model/entity/WalkingQueue.java index cf3b7e29..81020821 100644 --- a/game/src/main/org/apollo/game/model/entity/WalkingQueue.java +++ b/game/src/main/org/apollo/game/model/entity/WalkingQueue.java @@ -7,8 +7,6 @@ import java.util.Queue; import org.apollo.game.model.Direction; import org.apollo.game.model.Position; -import com.google.common.base.MoreObjects; - /** * A queue of {@link Direction}s which a {@link Mob} will follow. * @@ -17,162 +15,167 @@ import com.google.common.base.MoreObjects; public final class WalkingQueue { /** - * Represents a single point in the queue. - * - * @author Graham - */ - private static final class Point { - - /** - * The direction to walk to this point. - */ - private final Direction direction; - - /** - * The point's position. - */ - private final Position position; - - /** - * Creates a point. - * - * @param position The position. - * @param direction The direction. - */ - public Point(Position position, Direction direction) { - this.position = position; - this.direction = direction; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this).add("direction", direction).add("position", position) - .toString(); - } - - } - - /** - * The maximum size of the queue. If any additional steps are added, they are discarded. - */ - private static final int MAXIMUM_SIZE = 128; - - /** - * The mob whose walking queue this is. + * The Mob this WalkingQueue belongs to. */ private final Mob mob; /** - * The old queue of directions. + * The Deque of active points in this WalkingQueue. */ - private final Deque oldPoints = new ArrayDeque<>(); + private final Deque points = new ArrayDeque<>(); /** - * The queue of directions. + * The Deque of previous points in this WalkingQueue. */ - private final Deque points = new ArrayDeque<>(); + private final Deque previousPoints = new ArrayDeque<>(); /** - * Flag indicating if this queue (only) should be ran. + * The running status of this WalkingQueue. */ - private boolean runningQueue; + private boolean running; /** - * Creates a walking queue for the specified mob. + * Creates the WalkingQueue. * - * @param mob The mob. + * @param mob The {@link Mob} the WalkingQueue is for. */ public WalkingQueue(Mob mob) { this.mob = mob; } /** - * Adds the first step to the queue, attempting to connect the server and client position by looking at the - * previous queue. + * Adds a first step into this WalkingQueue. * - * @param clientPosition The first step. - * @return {@code true} if the queues could be connected correctly, {@code false} if not. + * @param next The {@link Position} of the step. */ - public boolean addFirstStep(Position clientPosition) { - Position serverPosition = mob.getPosition(); + public void addFirstStep(Position next) { + points.clear(); + running = false; - int deltaX = clientPosition.getX() - serverPosition.getX(); - int deltaY = clientPosition.getY() - serverPosition.getY(); + /* + * We need to connect 'current' and 'next' whilst accounting for the + * fact that the client and server might be out of sync (i.e. what the + * client thinks is 'current' is different to what the server thinks is + * 'current'). + * + * First try to connect them via points from the previous queue. + */ + Queue backtrack = new ArrayDeque<>(); - if (Direction.isConnectable(deltaX, deltaY)) { - points.clear(); - oldPoints.clear(); + while (!previousPoints.isEmpty()) { + Position position = previousPoints.pollLast(); + backtrack.add(position); - addStep(clientPosition); - return true; - } - - Queue travelBackQueue = new ArrayDeque<>(); - - Point oldPoint; - while ((oldPoint = oldPoints.pollLast()) != null) { - Position oldPosition = oldPoint.position; - - deltaX = oldPosition.getX() - serverPosition.getX(); - deltaY = oldPosition.getX() - serverPosition.getY(); - - travelBackQueue.add(oldPosition); - - if (Direction.isConnectable(deltaX, deltaY)) { - points.clear(); - oldPoints.clear(); - - travelBackQueue.forEach(this::addStep); - - addStep(clientPosition); - return true; + if (position.equals(next)) { + backtrack.forEach(this::addStep); + previousPoints.clear(); + return; } } - oldPoints.clear(); - return false; + /* If that doesn't work, connect the points directly. */ + previousPoints.clear(); + addStep(next); } /** - * Adds a step. + * Adds a step to this WalkingQueue. * - * @param x The x coordinate of this step. - * @param y The y coordinate of this step. + * @param next The {@link Position} of the step. */ - private void addStep(int x, int y) { - if (points.size() >= MAXIMUM_SIZE) { - return; + public void addStep(Position next) { + Position current = points.peekLast(); + + /* + * If current equals next, addFirstStep doesn't end up adding anything points queue. This makes peekLast() + * return null. If it does, the correct behaviour is to fill it in with mob.getPosition(). + */ + if (current == null) { + current = mob.getPosition(); } - Point last = getLast(); - - int deltaX = x - last.position.getX(); - int deltaY = y - last.position.getY(); - - Direction direction = Direction.fromDeltas(deltaX, deltaY); - - if (direction != Direction.NONE) { - Point point = new Point(new Position(x, y, mob.getPosition().getHeight()), direction); - points.add(point); - oldPoints.add(point); - } + addStep(current, next); } /** - * Adds a step to the queue. - * - * @param step The step to add. + * Clears this WalkingQueue. */ - public void addStep(Position step) { - int x = step.getX(), y = step.getY(); - Point last = getLast(); + public void clear() { + points.clear(); + running = false; + previousPoints.clear(); + } - int deltaX = x - last.position.getX(); - int deltaY = y - last.position.getY(); + /** + * Returns whether or not this WalkingQueue has running enabled. + * + * @return {@code true} iff this WalkingQueue has running enabled. + */ + public boolean isRunning() { + return running; + } + + /** + * Pulses this WalkingQueue. + */ + public void pulse() { + Position position = mob.getPosition(); + + Direction firstDirection = Direction.NONE; + Direction secondDirection = Direction.NONE; + + Position next = points.poll(); + if (next != null) { + previousPoints.add(next); + firstDirection = Direction.between(position, next); + position = next; + + if (running) { + next = points.poll(); + if (next != null) { + previousPoints.add(next); + secondDirection = Direction.between(position, next); + position = next; + } + } + } + + mob.setDirections(firstDirection, secondDirection); + mob.setPosition(position); + } + + /** + * Sets the running flag status of this WalkingQueue. + * + * @param running The running flag. + */ + public void setRunning(boolean running) { + this.running = running; + } + + /** + * Gets the size of this WalkingQueue, which is the number of points remaining in it. + * + * @return The size. + */ + public int size() { + return points.size(); + } + + /** + * Adds the {@code next} step to this WalkingQueue. + * + * @param current The current {@link Position}. + * @param next The next Position. + */ + private void addStep(Position current, Position next) { + int nextX = next.getX(), nextY = next.getY(), height = next.getHeight(); + int deltaX = nextX - current.getX(); + int deltaY = nextY - current.getY(); int max = Math.max(Math.abs(deltaX), Math.abs(deltaY)); - for (int i = 0; i < max; i++) { + for (int count = 0; count < max; count++) { if (deltaX < 0) { deltaX++; } else if (deltaX > 0) { @@ -185,70 +188,8 @@ public final class WalkingQueue { deltaY--; } - addStep(x - deltaX, y - deltaY); + points.add(new Position(nextX - deltaX, nextY - deltaY, height)); } } - /** - * Clears the walking queue. - */ - public void clear() { - points.clear(); - oldPoints.clear(); - } - - /** - * Gets the last point. - * - * @return The last point. - */ - private Point getLast() { - return points.isEmpty() ? new Point(mob.getPosition(), Direction.NONE) : points.peekLast(); - } - - /** - * Called every pulse, updates the queue. - */ - public void pulse() { - Position position = mob.getPosition(); - Direction first = Direction.NONE, second = Direction.NONE; - - Point next = points.poll(); - if (next != null) { - first = next.direction; - position = next.position; - - if (runningQueue /* and enough energy */) { - next = points.poll(); - - if (next != null) { - second = next.direction; - position = next.position; - } - } - - mob.setPosition(position); - } - - mob.setDirections(first, second); - } - - /** - * Sets the running queue flag. - * - * @param running The running queue flag. - */ - public void setRunningQueue(boolean running) { - runningQueue = running; - } - - /** - * Gets the size of the queue. - * - * @return The size of the queue. - */ - public int size() { - return points.size(); - } - } \ No newline at end of file diff --git a/game/src/main/org/apollo/game/scheduling/impl/NpcMovementTask.java b/game/src/main/org/apollo/game/scheduling/impl/NpcMovementTask.java index 4d3abed2..36e99508 100644 --- a/game/src/main/org/apollo/game/scheduling/impl/NpcMovementTask.java +++ b/game/src/main/org/apollo/game/scheduling/impl/NpcMovementTask.java @@ -93,7 +93,9 @@ public final class NpcMovementTask extends ScheduledTask { WalkingQueue queue = npc.getWalkingQueue(); Position first = positions.pollFirst(); - if (first != null && queue.addFirstStep(first)) { + + if (first != null) { + queue.addFirstStep(first); positions.forEach(queue::addStep); } diff --git a/game/src/main/org/apollo/game/service/GameService.java b/game/src/main/org/apollo/game/service/GameService.java index c206b606..7253bc96 100644 --- a/game/src/main/org/apollo/game/service/GameService.java +++ b/game/src/main/org/apollo/game/service/GameService.java @@ -33,11 +33,6 @@ import org.xml.sax.SAXException; */ public final class GameService extends Service { - /** - * The World this Service is for. - */ - protected final World world; - /** * 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. @@ -45,9 +40,9 @@ public final class GameService extends Service { private static final int UNREGISTERS_PER_CYCLE = 50; /** - * The {@link MessageHandlerChainSet}. + * The World this Service is for. */ - private MessageHandlerChainSet messageHandlerChainSet; + protected final World world; /** * A queue of players to remove. @@ -60,6 +55,11 @@ public final class GameService extends Service { private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(ThreadUtil .create("GameService")); + /** + * The {@link MessageHandlerChainSet}. + */ + private MessageHandlerChainSet handlers; + /** * The {@link ClientSynchronizer}. */ @@ -90,30 +90,28 @@ public final class GameService extends Service { /** * Gets the MessageHandlerChainSet * - * @return The set of MessageHandlerChain's. + * @return The MessageHandlerChainSet. */ public MessageHandlerChainSet getMessageHandlerChainSet() { - return messageHandlerChainSet; + return handlers; } /** * Called every pulse. */ - public void pulse() { - synchronized (this) { - finalizeUnregisters(); + public synchronized void pulse() { + finalizeUnregistrations(); - MobRepository players = world.getPlayerRepository(); - for (Player player : players) { - GameSession session = player.getSession(); - if (session != null) { - session.handlePendingMessages(messageHandlerChainSet); - } + MobRepository players = world.getPlayerRepository(); + for (Player player : players) { + GameSession session = player.getSession(); + if (session != null) { + session.handlePendingMessages(handlers); } - - world.pulse(); - synchronizer.synchronize(players, world.getNpcRepository()); } + + world.pulse(); + synchronizer.synchronize(players, world.getNpcRepository()); } /** @@ -123,18 +121,16 @@ public final class GameService extends Service { * @param session The {@link GameSession} of the Player. * @return A {@link RegistrationStatus}. */ - public RegistrationStatus registerPlayer(Player player, GameSession session) { - synchronized (this) { - RegistrationStatus status = world.register(player); - if (status == RegistrationStatus.OK) { - player.setSession(session); + public synchronized RegistrationStatus registerPlayer(Player player, GameSession session) { + RegistrationStatus status = world.register(player); + if (status == RegistrationStatus.OK) { + player.setSession(session); - Region region = world.getRegionRepository().get(player.getPosition().getRegionCoordinates()); - region.addEntity(player); - } - - return status; + Region region = world.getRegionRepository().fromPosition(player.getPosition()); + region.addEntity(player); } + + return status; } /** @@ -165,7 +161,7 @@ public final class GameService extends Service { /** * Finalizes the unregistration of Player's queued to be unregistered. */ - private void finalizeUnregisters() { + private void finalizeUnregistrations() { LoginService loginService = context.getLoginService(); for (int count = 0; count < UNREGISTERS_PER_CYCLE; count++) { @@ -188,7 +184,7 @@ public final class GameService extends Service { private void init() throws IOException, SAXException, ReflectiveOperationException { try (InputStream input = new FileInputStream("data/messages.xml")) { MessageHandlerChainSetParser chainSetParser = new MessageHandlerChainSetParser(input); - messageHandlerChainSet = chainSetParser.parse(world); + handlers = chainSetParser.parse(world); } try (InputStream input = new FileInputStream("data/synchronizer.xml")) { diff --git a/game/src/main/org/apollo/game/sync/task/PlayerSynchronizationTask.java b/game/src/main/org/apollo/game/sync/task/PlayerSynchronizationTask.java index 637144cd..3decca26 100644 --- a/game/src/main/org/apollo/game/sync/task/PlayerSynchronizationTask.java +++ b/game/src/main/org/apollo/game/sync/task/PlayerSynchronizationTask.java @@ -67,9 +67,10 @@ public final class PlayerSynchronizationTask extends SynchronizationTask { int oldLocalPlayers = localPlayers.size(); List segments = new ArrayList<>(); - for (Iterator it = localPlayers.iterator(); it.hasNext();) { + for (Iterator it = localPlayers.iterator(); it.hasNext(); ) { Player other = it.next(); - if (!other.isActive() || other.isTeleporting() || other.getPosition().getLongestDelta(player.getPosition()) > player.getViewingDistance() || !other.getPosition().isWithinDistance(player.getPosition(), player.getViewingDistance())) { + + if (removePlayer(other)) { it.remove(); segments.add(new RemoveMobSegment()); } else { @@ -103,8 +104,27 @@ public final class PlayerSynchronizationTask extends SynchronizationTask { } } - PlayerSynchronizationMessage message = new PlayerSynchronizationMessage(lastKnownRegion, player.getPosition(), regionChanged, segment, oldLocalPlayers, segments); + PlayerSynchronizationMessage message = new PlayerSynchronizationMessage(lastKnownRegion, player.getPosition(), + regionChanged, segment, oldLocalPlayers, segments); player.send(message); } + /** + * Returns whether or not the specified {@link Player} should be removed. + * + * @param other The Player being tested. + * @return {@code true} iff the specified Player should be removed. + */ + private boolean removePlayer(Player other) { + if (other.isTeleporting() || !other.isActive()) { + return true; + } + + Position position = player.getPosition(); + Position otherPosition = other.getPosition(); + int distance = player.getViewingDistance(); + + return otherPosition.getLongestDelta(position) > distance || !otherPosition.isWithinDistance(position, distance); + } + } \ No newline at end of file diff --git a/game/src/main/org/apollo/game/sync/task/PrePlayerSynchronizationTask.java b/game/src/main/org/apollo/game/sync/task/PrePlayerSynchronizationTask.java index 6f435d7f..eedc64cb 100644 --- a/game/src/main/org/apollo/game/sync/task/PrePlayerSynchronizationTask.java +++ b/game/src/main/org/apollo/game/sync/task/PrePlayerSynchronizationTask.java @@ -66,7 +66,8 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask { private final Map> snapshots; /** - * The Map of RegionCoordinates to Sets of RegionUpdateMessages, which contain the updates for a Region a Player can + * The Map of RegionCoordinates to Sets of RegionUpdateMessages, which contain the updates for a Region a Player + * can * already view. */ private final Map> updates; @@ -78,7 +79,8 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask { * @param updates The {@link Map} containing {@link Region} updates. * @param snapshots The Map containing Region snapshots. */ - public PrePlayerSynchronizationTask(Player player, Map> updates, Map> snapshots) { + public PrePlayerSynchronizationTask(Player player, Map> updates, + Map> snapshots) { this.player = player; this.updates = updates; this.snapshots = snapshots; @@ -156,6 +158,22 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask { return coordinates; } + /** + * Checks if a region update is required. + * + * @return {@code true} if a Region update is required, {@code false} if not. + */ + private boolean isRegionUpdateRequired() { + Position current = player.getPosition(); + Position last = player.getLastKnownRegion(); + + int deltaX = current.getLocalX(last); + int deltaY = current.getLocalY(last); + + return deltaX <= Position.MAX_DISTANCE || deltaX >= VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1 + || deltaY <= Position.MAX_DISTANCE || deltaY >= VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1; + } + /** * Gets the {@link List} of {@link GroupedRegionUpdateMessage}s. * @@ -181,31 +199,13 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask { player.send(new ClearRegionMessage(position, coordinates)); } - Optional message = toUpdateMessage(local, player.getLastKnownRegion(), coordinates, repository); - if (message.isPresent()) { - messages.add(message.get()); - } + toUpdateMessage(local, player.getLastKnownRegion(), coordinates, repository).ifPresent(messages::add); } } messages.forEach(player::send); } - /** - * Checks if a region update is required. - * - * @return {@code true} if a Region update is required, {@code false} if not. - */ - private boolean isRegionUpdateRequired() { - Position current = player.getPosition(); - Position last = player.getLastKnownRegion(); - - int deltaX = current.getLocalX(last); - int deltaY = current.getLocalY(last); - - return deltaX <= Position.MAX_DISTANCE || deltaX >= VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1 || deltaY <= Position.MAX_DISTANCE || deltaY >= VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1; - } - /** * Creates a {@link GroupedRegionUpdateMessage} using the specified {@link RegionUpdateMode}, returning * {@link Optional#empty()} if no update message is required. @@ -216,7 +216,8 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask { * @param repository The {@link RegionRepository} containing the Regions. * @return The Optional containing the GroupedRegionUpdateMessage. */ - private Optional toUpdateMessage(RegionUpdateMode mode, Position lastKnownRegion, RegionCoordinates coordinates, RegionRepository repository) { + private Optional toUpdateMessage(RegionUpdateMode mode, Position lastKnownRegion, + RegionCoordinates coordinates, RegionRepository repository) { List messages; /*