Move sector-related items, correct a bug in MobRepository and NpcActionVerificationHandler.

This commit is contained in:
Major-
2014-06-27 13:05:04 +01:00
parent 464db2cc27
commit 6612a8fc14
7 changed files with 400 additions and 25 deletions
@@ -13,21 +13,20 @@ import org.apollo.game.model.WorldConstants;
*
* @author Stuart
*/
public class NpcActionVerificationHandler extends EventHandler<NpcActionEvent> {
public final class NpcActionVerificationHandler extends EventHandler<NpcActionEvent> {
@Override
public void handle(EventHandlerContext ctx, Player player, NpcActionEvent event) {
if(event.getIndex() < 0 || event.getIndex() > WorldConstants.MAXIMUM_NPCS) {
ctx.breakHandlerChain();
return;
}
@Override
public void handle(EventHandlerContext ctx, Player player, NpcActionEvent event) {
if (event.getIndex() < 0 || event.getIndex() >= WorldConstants.MAXIMUM_NPCS) {
ctx.breakHandlerChain();
return;
}
Npc npc = (Npc)World.getWorld().getNpcRepository().get(event.getIndex());
Npc npc = World.getWorld().getNpcRepository().get(event.getIndex());
if(npc == null || !player.getPosition().isWithinDistance(npc.getPosition(), 15)) {
ctx.breakHandlerChain();
return;
}
}
if (npc == null || !player.getPosition().isWithinDistance(npc.getPosition(), 15)) {
ctx.breakHandlerChain();
}
}
}
+160
View File
@@ -0,0 +1,160 @@
package org.apollo.game.model.area;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apollo.game.model.Entity;
import org.apollo.game.model.Entity.EntityType;
import org.apollo.game.model.Position;
/**
* Represents an 8x8 area of the map.
*
* @author Major
*/
public final class Sector {
/**
* The width and height of a sector, in tiles.
*/
public static final int SECTOR_SIZE = 8;
/**
* The sector coordinates of this sector.
*/
private final SectorCoordinates coordinates;
/**
* A map of positions to entities in that position.
*/
private final Map<Position, List<Entity>> entities = new HashMap<>();
/**
* A list of listeners registered to this sector.
*/
private final List<SectorListener> listeners = new ArrayList<>();
/**
* Creates a new sector.
*
* @param x The x coordinate of the sector.
* @param y The y coordinate of the sector.
*/
public Sector(int x, int y) {
this(new SectorCoordinates(x, y));
}
/**
* Creates a new sector with the specified {@link SectorCoordinates}.
*
* @param coordinates The coordinates.
*/
public Sector(SectorCoordinates coordinates) {
this.coordinates = coordinates;
}
/**
* Adds a {@link Entity} from to sector. Note that this does not spawn the entity, or do any other action other than
* register it to this sector.
*
* @param entity The entity.
* @return {@code true} if the entity was added successfully, otherwise {@code false}.
*/
public boolean addEntity(Entity entity) {
Position position = entity.getPosition();
List<Entity> entities = this.entities.get(position);
if (entities == null) {
entities = new ArrayList<>();
}
if (entities.add(entity)) {
this.entities.put(position, entities);
notifyListeners(entity);
return true;
}
return false;
}
/**
* Checks if this sector contains the specified entity.
*
* @param entity The entity.
* @return {@code true} if this sector contains the entity, otherwise {@code false}.
*/
public boolean contains(Entity entity) {
List<Entity> entities = this.entities.get(entity.getPosition());
return entities.contains(entity);
}
/**
* Gets this sector's {@link SectorCoordinates}.
*
* @return The sector coordinates.
*/
public SectorCoordinates getCoordinates() {
return coordinates;
}
/**
* Gets a copy of the {@link List} of {@link Entity}s.
*
* @param position The position containing the entities.
* @return The list.
*/
public List<Entity> getEntities(Position position) {
return new ArrayList<>(entities.get(position));
}
/**
* Gets a copy of the {@link List} of {@link Entity}s with the specified {@link EntityType}.
*
* @param position The {@link Position} containing the entities.
* @param type The {@link EntityType}.
* @return The list of entities.
*/
@SuppressWarnings("unchecked")
public <T extends Entity> List<T> getEntities(Position position, EntityType type) {
List<Entity> entities = getEntities(position);
List<T> filtered = new ArrayList<>();
for (Entity entity : entities) {
if (entity.getEntityType() == type) {
filtered.add((T) entity);
}
}
return filtered;
}
/**
* Notifies the listeners registered to this sector that an update has occurred.
*
* @param entity The entity that was updated.
*/
public void notifyListeners(Entity entity) {
for (SectorListener listener : listeners) {
listener.execute(this, entity);
}
}
/**
* Removes a {@link Entity} from this sector.
*
* @param entity The entity.
* @return {@code true} if the entity was removed, otherwise {@code false}.
*/
public boolean removeEntity(Entity entity) {
List<Entity> entities = this.entities.get(entity.getPosition());
if (entities == null) {
this.entities.put(entity.getPosition(), new ArrayList<Entity>());
return false;
}
if (entities.remove(entity)) {
notifyListeners(entity);
return true;
}
return false;
}
}
@@ -0,0 +1,79 @@
package org.apollo.game.model.area;
import org.apollo.game.model.Position;
/**
* An immutable class representing the coordinates of a sector, where the coordinates ({@code x, y}) are the top-left of
* the sector.
*
* @author Graham
*/
public final class SectorCoordinates {
/**
* Gets a pair of sector coordinates from a {@link Position}.
*
* @param position The position.
* @return The sector coordinates.
*/
public static SectorCoordinates fromPosition(Position position) {
return new SectorCoordinates(position.getTopLeftSectorX(), position.getTopLeftSectorY());
}
/**
* The x coordinate of this sector.
*/
private final int x;
/**
* The y coordinate of this sector.
*/
private final int y;
/**
* Creates the sector coordinates.
*
* @param x The x coordinate.
* @param y The y coordinate.
*/
public SectorCoordinates(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object obj) {
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final SectorCoordinates other = (SectorCoordinates) obj;
if (x != other.x || y != other.y) {
return false;
}
return true;
}
/**
* Gets the x coordinate (equivalent to the {@link Position#getTopLeftSectorX()} of a position within this sector).
*
* @return The x coordinate.
*/
public int getX() {
return x;
}
/**
* Gets the y coordinate (equivalent to the {@link Position#getTopLeftSectorY()} of a position within this sector).
*
* @return The y coordinate.
*/
public int getY() {
return y;
}
@Override
public int hashCode() {
return 61 * (427 + x) + y;
}
}
@@ -0,0 +1,20 @@
package org.apollo.game.model.area;
import org.apollo.game.model.Entity;
/**
* A class that should be extended by listeners that execute actions when an entity is added or removed from the sector.
*
* @author Major
*/
public abstract class SectorListener {
/**
* Executes the action for this listener.
*
* @param The sector that was updated.
* @param entity The affected entity.
*/
public abstract void execute(Sector sector, Entity entity);
}
@@ -0,0 +1,111 @@
package org.apollo.game.model.area;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A repository of sectors, backed by a {@link HashMap} of {@link SectorCoordinates} that correspond to their
* appropriate {@link Sector}s.
*
* @author Major
*/
public final class SectorRepository {
/**
* Indicates whether sectors can be removed from this repository.
*/
private final boolean permitRemoval;
/**
* A {@link Map} of {@link SectorCoordinates} that correspond to the appropriate {@link Sector}s..
*/
private final Map<SectorCoordinates, Sector> sectors = new HashMap<>();
/**
* Creates a new sector repository.
*
* @param permitRemoval If removal (of {@link Sector}s) from this repository should be permitted.
*/
public SectorRepository(boolean permitRemoval) {
this.permitRemoval = permitRemoval;
}
/**
* Adds a {@link Sector} to the repository.
*
* @param sector The sector.
* @throws IllegalArgumentException If the provided sector is null.
* @throws UnsupportedOperationException If the coordinates of the provided sector are already mapped (and hence the
* existing sector would be replaced), and removal of sectors is not permitted.
*/
public void add(Sector sector) {
if (sector == null) {
throw new IllegalArgumentException("Sector cannot be null.");
} else if (sectors.containsKey(sector.getCoordinates()) && !permitRemoval) {
throw new UnsupportedOperationException(
"Cannot add a sector with the same coordinates as an existing sector.");
}
sectors.put(sector.getCoordinates(), sector);
}
/**
* Indicates whether the supplied value (i.e. the {@link Sector}) has a mapping.
*
* @param sector The sector.
* @return {@code true} if the value is mapped by a key (i.e. {@link SectorCoordinates}), otherwise {@code false}.
*/
public boolean contains(Sector sector) {
return sectors.containsValue(sector);
}
/**
* Indicates whether the supplied key (i.e. the {@link SectorCoordinates}) has a mapping.
*
* @param coordinates The coordinates.
* @return {@code true} if the key is already mapped to a value (i.e. a {@link Sector}), otherwise {@code false}.
*/
public boolean contains(SectorCoordinates coordinates) {
return sectors.containsKey(coordinates);
}
/**
* Gets a {@link Sector} with the specified {@link SectorCoordinates}. If the sector does not exist (i.e.
* {@link #sectors}{@code .get()} returns {@code null}) then a new sector is created, submitted to the repository,
* and returned.
*
* @param coordinates The coordinates.
* @return The sector.
*/
public Sector get(SectorCoordinates coordinates) {
Sector sector = sectors.get(coordinates);
if (sector == null) {
add(sector = new Sector(coordinates));
}
return sector;
}
/**
* Gets the {@link List} of {@link Sector}s.
*
* @return The list.
*/
public List<Sector> getSectors() {
return new ArrayList<>(sectors.values());
}
/**
* Removes a {@link Sector} from the repository, if permitted.
*
* @param sector The sector to remove.
* @throws UnsupportedOperationException If this method is called on a repository that does not permit removal.
*/
public void remove(Sector sector) {
if (!permitRemoval) {
throw new UnsupportedOperationException("Cannot remove sectors from this repository.");
}
sectors.remove(sector.getCoordinates());
}
}
@@ -0,0 +1,5 @@
/**
* Contains classes which represent in-game sectors - blocks of 8x8 tiles used to store ground items, temporary objects, etc.
* efficiently.
*/
package org.apollo.game.model.area;
+13 -12
View File
@@ -178,19 +178,20 @@ public final class MobRepository<T extends Mob> implements Iterable<T> {
return false;
}
/**
* Gets the mob at the given index
*
* @param index The index of the mob
* @return The mob instance
*/
public Mob get(int index) {
if (index < 0 || index >= mobs.length) {
throw new IndexOutOfBoundsException("Mob index is out of bounds.");
}
/**
* Gets the mob at the given index
*
* @param index The index of the mob
* @return The mob instance
*/
@SuppressWarnings("unchecked")
public T get(int index) {
if (index < 0 || index >= mobs.length) {
throw new IndexOutOfBoundsException("Mob index is out of bounds.");
}
return mobs[index];
}
return (T) mobs[index];
}
/**
* Gets the size of this repository.