From effcca0c3b5469406e40032b226568eb13716e35 Mon Sep 17 00:00:00 2001 From: Major- Date: Sat, 1 Aug 2015 14:18:10 +0100 Subject: [PATCH] Add GroupableEntity. --- .../org/apollo/game/model/area/Region.java | 26 ++++++++++--------- .../model/area/update/GroupableEntity.java | 24 +++++++++++++++++ .../org/apollo/game/model/entity/Entity.java | 12 --------- .../apollo/game/model/entity/GroundItem.java | 3 ++- .../org/apollo/game/model/entity/Mob.java | 22 ++++++---------- .../game/model/entity/WalkingQueue.java | 16 ++++++------ .../model/entity/obj/DynamicGameObject.java | 20 +++++++------- .../game/model/entity/obj/GameObject.java | 6 +++-- .../GroupedRegionUpdateMessageEncoder.java | 6 ++--- .../game/scheduling/impl/NpcMovementTask.java | 2 +- 10 files changed, 74 insertions(+), 63 deletions(-) create mode 100644 game/src/main/org/apollo/game/model/area/update/GroupableEntity.java diff --git a/game/src/main/org/apollo/game/model/area/Region.java b/game/src/main/org/apollo/game/model/area/Region.java index 4e1f8eda..7c1f1577 100644 --- a/game/src/main/org/apollo/game/model/area/Region.java +++ b/game/src/main/org/apollo/game/model/area/Region.java @@ -14,6 +14,7 @@ import org.apollo.game.message.impl.RegionUpdateMessage; import org.apollo.game.model.Direction; import org.apollo.game.model.Position; import org.apollo.game.model.area.collision.CollisionMatrix; +import org.apollo.game.model.area.update.GroupableEntity; import org.apollo.game.model.area.update.UpdateOperation; import org.apollo.game.model.entity.Entity; import org.apollo.game.model.entity.EntityType; @@ -40,8 +41,8 @@ public final class Region { @Override public void execute(Region region, Entity entity, EntityUpdateType update) { EntityType type = entity.getEntityType(); - if (type != EntityType.PLAYER && type != EntityType.NPC) { - region.record(entity, update); + if (!type.isMob()) { + region.record((Entity & GroupableEntity) entity, update); } } @@ -53,9 +54,9 @@ public final class Region { public static final int SIZE = 8; /** - * The default size of newly-created sets, to reduce memory usage. + * The default size of newly-created Lists, to reduce memory usage. */ - private static final int DEFAULT_SET_SIZE = 2; + private static final int DEFAULT_LIST_SIZE = 2; /** * The RegionCoordinates of this Region. @@ -108,7 +109,7 @@ public final class Region { for (int height = 0; height < Position.HEIGHT_LEVELS; height++) { snapshots.add(new HashMap<>()); - updates.add(new ArrayList<>(DEFAULT_SET_SIZE)); + updates.add(new ArrayList<>(DEFAULT_LIST_SIZE)); } } @@ -124,7 +125,7 @@ public final class Region { Position position = entity.getPosition(); checkPosition(position); - Set local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE)); + Set local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_LIST_SIZE)); local.add(entity); if (notify) { @@ -212,7 +213,7 @@ public final class Region { */ public CollisionMatrix getMatrix(int height) { Preconditions.checkElementIndex(height, matrices.length, "Matrix height level must be [0, " + matrices.length - + ")."); + + "), received " + height + "."); return matrices[height]; } @@ -307,22 +308,23 @@ public final class Region { } /** - * Records the specified {@link Entity} as being updated this pulse. + * Records the specified {@link GroupableEntity} as being updated this pulse. * - * @param entity The Entity. + * @param entity The GroupableEntity. * @param type The {@link EntityUpdateType}. * @throws UnsupportedOperationException If the specified Entity cannot be operated on in this manner. */ - private void record(Entity entity, EntityUpdateType type) { + private void record(T entity, EntityUpdateType type) { RegionUpdateMessage message = entity.toUpdateOperation(this, type).toMessage(); int height = entity.getPosition().getHeight(); + Map snapshot = snapshots.get(height); updates.get(height).add(message); - snapshots.get(height).remove(entity); + snapshot.remove(entity); if ((entity.getEntityType() == EntityType.STATIC_OBJECT && type == EntityUpdateType.REMOVE) || (entity.getEntityType() != EntityType.STATIC_OBJECT && type == EntityUpdateType.ADD)) { - snapshots.get(height).put(entity, message); + snapshot.put(entity, message); } } diff --git a/game/src/main/org/apollo/game/model/area/update/GroupableEntity.java b/game/src/main/org/apollo/game/model/area/update/GroupableEntity.java new file mode 100644 index 00000000..a90ddad5 --- /dev/null +++ b/game/src/main/org/apollo/game/model/area/update/GroupableEntity.java @@ -0,0 +1,24 @@ +package org.apollo.game.model.area.update; + +import org.apollo.game.model.area.EntityUpdateType; +import org.apollo.game.model.area.Region; + +/** + * An entity that can be sent as part of a grouped region update message. + *

+ * Only {@link org.apollo.game.model.entity.Entity} extensions may implement this interface. + * + * @author Major + */ +public interface GroupableEntity { + + /** + * Gets this Entity, as an {@link UpdateOperation} of a {@link Region}. + * + * @param region The Region. + * @param type The EntityUpdateType. + * @return The UpdateOperation. + */ + public UpdateOperation toUpdateOperation(Region region, EntityUpdateType type); + +} \ No newline at end of file diff --git a/game/src/main/org/apollo/game/model/entity/Entity.java b/game/src/main/org/apollo/game/model/entity/Entity.java index 48c0fdbf..97e35349 100644 --- a/game/src/main/org/apollo/game/model/entity/Entity.java +++ b/game/src/main/org/apollo/game/model/entity/Entity.java @@ -2,9 +2,6 @@ package org.apollo.game.model.entity; import org.apollo.game.model.Position; import org.apollo.game.model.World; -import org.apollo.game.model.area.EntityUpdateType; -import org.apollo.game.model.area.Region; -import org.apollo.game.model.area.update.UpdateOperation; /** * Represents an in-game entity, such as a mob, object, projectile, etc. @@ -65,13 +62,4 @@ public abstract class Entity { @Override public abstract int hashCode(); - /** - * Gets this Entity, as an {@link UpdateOperation} of a {@link Region}. - * - * @param region The Region. - * @param type The EntityUpdateType. - * @return The UpdateOperation. - */ - public abstract UpdateOperation toUpdateOperation(Region region, EntityUpdateType type); - } \ No newline at end of file diff --git a/game/src/main/org/apollo/game/model/entity/GroundItem.java b/game/src/main/org/apollo/game/model/entity/GroundItem.java index b37c7707..a81c612c 100644 --- a/game/src/main/org/apollo/game/model/entity/GroundItem.java +++ b/game/src/main/org/apollo/game/model/entity/GroundItem.java @@ -5,6 +5,7 @@ import org.apollo.game.model.Position; import org.apollo.game.model.World; import org.apollo.game.model.area.EntityUpdateType; import org.apollo.game.model.area.Region; +import org.apollo.game.model.area.update.GroupableEntity; import org.apollo.game.model.area.update.ItemUpdateOperation; import org.apollo.game.model.area.update.UpdateOperation; @@ -13,7 +14,7 @@ import org.apollo.game.model.area.update.UpdateOperation; * * @author Major */ -public final class GroundItem extends Entity { +public final class GroundItem extends Entity implements GroupableEntity { /** * Creates a new GroundItem. diff --git a/game/src/main/org/apollo/game/model/entity/Mob.java b/game/src/main/org/apollo/game/model/entity/Mob.java index cd7cbcde..1ee4e2c9 100644 --- a/game/src/main/org/apollo/game/model/entity/Mob.java +++ b/game/src/main/org/apollo/game/model/entity/Mob.java @@ -12,10 +12,8 @@ import org.apollo.game.model.Direction; import org.apollo.game.model.Graphic; import org.apollo.game.model.Position; import org.apollo.game.model.World; -import org.apollo.game.model.area.EntityUpdateType; import org.apollo.game.model.area.Region; import org.apollo.game.model.area.RegionRepository; -import org.apollo.game.model.area.update.UpdateOperation; import org.apollo.game.model.entity.attr.Attribute; import org.apollo.game.model.entity.attr.AttributeMap; import org.apollo.game.model.event.impl.MobPositionUpdateEvent; @@ -53,7 +51,8 @@ public abstract class Mob extends Entity { /** * This mob's equipment. */ - protected final Inventory equipment = new Inventory(InventoryConstants.EQUIPMENT_CAPACITY, StackMode.STACK_ALWAYS); + protected final Inventory equipment = new Inventory(InventoryConstants.EQUIPMENT_CAPACITY, + StackMode.STACK_ALWAYS); /** * The index of this mob. @@ -198,8 +197,8 @@ public abstract class Mob extends Entity { */ public final Direction[] getDirections() { if (firstDirection != Direction.NONE) { - return secondDirection == Direction.NONE ? new Direction[] { firstDirection } : new Direction[] { - firstDirection, secondDirection }; + return secondDirection == Direction.NONE ? new Direction[] { firstDirection } + : new Direction[] { firstDirection, secondDirection }; } return Direction.EMPTY_DIRECTION_ARRAY; @@ -430,14 +429,14 @@ public abstract class Mob extends Entity { /** * Sets the {@link Position} of this mob. *

- * This method may be intercepted using a {@link MobPositionUpdateEvent}, which can be terminated like any other. - * Plugins that intercept this Event must be cautious, because movement will not be possible (even - * through mechanisms such as teleporting) if the Event is terminated. + * This method may be intercepted using a {@link MobPositionUpdateEvent}, which can be terminated like any + * other. Plugins that intercept this Event must be cautious, because movement will not be + * possible (even through mechanisms such as teleporting) if the Event is terminated. * * @param position The Position. */ public final void setPosition(Position position) { - if (world.submit(new MobPositionUpdateEvent(this, position))) { + if (!position.equals(this.position) && world.submit(new MobPositionUpdateEvent(this, position))) { Position old = this.position; RegionRepository repository = world.getRegionRepository(); Region current = repository.fromPosition(old), next = repository.fromPosition(position); @@ -524,11 +523,6 @@ public abstract class Mob extends Entity { stopAction(); } - @Override - public final UpdateOperation toUpdateOperation(Region region, EntityUpdateType operation) { - throw new UnsupportedOperationException("Mobs cannot be recorded as a Region update."); - } - /** * Turns this mob to face the specified {@link Position}. * 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 8888598a..cf3b7e29 100644 --- a/game/src/main/org/apollo/game/model/entity/WalkingQueue.java +++ b/game/src/main/org/apollo/game/model/entity/WalkingQueue.java @@ -46,7 +46,8 @@ public final class WalkingQueue { @Override public String toString() { - return MoreObjects.toStringHelper(this).add("direction", direction).add("position", position).toString(); + return MoreObjects.toStringHelper(this).add("direction", direction).add("position", position) + .toString(); } } @@ -86,8 +87,8 @@ public final class WalkingQueue { } /** - * Adds the first step to the queue, attempting to connect the server and client position by looking at the previous - * queue. + * Adds the first step to the queue, attempting to connect the server and client position by looking at the + * previous queue. * * @param clientPosition The first step. * @return {@code true} if the queues could be connected correctly, {@code false} if not. @@ -202,11 +203,7 @@ public final class WalkingQueue { * @return The last point. */ private Point getLast() { - Point last = points.peekLast(); - if (last == null) { - return new Point(mob.getPosition(), Direction.NONE); - } - return last; + return points.isEmpty() ? new Point(mob.getPosition(), Direction.NONE) : points.peekLast(); } /** @@ -223,13 +220,16 @@ public final class WalkingQueue { if (runningQueue /* and enough energy */) { next = points.poll(); + if (next != null) { second = next.direction; position = next.position; } } + mob.setPosition(position); } + mob.setDirections(first, second); } diff --git a/game/src/main/org/apollo/game/model/entity/obj/DynamicGameObject.java b/game/src/main/org/apollo/game/model/entity/obj/DynamicGameObject.java index befda12b..91a071d0 100644 --- a/game/src/main/org/apollo/game/model/entity/obj/DynamicGameObject.java +++ b/game/src/main/org/apollo/game/model/entity/obj/DynamicGameObject.java @@ -39,7 +39,8 @@ public final class DynamicGameObject extends GameObject { * @param orientation The orientation of the DynamicGameObject. * @return The DynamicGameObject. */ - public static DynamicGameObject createPublic(World world, int id, Position position, int type, int orientation) { + public static DynamicGameObject createPublic(World world, int id, Position position, int type, + int orientation) { return new DynamicGameObject(world, id, position, type, orientation, true); } @@ -49,9 +50,9 @@ public final class DynamicGameObject extends GameObject { private final boolean alwaysVisible; /** - * The Set of Players that can view this DynamicGameObject. + * The Set of Player usernames that can view this DynamicGameObject. */ - private final Set players = new HashSet<>(); + private final Set players = new HashSet<>(); // TODO more appropriate type? /** * Creates the DynamicGameObject. @@ -63,7 +64,8 @@ public final class DynamicGameObject extends GameObject { * @param orientation The orientation of the DynamicGameObject. * @param alwaysVisible The flag indicates whether or not this DynamicGameObject is visible to every player. */ - private DynamicGameObject(World world, int id, Position position, int type, int orientation, boolean alwaysVisible) { + private DynamicGameObject(World world, int id, Position position, int type, int orientation, + boolean alwaysVisible) { super(world, id, position, type, orientation); this.alwaysVisible = alwaysVisible; } @@ -72,10 +74,10 @@ public final class DynamicGameObject extends GameObject { * Adds this DynamicGameObject to the view of the specified {@link Player}. * * @param player The Player. - * @return {@code true} if this GameObject was not already visible to the specified Player. + * @return {@code true} if this DynamicGameObject was not already visible to the specified Player. */ public boolean addTo(Player player) { - return players.add(player); + return players.add(player.getUsername()); } @Override @@ -87,15 +89,15 @@ public final class DynamicGameObject extends GameObject { * Removes this DynamicGameObject from the view of the specified {@link Player}. * * @param player The Player. - * @return {@code true} if this GameObject was visible to the specified Player. + * @return {@code true} if this DynamicGameObject was visible to the specified Player. */ public boolean removeFrom(Player player) { - return players.remove(player); + return players.remove(player.getUsername()); } @Override public boolean viewableBy(Player player, World world) { - return alwaysVisible || players.contains(player); + return alwaysVisible || players.contains(player.getUsername()); } } \ No newline at end of file diff --git a/game/src/main/org/apollo/game/model/entity/obj/GameObject.java b/game/src/main/org/apollo/game/model/entity/obj/GameObject.java index 0dcf5519..cdb0f749 100644 --- a/game/src/main/org/apollo/game/model/entity/obj/GameObject.java +++ b/game/src/main/org/apollo/game/model/entity/obj/GameObject.java @@ -5,6 +5,7 @@ import org.apollo.game.model.Position; import org.apollo.game.model.World; import org.apollo.game.model.area.EntityUpdateType; import org.apollo.game.model.area.Region; +import org.apollo.game.model.area.update.GroupableEntity; import org.apollo.game.model.area.update.ObjectUpdateOperation; import org.apollo.game.model.entity.Entity; import org.apollo.game.model.entity.Player; @@ -17,7 +18,7 @@ import com.google.common.base.MoreObjects; * @author Chris Fletcher * @author Major */ -public abstract class GameObject extends Entity { +public abstract class GameObject extends Entity implements GroupableEntity { /** * The packed value that stores this object's id, type, and orientation. @@ -91,7 +92,8 @@ public abstract class GameObject extends Entity { @Override public String toString() { - return MoreObjects.toStringHelper(this).add("id", getId()).add("type", getType()).add("orientation", getOrientation()).toString(); + return MoreObjects.toStringHelper(this).add("id", getId()).add("type", getType()) + .add("orientation", getOrientation()).toString(); } @Override diff --git a/game/src/main/org/apollo/game/release/r317/GroupedRegionUpdateMessageEncoder.java b/game/src/main/org/apollo/game/release/r317/GroupedRegionUpdateMessageEncoder.java index 6e21eae4..aaab4c8c 100644 --- a/game/src/main/org/apollo/game/release/r317/GroupedRegionUpdateMessageEncoder.java +++ b/game/src/main/org/apollo/game/release/r317/GroupedRegionUpdateMessageEncoder.java @@ -26,7 +26,8 @@ public final class GroupedRegionUpdateMessageEncoder extends MessageEncoder encoder = (MessageEncoder) release .getMessageEncoder(update.getClass()); 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 7bcdcf73..4d3abed2 100644 --- a/game/src/main/org/apollo/game/scheduling/impl/NpcMovementTask.java +++ b/game/src/main/org/apollo/game/scheduling/impl/NpcMovementTask.java @@ -94,7 +94,7 @@ public final class NpcMovementTask extends ScheduledTask { Position first = positions.pollFirst(); if (first != null && queue.addFirstStep(first)) { - positions.forEach(npc.getWalkingQueue()::addStep); + positions.forEach(queue::addStep); } npcs.offer(npc);