Remove duplicate sector package, add ObjectActionVerificationHandler, expand NpcActionVerificationHandler, and add a utility method to SectorRepository.

This commit is contained in:
Major-
2014-07-10 00:18:02 +01:00
parent 31ba87262a
commit 465d820890
11 changed files with 115 additions and 388 deletions
@@ -9,7 +9,7 @@ import org.apollo.game.model.entity.Npc;
import org.apollo.game.model.entity.Player;
/**
* An {@link EventHandler} that verifies {@link org.apollo.game.event.impl.NpcActionEvent}
* A verification {@link EventHandler} for the {@link NpcActionEvent}.
*
* @author Stuart
*/
@@ -26,6 +26,13 @@ public final class NpcActionVerificationHandler extends EventHandler<NpcActionEv
if (npc == null || !player.getPosition().isWithinDistance(npc.getPosition(), 15)) {
ctx.breakHandlerChain();
return;
}
// TODO is this right?
if (event.getOption() >= npc.getDefinition().getInteractions().length) {
ctx.breakHandlerChain();
return;
}
}
@@ -0,0 +1,68 @@
package org.apollo.game.event.handler.impl;
import java.util.List;
import org.apollo.game.event.handler.EventHandler;
import org.apollo.game.event.handler.EventHandlerContext;
import org.apollo.game.event.impl.ObjectActionEvent;
import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.area.Sector;
import org.apollo.game.model.def.ObjectDefinition;
import org.apollo.game.model.entity.Entity.EntityType;
import org.apollo.game.model.entity.Player;
import org.apollo.game.model.obj.GameObject;
/**
* A verification {@link EventHandler} for the {@link ObjectActionEvent}.
*
* @author Major
*/
public final class ObjectActionVerificationHandler extends EventHandler<ObjectActionEvent> {
@Override
public void handle(EventHandlerContext ctx, Player player, ObjectActionEvent event) {
int id = event.getId();
if (id < 0 || id >= ObjectDefinition.count()) {
ctx.breakHandlerChain();
return;
}
Position position = event.getPosition();
Sector sector = World.getWorld().getSectorRepository().fromPosition(position);
List<GameObject> objects = sector.getEntities(position, EntityType.GAME_OBJECT);
if (!containsObject(id, objects)) {
ctx.breakHandlerChain();
return;
}
if (!player.getPosition().isWithinDistance(position, 15)) {
ctx.breakHandlerChain();
return;
}
// TODO is this right?
if (event.getOption() >= ObjectDefinition.lookup(id).getMenuActions().length) {
ctx.breakHandlerChain();
return;
}
}
/**
* Indicates whether or not the {@link List} of {@link GameObject}s contains the object with the specified id.
*
* @param id The id of the object.
* @param objects The list of objects.
* @return {@code true} if the list does contain the object with the specified id, otherwise {@code false}.
*/
private boolean containsObject(int id, List<GameObject> objects) {
for (GameObject object : objects) {
if (object.getId() == id) {
return true;
}
}
return false;
}
}
+3 -3
View File
@@ -17,6 +17,9 @@ import org.apollo.fs.decoder.StaticObjectDecoder;
import org.apollo.game.command.CommandDispatcher;
import org.apollo.game.login.LoginDispatcher;
import org.apollo.game.login.LogoutDispatcher;
import org.apollo.game.model.area.Sector;
import org.apollo.game.model.area.SectorCoordinates;
import org.apollo.game.model.area.SectorRepository;
import org.apollo.game.model.def.EquipmentDefinition;
import org.apollo.game.model.def.ItemDefinition;
import org.apollo.game.model.def.NpcDefinition;
@@ -25,9 +28,6 @@ import org.apollo.game.model.entity.Entity;
import org.apollo.game.model.entity.Npc;
import org.apollo.game.model.entity.Player;
import org.apollo.game.model.obj.GameObject;
import org.apollo.game.model.sector.Sector;
import org.apollo.game.model.sector.SectorCoordinates;
import org.apollo.game.model.sector.SectorRepository;
import org.apollo.game.scheduling.ScheduledTask;
import org.apollo.game.scheduling.Scheduler;
import org.apollo.io.EquipmentDefinitionParser;
@@ -5,6 +5,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apollo.game.model.Position;
/**
* A repository of sectors, backed by a {@link HashMap} of {@link SectorCoordinates} that correspond to their
* appropriate {@link Sector}s.
@@ -71,9 +73,19 @@ public final class SectorRepository {
}
/**
* 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.
* Gets the {@link Sector} that contains the specified {@link Position}. If the sector does not exist in this
* repository then a new sector is created, submitted to the repository, and returned.
*
* @param position The position.
* @return The sector.
*/
public Sector fromPosition(Position position) {
return get(SectorCoordinates.fromPosition(position));
}
/**
* Gets a {@link Sector} with the specified {@link SectorCoordinates}. If the sector does not exist in this
* repository then a new sector is created, submitted to the repository, and returned.
*
* @param coordinates The coordinates.
* @return The sector.
@@ -56,6 +56,15 @@ public final class GameObject extends Entity {
return EntityType.GAME_OBJECT;
}
/**
* Gets the id of this object.
*
* @return The id.
*/
public int getId() {
return definition.getId();
}
/**
* Gets the object's rotation.
*
@@ -1,160 +0,0 @@
package org.apollo.game.model.sector;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apollo.game.model.entity.Entity;
import org.apollo.game.model.entity.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<>());
return false;
}
if (entities.remove(entity)) {
notifyListeners(entity);
return true;
}
return false;
}
}
@@ -1,79 +0,0 @@
package org.apollo.game.model.sector;
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;
}
}
@@ -1,20 +0,0 @@
package org.apollo.game.model.sector;
import org.apollo.game.model.entity.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);
}
@@ -1,111 +0,0 @@
package org.apollo.game.model.sector;
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());
}
}
@@ -1,5 +0,0 @@
/**
* 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.sector;