diff --git a/src/org/apollo/game/model/area/Sector.java b/src/org/apollo/game/model/area/Sector.java
index a8c140fc..e1c35d46 100644
--- a/src/org/apollo/game/model/area/Sector.java
+++ b/src/org/apollo/game/model/area/Sector.java
@@ -13,7 +13,6 @@ import org.apollo.game.model.entity.Entity;
import org.apollo.game.model.entity.Entity.EntityType;
import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
@@ -23,16 +22,16 @@ import com.google.common.collect.ImmutableSet;
*/
public final class Sector {
- /**
- * The default size of newly-created sets, to reduce memory usage.
- */
- private static final int DEFAULT_SET_SIZE = 2;
-
/**
* The width and length of a sector, in tiles.
*/
public static final int SECTOR_SIZE = 8;
+ /**
+ * The default size of newly-created sets, to reduce memory usage.
+ */
+ private static final int DEFAULT_SET_SIZE = 2;
+
/**
* The sector coordinates of this sector.
*/
@@ -72,6 +71,7 @@ public final class Sector {
* register it to this sector.
*
* @param entity The entity.
+ * @throws IllegalArgumentException If the entity does not belong in this sector.
*/
public void addEntity(Entity entity) {
Position position = entity.getPosition();
@@ -82,17 +82,6 @@ public final class Sector {
notifyListeners(entity, SectorOperation.ADD);
}
- /**
- * Checks that the specified {@link Position} is included in this sector.
- *
- * @param position The position.
- * @throws IllegalArgumentException If the specified position is not included in this sector.
- */
- private void checkPosition(Position position) {
- Preconditions.checkArgument(coordinates.equals(SectorCoordinates.fromPosition(position)),
- "Position is not included in this sector.");
- }
-
/**
* Checks if this sector contains the specified entity.
*
@@ -118,24 +107,24 @@ public final class Sector {
}
/**
- * Gets a shallow copy of the {@link List} of {@link Entity} objects at the specified {@link Position}. The returned
- * type will be {@link ImmutableList}.
+ * Gets a shallow copy of the {@link Set} of {@link Entity} objects at the specified {@link Position}. The returned
+ * type will be immutable.
*
* @param position The position containing the entities.
* @return The list.
*/
- public List getEntities(Position position) {
- return ImmutableList.copyOf(entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE)));
+ public Set getEntities(Position position) {
+ return ImmutableSet.copyOf(entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE)));
}
/**
- * Gets a shallow copy of the {@link List} of {@link Entity}s with the specified {@link EntityType}. The returned
- * list will be an {@link ImmutableList}. Type will be inferred from the call, so ensure that the entity type and
- * the reference correspond, or this method will fail at runtime.
+ * Gets a shallow copy of the {@link Set} of {@link Entity}s with the specified {@link EntityType}. The returned
+ * type will be immutable. Type will be inferred from the call, so ensure that the entity type and the reference
+ * correspond, or this method will fail at runtime.
*
* @param position The {@link Position} containing the entities.
* @param type The {@link EntityType}.
- * @return The list of entities.
+ * @return The set of entities.
*/
public Set getEntities(Position position, EntityType type) {
Set local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE));
@@ -145,6 +134,34 @@ public final class Sector {
return ImmutableSet.copyOf(filtered);
}
+ /**
+ * Moves the {@link Entity} that was in the specified {@code old} {@link Position}, to the current position of the
+ * entity.
+ *
+ * Both the {@code old} and current positions of the entity must belong to this sector.
+ *
+ * @param old The old position of the entity.
+ * @param entity The entity to move.
+ * @throws IllegalArgumentException If either of the positions do not belong to this sector.
+ */
+ public void moveEntity(Position old, Entity entity) {
+ Position position = entity.getPosition();
+ checkPosition(old);
+ checkPosition(position);
+
+ Set local = entities.get(old);
+
+ if (local == null || !local.remove(entity)) {
+ throw new IllegalArgumentException("Entity belongs in this sector but does not exist.");
+ }
+
+ local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE));
+
+ local.add(entity);
+ notifyListeners(entity, SectorOperation.MOVE);
+
+ }
+
/**
* Notifies the {@link SectorListener}s registered to this sector that an update has occurred.
*
@@ -174,4 +191,15 @@ public final class Sector {
notifyListeners(entity, SectorOperation.REMOVE);
}
+ /**
+ * Checks that the specified {@link Position} is included in this sector.
+ *
+ * @param position The position.
+ * @throws IllegalArgumentException If the specified position is not included in this sector.
+ */
+ private void checkPosition(Position position) {
+ Preconditions.checkArgument(coordinates.equals(SectorCoordinates.fromPosition(position)),
+ "Position is not included in this sector.");
+ }
+
}
\ No newline at end of file
diff --git a/src/org/apollo/game/model/area/SectorOperation.java b/src/org/apollo/game/model/area/SectorOperation.java
index 14997350..a0df172d 100644
--- a/src/org/apollo/game/model/area/SectorOperation.java
+++ b/src/org/apollo/game/model/area/SectorOperation.java
@@ -12,6 +12,11 @@ public enum SectorOperation {
*/
ADD,
+ /**
+ * The move operation, when an entity has moved positions, but is still in the same sector.
+ */
+ MOVE,
+
/**
* The remove operation, when an entity has been removed from a sector.
*/
diff --git a/src/org/apollo/game/model/entity/Mob.java b/src/org/apollo/game/model/entity/Mob.java
index ad4c6512..9240dc8e 100644
--- a/src/org/apollo/game/model/entity/Mob.java
+++ b/src/org/apollo/game/model/entity/Mob.java
@@ -419,15 +419,20 @@ public abstract class Mob extends Entity {
* @param position The position.
*/
public final void setPosition(Position position) {
+ Position old = this.position;
SectorRepository repository = World.getWorld().getSectorRepository();
- Sector current = repository.fromPosition(this.position);
+ Sector current = repository.fromPosition(old);
- Sector next = position.inside(current) ? current : repository.fromPosition(position);
+ if (position.inside(current)) {
+ this.position = position;
+ current.moveEntity(old, this);
+ } else {
+ Sector next = repository.fromPosition(position);
+ current.removeEntity(this);
+ this.position = position; // addEntity relies on the position being updated, so do that first.
- current.removeEntity(this);
- this.position = position; // addEntity relies on the position being updated, so do that first.
-
- next.addEntity(this);
+ next.addEntity(this);
+ }
}
/**
diff --git a/src/org/apollo/game/model/entity/Npc.java b/src/org/apollo/game/model/entity/Npc.java
index 478b77a1..66532a96 100644
--- a/src/org/apollo/game/model/entity/Npc.java
+++ b/src/org/apollo/game/model/entity/Npc.java
@@ -13,19 +13,19 @@ import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
/**
- * An {@link Npc} is a {@link Mob} that is not being controlled by a player.
+ * A {@link Mob} that is not controlled by a player.
*
* @author Major
*/
public final class Npc extends Mob {
/**
- * The positions representing the bounds (i.e. walking limits) of this npc.
+ * The positions representing the bounds (i.e. walking limits) of this Npc.
*/
private Position[] boundary;
/**
- * Creates a new npc with the specified id and {@link Position}.
+ * Creates a new Npc with the specified id and {@link Position}.
*
* @param id The id.
* @param position The position.
@@ -35,7 +35,7 @@ public final class Npc extends Mob {
}
/**
- * Creates a new npc with the specified {@link NpcDefinition} and {@link Position}.
+ * Creates a new Npc with the specified {@link NpcDefinition} and {@link Position}.
*
* @param position The position.
* @param definition The definition.
@@ -57,7 +57,7 @@ public final class Npc extends Mob {
}
/**
- * Gets the boundary of this npc.
+ * Gets the boundary of this Npc.
*
* @return The boundary.
*/
@@ -71,7 +71,7 @@ public final class Npc extends Mob {
}
/**
- * Gets the id of this npc.
+ * Gets the id of this Npc.
*
* @return The id.
*/
@@ -87,16 +87,16 @@ public final class Npc extends Mob {
}
/**
- * Indicates whether or not this npc is bound to a specific set of coordinates.
+ * Indicates whether or not this Npc is bound to a specific set of coordinates.
*
- * @return {@code true} if the npc is bound, otherwise {@code false}.
+ * @return {@code true} if the Npc is bound, otherwise {@code false}.
*/
public boolean isBound() {
return boundary == null;
}
/**
- * Sets the boundary of this npc.
+ * Sets the boundary of this Npc.
*
* @param boundary The boundary.
*/
@@ -111,7 +111,7 @@ public final class Npc extends Mob {
}
/**
- * Transforms this npc into the npc with the specified id.
+ * Transforms this Npc into the Npc with the specified id.
*
* @param id The id.
*/
@@ -123,10 +123,10 @@ public final class Npc extends Mob {
}
/**
- * Initialises this npc.
+ * Initialises this Npc.
*/
private void init() {
- // This has to be here instead of in Mob#init because of ordering issues - the player cannot be added to the
+ // This has to be here instead of in Mob#init because of ordering issues - the Npc cannot be added to the
// sector until their credentials have been set, which is only done after the super constructors are called.
Sector sector = World.getWorld().getSectorRepository().get(position.getSectorCoordinates());
sector.addEntity(this);