From c7d1a5a7329206648181754d4ea678fa0d175c73 Mon Sep 17 00:00:00 2001 From: atomicint Date: Fri, 22 Jan 2016 01:46:40 -0500 Subject: [PATCH 1/2] Fixes issue #84 --- .../org/apollo/game/model/entity/Player.java | 59 ++++++++++++++++++- .../inv/AppearanceInventoryListener.java | 2 +- .../skill/SynchronizationSkillListener.java | 2 +- .../sync/task/PlayerSynchronizationTask.java | 30 +++++++++- 4 files changed, 88 insertions(+), 5 deletions(-) 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 86e8a549..abe02680 100644 --- a/game/src/main/org/apollo/game/model/entity/Player.java +++ b/game/src/main/org/apollo/game/model/entity/Player.java @@ -6,6 +6,7 @@ import java.util.Deque; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import org.apollo.game.message.impl.ConfigMessage; import org.apollo.game.message.impl.IdAssignmentMessage; @@ -19,6 +20,7 @@ import org.apollo.game.message.impl.UpdateRunEnergyMessage; import org.apollo.game.model.Appearance; import org.apollo.game.model.Position; import org.apollo.game.model.World; +import org.apollo.game.model.WorldConstants; import org.apollo.game.model.entity.attr.Attribute; import org.apollo.game.model.entity.attr.AttributeDefinition; import org.apollo.game.model.entity.attr.AttributeMap; @@ -47,6 +49,7 @@ import org.apollo.game.model.skill.LevelUpSkillListener; import org.apollo.game.model.skill.SynchronizationSkillListener; import org.apollo.game.session.GameSession; import org.apollo.game.sync.block.SynchronizationBlock; +import org.apollo.game.sync.block.SynchronizationBlockSet; import org.apollo.net.message.Message; import org.apollo.util.CollectionUtil; import org.apollo.util.Point; @@ -71,6 +74,15 @@ public final class Player extends Mob { AttributeMap.define("run_energy", AttributeDefinition.forInt(100, AttributePersistence.PERSISTENT)); } + /** + * The current amount of appearance tickets. + */ + private static final AtomicInteger appearanceTicketCounter = new AtomicInteger(0); + + /** + * This appearance tickets for this Player. + */ + private final int[] appearanceTickets = new int[WorldConstants.MAXIMUM_PLAYERS]; /** * This player's bank. @@ -207,6 +219,11 @@ public final class Player extends Mob { */ private int worldId = 1; + /** + * This Players appearance ticket. + */ + private int appearanceTicket = nextAppearanceTicket(); + /** * Creates the Player. * @@ -641,6 +658,36 @@ public final class Player extends Mob { localObjects.forEach(object -> object.removeFrom(this)); } + /** + * Generates the next appearance ticket. + * + * @return The next available appearance ticket. + */ + private static int nextAppearanceTicket() { + if (appearanceTicketCounter.incrementAndGet() == 0) { + appearanceTicketCounter.set(1); + } + return appearanceTicketCounter.get(); + } + + /** + * Gets all of this Players appearance tickets. + * + * @return All of this Players appearance tickets. + */ + public int[] getAppearanceTickets() { + return appearanceTickets; + } + + /** + * Gets this Players appearance ticket. + * + * @return This Players appearance ticket. + */ + public int getAppearanceTicket() { + return appearanceTicket; + } + /** * Indicates whether the message filter is enabled. * @@ -735,7 +782,7 @@ public final class Player extends Mob { * Sends the initial messages. */ public void sendInitialMessages() { - blockSet.add(SynchronizationBlock.createAppearanceBlock(this)); + updateAppearance(); send(new IdAssignmentMessage(index, members)); sendMessage("Welcome to RuneScape."); @@ -813,7 +860,7 @@ public final class Player extends Mob { */ public void setAppearance(Appearance appearance) { this.appearance = appearance; - blockSet.add(SynchronizationBlock.createAppearanceBlock(this)); + updateAppearance(); } /** @@ -1025,4 +1072,12 @@ public final class Player extends Mob { skillSet.addListener(new LevelUpSkillListener(this)); } + /** + * Updates the appearance for this Player. + */ + public void updateAppearance() { + appearanceTicket = nextAppearanceTicket(); + blockSet.add(SynchronizationBlock.createAppearanceBlock(this)); + } + } \ No newline at end of file diff --git a/game/src/main/org/apollo/game/model/inv/AppearanceInventoryListener.java b/game/src/main/org/apollo/game/model/inv/AppearanceInventoryListener.java index a977ec6f..a59a883a 100644 --- a/game/src/main/org/apollo/game/model/inv/AppearanceInventoryListener.java +++ b/game/src/main/org/apollo/game/model/inv/AppearanceInventoryListener.java @@ -39,7 +39,7 @@ public final class AppearanceInventoryListener extends InventoryAdapter { * Updates the player's appearance. */ private void update() { - player.getBlockSet().add(SynchronizationBlock.createAppearanceBlock(player)); + player.updateAppearance(); } } \ No newline at end of file diff --git a/game/src/main/org/apollo/game/model/skill/SynchronizationSkillListener.java b/game/src/main/org/apollo/game/model/skill/SynchronizationSkillListener.java index 8f599f7a..f6555ec2 100644 --- a/game/src/main/org/apollo/game/model/skill/SynchronizationSkillListener.java +++ b/game/src/main/org/apollo/game/model/skill/SynchronizationSkillListener.java @@ -32,7 +32,7 @@ public final class SynchronizationSkillListener extends SkillAdapter { @Override public void levelledUp(SkillSet set, int id, Skill skill) { if (Skill.isCombatSkill(id)) { - player.getBlockSet().add(SynchronizationBlock.createAppearanceBlock(player)); + player.updateAppearance(); } } 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 06290056..456d4d7f 100644 --- a/game/src/main/org/apollo/game/sync/task/PlayerSynchronizationTask.java +++ b/game/src/main/org/apollo/game/sync/task/PlayerSynchronizationTask.java @@ -53,6 +53,7 @@ public final class PlayerSynchronizationTask extends SynchronizationTask { public void run() { Position lastKnownRegion = player.getLastKnownRegion(); boolean regionChanged = player.hasRegionChanged(); + int[] appearanceTickets = player.getAppearanceTickets(); SynchronizationBlockSet blockSet = player.getBlockSet(); @@ -101,7 +102,7 @@ public final class PlayerSynchronizationTask extends SynchronizationTask { added++; blockSet = other.getBlockSet(); - if (!blockSet.contains(AppearanceBlock.class)) { // TODO check if client has cached appearance + if (!blockSet.contains(AppearanceBlock.class) && !hasCachedAppearance(appearanceTickets, other)) { blockSet = blockSet.clone(); blockSet.add(SynchronizationBlock.createAppearanceBlock(other)); } @@ -115,6 +116,33 @@ public final class PlayerSynchronizationTask extends SynchronizationTask { player.send(message); } + /** + * Tests whether or not the specified Player has a cached appearance within + * the specified appearance ticket array. + * + * @param tickets The appearance tickets. + * @param player The Player. + * @return {@code true} if the specified Player has a cached appearance + * otherwise {@code false}. + */ + private boolean hasCachedAppearance(int[] tickets, Player player) { + + // If the Player is not active they cannot have a cached appearance + if (!player.isActive()) { + return false; + } + + int index = player.getIndex() - 1; + int ticket = player.getAppearanceTicket(); + + if (tickets[index] == ticket) { + return true; + } + + tickets[index] = ticket; + return false; + } + /** * Returns whether or not the specified {@link Player} should be removed. * From cebdb811cb7fa8711f342ec68293f41721a3d1be Mon Sep 17 00:00:00 2001 From: atomicint Date: Fri, 22 Jan 2016 15:51:52 -0500 Subject: [PATCH 2/2] Clean up hasCachedAppearance - Remove useless inline comment - Remove blank line after param declaration - Only call getIndex() once --- .../sync/task/PlayerSynchronizationTask.java | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) 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 456d4d7f..be7f30d1 100644 --- a/game/src/main/org/apollo/game/sync/task/PlayerSynchronizationTask.java +++ b/game/src/main/org/apollo/game/sync/task/PlayerSynchronizationTask.java @@ -102,12 +102,15 @@ public final class PlayerSynchronizationTask extends SynchronizationTask { added++; blockSet = other.getBlockSet(); - if (!blockSet.contains(AppearanceBlock.class) && !hasCachedAppearance(appearanceTickets, other)) { + + int index = other.getIndex(); + + if (!blockSet.contains(AppearanceBlock.class) && !hasCachedAppearance(appearanceTickets, index - 1, other.getAppearanceTicket())) { blockSet = blockSet.clone(); blockSet.add(SynchronizationBlock.createAppearanceBlock(other)); } - segments.add(new AddPlayerSegment(blockSet, other.getIndex(), local)); + segments.add(new AddPlayerSegment(blockSet, index, local)); } } @@ -120,27 +123,19 @@ public final class PlayerSynchronizationTask extends SynchronizationTask { * Tests whether or not the specified Player has a cached appearance within * the specified appearance ticket array. * - * @param tickets The appearance tickets. - * @param player The Player. + * @param appearanceTickets The appearance tickets. + * @param index The index of the Player. + * @param appearanceTicket The current appearance ticket for the Player. * @return {@code true} if the specified Player has a cached appearance * otherwise {@code false}. */ - private boolean hasCachedAppearance(int[] tickets, Player player) { - - // If the Player is not active they cannot have a cached appearance - if (!player.isActive()) { + private boolean hasCachedAppearance(int[] appearanceTickets, int index, int appearanceTicket) { + if (appearanceTickets[index] != appearanceTicket) { + appearanceTickets[index] = appearanceTicket; return false; } - int index = player.getIndex() - 1; - int ticket = player.getAppearanceTicket(); - - if (tickets[index] == ticket) { - return true; - } - - tickets[index] = ticket; - return false; + return true; } /**