mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-03 00:38:21 +00:00
Add half-done grouped region frame stuff so Ryley can take a look. This is in master because I'm an idiot.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
java_import 'org.apollo.game.model.Direction'
|
||||
require 'set'
|
||||
|
||||
# Contains door-related constants.
|
||||
module DoorConstants
|
||||
|
||||
# TODO: GameObjectOrientation enumeration in Apollo's core?
|
||||
module Orientation
|
||||
WEST = 0
|
||||
@@ -9,17 +11,18 @@ module DoorConstants
|
||||
SOUTH = 3
|
||||
end
|
||||
|
||||
# The object size of a door.
|
||||
# The size of a door object.
|
||||
DOOR_SIZE = 1
|
||||
|
||||
# Door object ids that have a hinge on the left side.
|
||||
LEFT_SIDE_HINGE_DOOR_IDS = [1516, 1536, 1533]
|
||||
LEFT_HINGE_DOORS = Set.new [ 1516, 1536, 1533 ]
|
||||
|
||||
# Door object ids that have a hinge on the right side.
|
||||
RIGHT_SIDE_HINGE_DOOR_IDS = [1519, 1530, 4465, 4467, 3014, 3017, 3018, 3019]
|
||||
RIGHT_HINGE_DOORS = Set.new [ 1519, 1530, 4465, 4467, 3014, 3017, 3018, 3019 ]
|
||||
|
||||
# A map of orientations that a door will translate to when opened.
|
||||
# The hash of orientations that a door will translate to when opened.
|
||||
ORIENTATIONS = {
|
||||
|
||||
# Orientations for doors that have a hinge on the left side.
|
||||
:left_side_hinge => {
|
||||
Orientation::NORTH => Orientation::WEST,
|
||||
@@ -27,6 +30,7 @@ module DoorConstants
|
||||
Orientation::WEST => Orientation::SOUTH,
|
||||
Orientation::EAST => Orientation::NORTH
|
||||
},
|
||||
|
||||
# Orientations for doors that have a hinge on the right side.
|
||||
:right_side_hinge => {
|
||||
Orientation::NORTH => Orientation::EAST,
|
||||
@@ -35,4 +39,5 @@ module DoorConstants
|
||||
Orientation::EAST => Orientation::SOUTH
|
||||
}
|
||||
}
|
||||
|
||||
end
|
||||
@@ -4,28 +4,30 @@ java_import 'org.apollo.game.action.DistancedAction'
|
||||
class OpenDoorAction < DistancedAction
|
||||
include DoorConstants
|
||||
|
||||
attr_reader :door_object
|
||||
attr_reader :door
|
||||
|
||||
def initialize(mob, door_object)
|
||||
super(0, true, mob, door_object.position, DOOR_SIZE)
|
||||
@door_object = door_object
|
||||
def initialize(mob, door)
|
||||
super(0, true, mob, door.position, DOOR_SIZE)
|
||||
@door = door
|
||||
end
|
||||
|
||||
def executeAction
|
||||
mob.turn_to @door_object.position
|
||||
DoorUtil::toggle(@door_object, mob)
|
||||
mob.turn_to(@door.position)
|
||||
DoorUtil::toggle(@door, mob)
|
||||
stop
|
||||
end
|
||||
|
||||
def equals(other)
|
||||
return (get_class == other.get_class && @door_object == other.door_object)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Message handler for opening and closing doors.
|
||||
on :message, :first_object_action do |ctx, player, message|
|
||||
if DoorUtil::is_door?(message.id)
|
||||
door_object = DoorUtil::get_door_object(message.position, message.id)
|
||||
player.start_action(OpenDoorAction.new(player, door_object)) unless door_object.nil?
|
||||
puts "Player: #{player.position}, door: #{message.position}"
|
||||
door = DoorUtil::get_door_object(message.position, message.id)
|
||||
player.start_action(OpenDoorAction.new(player, door)) unless door.nil?
|
||||
end
|
||||
end
|
||||
@@ -1,20 +1,22 @@
|
||||
java_import 'org.apollo.game.model.entity.GameObject'
|
||||
java_import 'org.apollo.game.model.entity.Entity'
|
||||
java_import 'org.apollo.game.model.Position'
|
||||
java_import 'org.apollo.game.message.impl.PositionMessage'
|
||||
java_import 'org.apollo.game.message.impl.RemoveObjectMessage'
|
||||
java_import 'org.apollo.game.message.impl.SendObjectMessage'
|
||||
require 'java'
|
||||
|
||||
java_import 'org.apollo.game.model.Position'
|
||||
java_import 'org.apollo.game.model.area.Region'
|
||||
java_import 'org.apollo.game.model.entity.Entity'
|
||||
java_import 'org.apollo.game.model.entity.obj.DynamicGameObject'
|
||||
|
||||
# Contains door-related utility methods.
|
||||
module DoorUtil
|
||||
include DoorConstants
|
||||
|
||||
# A hash containing currently toggled door objects mapped to the original door objects.
|
||||
TOGGLED_DOOR_REPOSITORY = {}
|
||||
TOGGLED_DOORS = {}
|
||||
|
||||
# Translates a door's position in the direction of its orientation.
|
||||
def self.translate_door_position(door)
|
||||
position = door.position
|
||||
orientation = door.orientation
|
||||
|
||||
case orientation
|
||||
when Orientation::WEST
|
||||
return Position.new(position.x - 1, position.y, position.height)
|
||||
@@ -25,6 +27,7 @@ module DoorUtil
|
||||
when Orientation::SOUTH
|
||||
return Position.new(position.x, position.y - 1, position.height)
|
||||
end
|
||||
|
||||
raise 'Invalid orientation for door!'
|
||||
end
|
||||
|
||||
@@ -32,68 +35,49 @@ module DoorUtil
|
||||
def self.translate_door_orientation(door)
|
||||
object_id = door.id
|
||||
orientation = door.orientation
|
||||
if RIGHT_SIDE_HINGE_DOOR_IDS.include?(object_id)
|
||||
|
||||
if RIGHT_HINGE_DOORS.include?(object_id)
|
||||
return ORIENTATIONS[:right_side_hinge][orientation]
|
||||
elsif LEFT_SIDE_HINGE_DOOR_IDS.include?(object_id)
|
||||
elsif LEFT_HINGE_DOORS.include?(object_id)
|
||||
return ORIENTATIONS[:left_side_hinge][orientation]
|
||||
end
|
||||
raise 'Given object was not registered as a door!'
|
||||
end
|
||||
|
||||
# Replaces a door object for a given player.
|
||||
# TODO: This is temporary.
|
||||
def self.replace_door(player, original, new)
|
||||
player.send PositionMessage.new(player.last_known_region, original.position)
|
||||
player.send RemoveObjectMessage.new(original)
|
||||
player.send PositionMessage.new(player.last_known_region, new.position)
|
||||
player.send SendObjectMessage.new(new)
|
||||
raise 'Given object was not registered as a door.'
|
||||
end
|
||||
|
||||
# Toggles the given door.
|
||||
def self.toggle(door, player)
|
||||
# First, we remove the door we're toggling (or un-toggling) from the game world.
|
||||
position = door.position
|
||||
region = $world.region_repository.from_position(position)
|
||||
region.remove_entity door
|
||||
region.remove_entity(door)
|
||||
|
||||
# Have we toggled this door already?
|
||||
if TOGGLED_DOOR_REPOSITORY.include?(door)
|
||||
# If we have, we get our original door. This also deletes the entry from our repository.
|
||||
original_door = TOGGLED_DOOR_REPOSITORY.delete(door)
|
||||
if TOGGLED_DOORS.include?(door)
|
||||
original_door = TOGGLED_DOORS.delete(door)
|
||||
|
||||
# Now we add our new door to the game world.
|
||||
original_region = $world.region_repository.from_position(original_door.position)
|
||||
original_region.add_entity original_door
|
||||
|
||||
# TODO: This and the 'player' parameter are temporary. We still need to synchronize objects for local players.
|
||||
replace_door player, door, original_door
|
||||
original_region.add_entity(original_door)
|
||||
else
|
||||
# If not, we get the translated orientation and position for this door, and create a new game object.
|
||||
toggled_position = translate_door_position(door)
|
||||
toggled_orientation = translate_door_orientation(door)
|
||||
toggled_door = GameObject.new(door.id, toggled_position, door.type, toggled_orientation)
|
||||
toggled_door = DynamicGameObject.createPublic(door.id, toggled_position, door.type, toggled_orientation)
|
||||
|
||||
# Now we add our new door to the game world.
|
||||
toggled_region = $world.region_repository.from_position(toggled_position)
|
||||
toggled_region.add_entity toggled_door
|
||||
toggled_region.add_entity(toggled_door)
|
||||
|
||||
# Insert our toggled door in the repository.
|
||||
TOGGLED_DOOR_REPOSITORY[toggled_door] = door
|
||||
|
||||
# TODO: This and the 'player' parameter are temporary. We still need to synchronize objects for local players.
|
||||
replace_door player, door, toggled_door
|
||||
TOGGLED_DOORS[toggled_door] = door
|
||||
end
|
||||
end
|
||||
|
||||
# Gets the door object at the given position, if it exists.
|
||||
def self.get_door_object(position, object_id)
|
||||
game_objects = $world.region_repository.from_position(position).get_entities(position, EntityType::GAME_OBJECT)
|
||||
game_objects = $world.region_repository.from_position(position).get_entities(position, EntityType::DYNAMIC_OBJECT, EntityType::STATIC_OBJECT)
|
||||
game_objects.each { |game_object| return game_object if game_object.id == object_id }
|
||||
return nil
|
||||
end
|
||||
|
||||
# Checks if the given game object id is a door.
|
||||
def self.is_door?(object_id)
|
||||
RIGHT_SIDE_HINGE_DOOR_IDS.include?(object_id) || LEFT_SIDE_HINGE_DOOR_IDS.include?(object_id)
|
||||
RIGHT_HINGE_DOORS.include?(object_id) || LEFT_HINGE_DOORS.include?(object_id)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -14,9 +14,10 @@ import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.area.Region;
|
||||
import org.apollo.game.model.area.RegionRepository;
|
||||
import org.apollo.game.model.area.collision.CollisionMatrix;
|
||||
import org.apollo.game.model.area.obj.ObjectType;
|
||||
import org.apollo.game.model.def.ObjectDefinition;
|
||||
import org.apollo.game.model.entity.GameObject;
|
||||
import org.apollo.game.model.entity.obj.GameObject;
|
||||
import org.apollo.game.model.entity.obj.ObjectType;
|
||||
import org.apollo.game.model.entity.obj.StaticGameObject;
|
||||
import org.apollo.util.BufferUtil;
|
||||
import org.apollo.util.CompressionUtil;
|
||||
|
||||
@@ -132,7 +133,7 @@ public final class GameObjectDecoder {
|
||||
if (block) {
|
||||
for (int dx = 0; dx < definition.getWidth(); dx++) {
|
||||
for (int dy = 0; dy < definition.getLength(); dy++) {
|
||||
int localX = (x % Region.REGION_SIZE) + dx, localY = (y % Region.REGION_SIZE) + dy;
|
||||
int localX = (x % Region.SIZE) + dx, localY = (y % Region.SIZE) + dy;
|
||||
|
||||
if (localX > 7 || localY > 7) {
|
||||
int nextLocalX = localX > 7 ? x + localX - 7 : x + localX;
|
||||
@@ -140,8 +141,7 @@ public final class GameObjectDecoder {
|
||||
Position nextPosition = new Position(nextLocalX, nextLocalY);
|
||||
Region next = regions.fromPosition(nextPosition);
|
||||
|
||||
int nextX = (nextPosition.getX() % Region.REGION_SIZE) + dx, nextY = (nextPosition.getY() % Region.REGION_SIZE)
|
||||
+ dy;
|
||||
int nextX = (nextPosition.getX() % Region.SIZE) + dx, nextY = (nextPosition.getY() % Region.SIZE) + dy;
|
||||
if (nextX > 7)
|
||||
nextX -= 7;
|
||||
if (nextY > 7)
|
||||
@@ -181,7 +181,7 @@ public final class GameObjectDecoder {
|
||||
}
|
||||
|
||||
if (block) {
|
||||
int localX = (x % Region.REGION_SIZE), localY = (y % Region.REGION_SIZE);
|
||||
int localX = (x % Region.SIZE), localY = (y % Region.SIZE);
|
||||
current.block(localX, localY);
|
||||
}
|
||||
}
|
||||
@@ -215,7 +215,7 @@ public final class GameObjectDecoder {
|
||||
int orientation = attributes & 0x3;
|
||||
Position position = new Position(x + localX, y + localY, height);
|
||||
|
||||
GameObject object = new GameObject(id, position, type, orientation);
|
||||
GameObject object = new StaticGameObject(id, position, type, orientation);
|
||||
objects.add(object);
|
||||
|
||||
block(object, position);
|
||||
|
||||
@@ -21,7 +21,7 @@ public final class MapFileDecoder {
|
||||
/**
|
||||
* The width (and length) of a map file, in tiles.
|
||||
*/
|
||||
public static final int MAP_FILE_WIDTH = Region.REGION_SIZE * Region.REGION_SIZE;
|
||||
public static final int MAP_FILE_WIDTH = Region.SIZE * Region.SIZE;
|
||||
|
||||
/**
|
||||
* The file id of the versions archive.
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.apollo.Service;
|
||||
import org.apollo.game.message.handler.MessageHandlerChainGroup;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.World.RegistrationStatus;
|
||||
import org.apollo.game.model.area.Region;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.sync.ClientSynchronizer;
|
||||
import org.apollo.io.MessageHandlerChainParser;
|
||||
@@ -49,7 +50,8 @@ public final class GameService extends Service {
|
||||
/**
|
||||
* The scheduled executor service.
|
||||
*/
|
||||
private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("GameService"));
|
||||
private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory(
|
||||
"GameService"));
|
||||
|
||||
/**
|
||||
* The {@link ClientSynchronizer}.
|
||||
@@ -154,10 +156,15 @@ public final class GameService extends Service {
|
||||
* @return A {@link RegistrationStatus}.
|
||||
*/
|
||||
public RegistrationStatus registerPlayer(Player player, GameSession session) {
|
||||
World world = World.getWorld();
|
||||
|
||||
synchronized (this) {
|
||||
RegistrationStatus status = World.getWorld().register(player);
|
||||
RegistrationStatus status = world.register(player);
|
||||
if (status == RegistrationStatus.OK) {
|
||||
player.setSession(session);
|
||||
|
||||
Region region = world.getRegionRepository().get(player.getPosition().getRegionCoordinates());
|
||||
region.addEntity(player);
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -169,7 +176,8 @@ public final class GameService extends Service {
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
scheduledExecutor.scheduleAtFixedRate(new GamePulseHandler(this), GameConstants.PULSE_DELAY, GameConstants.PULSE_DELAY, TimeUnit.MILLISECONDS);
|
||||
scheduledExecutor.scheduleAtFixedRate(new GamePulseHandler(this), GameConstants.PULSE_DELAY, GameConstants.PULSE_DELAY,
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,8 +12,8 @@ import org.apollo.game.model.area.Region;
|
||||
import org.apollo.game.model.area.RegionRepository;
|
||||
import org.apollo.game.model.def.ObjectDefinition;
|
||||
import org.apollo.game.model.entity.Entity.EntityType;
|
||||
import org.apollo.game.model.entity.GameObject;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.entity.obj.GameObject;
|
||||
|
||||
/**
|
||||
* A verification {@link MessageHandler} for the {@link ObjectActionMessage}.
|
||||
@@ -34,10 +34,11 @@ public final class ObjectActionVerificationHandler extends MessageHandler<Object
|
||||
ctx.breakHandlerChain();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Position position = message.getPosition();
|
||||
Region region = repository.fromPosition(position);
|
||||
Set<GameObject> objects = region.getEntities(position, EntityType.GAME_OBJECT);
|
||||
Set<GameObject> objects = region.getEntities(position, EntityType.STATIC_OBJECT, EntityType.DYNAMIC_OBJECT);
|
||||
|
||||
if (!player.getPosition().isWithinDistance(position, 15) || !containsObject(id, objects)) {
|
||||
ctx.breakHandlerChain();
|
||||
|
||||
@@ -19,9 +19,9 @@ public final class WalkMessageHandler extends MessageHandler<WalkMessage> {
|
||||
WalkingQueue queue = player.getWalkingQueue();
|
||||
|
||||
Position[] steps = message.getSteps();
|
||||
for (int i = 0; i < steps.length; i++) {
|
||||
Position step = steps[i];
|
||||
if (i == 0) {
|
||||
for (int index = 0; index < steps.length; index++) {
|
||||
Position step = steps[index];
|
||||
if (index == 0) {
|
||||
if (!queue.addFirstStep(step)) {
|
||||
return; // ignore packet
|
||||
}
|
||||
@@ -31,16 +31,15 @@ public final class WalkMessageHandler extends MessageHandler<WalkMessage> {
|
||||
}
|
||||
|
||||
queue.setRunningQueue(message.isRunning() || player.isRunning());
|
||||
player.getInterfaceSet().close();
|
||||
|
||||
if (queue.size() > 0) {
|
||||
player.stopAction();
|
||||
}
|
||||
player.getInterfaceSet().close();
|
||||
|
||||
if (player.getInteractingMob() != null) {
|
||||
player.resetInteractingMob();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.area.RegionCoordinates;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to remove all spawned objects and items from a Region.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class ClearRegionMessage extends Message {
|
||||
|
||||
/**
|
||||
* The Position of the Player.
|
||||
*/
|
||||
private final Position player;
|
||||
|
||||
/**
|
||||
* The Position in the Region being cleared.
|
||||
*/
|
||||
private final Position region;
|
||||
|
||||
/**
|
||||
* Creates the ClearRegionMessage.
|
||||
*
|
||||
* @param player The {@link Position} of the Player this {@link Message} is being sent to.
|
||||
* @param region The {@link RegionCoordinates} of the Region being cleared.
|
||||
*/
|
||||
public ClearRegionMessage(Position player, RegionCoordinates region) {
|
||||
this.player = player;
|
||||
this.region = new Position(region.getAbsoluteX(), region.getAbsoluteY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Position} of the Player this {@link Message} is being sent to..
|
||||
*
|
||||
* @return The Position.
|
||||
*/
|
||||
public Position getPlayerPosition() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Position} of the Region being cleared.
|
||||
*
|
||||
* @return The Position.
|
||||
*/
|
||||
public Position getRegionPosition() {
|
||||
return region;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.area.RegionCoordinates;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client that contains multiple
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class GroupedRegionUpdateMessage extends Message {
|
||||
|
||||
/**
|
||||
* The Position of the Player.
|
||||
*/
|
||||
private final Position player;
|
||||
|
||||
/**
|
||||
* The Position of the Region being updated.
|
||||
*/
|
||||
private final Position region;
|
||||
|
||||
/**
|
||||
* The List of RegionUpdateMessages to be sent.
|
||||
*/
|
||||
private final List<RegionUpdateMessage> messages;
|
||||
|
||||
/**
|
||||
* Creates the GroupedRegionUpdateMessage.
|
||||
*
|
||||
* @param player The {@link Position} of the Player.
|
||||
* @param coordinates The {@link RegionCoordinates} of the Region being updated.
|
||||
* @param messages The {@link List} of {@link RegionUpdateMessage}s.
|
||||
*/
|
||||
public GroupedRegionUpdateMessage(Position player, RegionCoordinates coordinates, List<RegionUpdateMessage> messages) {
|
||||
this.player = player;
|
||||
this.region = new Position(coordinates.getAbsoluteX(), coordinates.getAbsoluteY());
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Position} of the Player.
|
||||
*
|
||||
* @return The Position.
|
||||
*/
|
||||
public Position getPlayerPosition() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link List} of {@link RegionUpdateMessage}s.
|
||||
*
|
||||
* @return The Collection.
|
||||
*/
|
||||
public List<RegionUpdateMessage> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Position} of the Region these updates affect.
|
||||
*
|
||||
* @return The Position.
|
||||
*/
|
||||
public Position getRegionPosition() {
|
||||
return region;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.Position;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to focus on a specific {@link Position} (on which an action should be
|
||||
* performed).
|
||||
*
|
||||
* @author Chris Fletcher
|
||||
*/
|
||||
public final class PositionMessage extends Message {
|
||||
|
||||
/**
|
||||
* The base position.
|
||||
*/
|
||||
private final Position base;
|
||||
|
||||
/**
|
||||
* The target position.
|
||||
*/
|
||||
private final Position position;
|
||||
|
||||
/**
|
||||
* Creates a new position message.
|
||||
*
|
||||
* @param base The base from which the position is being focused on.
|
||||
* @param position The position to focus on.
|
||||
*/
|
||||
public PositionMessage(Position base, Position position) {
|
||||
this.base = base;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base position.
|
||||
*
|
||||
* @return The position.
|
||||
*/
|
||||
public Position getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position to focus on.
|
||||
*
|
||||
* @return The target position.
|
||||
*/
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
|
||||
/**
|
||||
* A {@link Message} that can be grouped with other Messages as part of a {@link GroupedRegionUpdateMessage}.
|
||||
* <p>
|
||||
* This is a utility class for Messages that can be grouped, as is not encoded directly.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public abstract class RegionUpdateMessage extends Message implements Comparable<RegionUpdateMessage> {
|
||||
|
||||
/**
|
||||
* The integer value indicating this RegionUpdateMessage is a high-priority message.
|
||||
*/
|
||||
protected static final int HIGH_PRIORITY = 0;
|
||||
|
||||
/**
|
||||
* The integer value indicating this RegionUpdateMessage is a low-priority message.
|
||||
*/
|
||||
protected static final int LOW_PRIORITY = 1;
|
||||
|
||||
@Override
|
||||
public final int compareTo(RegionUpdateMessage other) {
|
||||
return Integer.compare(priority(), other.priority());
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(Object obj);
|
||||
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
/**
|
||||
* Gets the priority of this RegionUpdateMessage, to use when sorting.
|
||||
*
|
||||
* @return The priority. Should be either 1 (low) or 0 (high).
|
||||
*/
|
||||
public abstract int priority();
|
||||
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.entity.GameObject;
|
||||
import org.apollo.game.model.entity.obj.GameObject;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to remove an object from a tile.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class RemoveObjectMessage extends Message {
|
||||
public final class RemoveObjectMessage extends RegionUpdateMessage {
|
||||
|
||||
/**
|
||||
* The orientation of the object.
|
||||
@@ -29,16 +29,7 @@ public final class RemoveObjectMessage extends Message {
|
||||
* Creates the RemoveObjectMessage.
|
||||
*
|
||||
* @param object The {@link GameObject} to send.
|
||||
*/
|
||||
public RemoveObjectMessage(GameObject object) {
|
||||
this(object, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the RemoveObjectMessage.
|
||||
*
|
||||
* @param object The {@link GameObject} to send.
|
||||
* @param positionOffset The offset of the object's position from the region's central position.
|
||||
* @param positionOffset The offset of the GameObject's Position from the Region's top-left position.
|
||||
*/
|
||||
public RemoveObjectMessage(GameObject object, int positionOffset) {
|
||||
this.positionOffset = positionOffset;
|
||||
@@ -46,6 +37,16 @@ public final class RemoveObjectMessage extends Message {
|
||||
this.orientation = object.getOrientation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof RemoveObjectMessage) {
|
||||
RemoveObjectMessage other = (RemoveObjectMessage) obj;
|
||||
return type == other.type && orientation == other.orientation && positionOffset == other.positionOffset;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the orientation of the object.
|
||||
*
|
||||
@@ -73,4 +74,16 @@ public final class RemoveObjectMessage extends Message {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = prime * positionOffset + orientation;
|
||||
return prime * result + type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int priority() {
|
||||
return HIGH_PRIORITY;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.Item;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to remove an item from a tile.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class RemoveTileItemMessage extends Message {
|
||||
public final class RemoveTileItemMessage extends RegionUpdateMessage {
|
||||
|
||||
/**
|
||||
* The item.
|
||||
* The id of the Item to remove.
|
||||
*/
|
||||
private final int id;
|
||||
|
||||
@@ -20,18 +21,9 @@ public final class RemoveTileItemMessage extends Message {
|
||||
private final int positionOffset;
|
||||
|
||||
/**
|
||||
* Creates a remove tile item message.
|
||||
* Creates the RemoveTileItemMessage.
|
||||
*
|
||||
* @param id The id of the item to remove.
|
||||
*/
|
||||
public RemoveTileItemMessage(int id) {
|
||||
this(id, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a remove tile item message.
|
||||
*
|
||||
* @param id The id of the item to remove.
|
||||
* @param id The id of the {@link Item} to remove.
|
||||
* @param positionOffset The offset from the 'base' position.
|
||||
*/
|
||||
public RemoveTileItemMessage(int id, int positionOffset) {
|
||||
@@ -39,6 +31,26 @@ public final class RemoveTileItemMessage extends Message {
|
||||
this.positionOffset = positionOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the RemoveTileItemMessage.
|
||||
*
|
||||
* @param item The {@link Item} to remove.
|
||||
* @param positionOffset The offset from the 'base' position.
|
||||
*/
|
||||
public RemoveTileItemMessage(Item item, int positionOffset) {
|
||||
this(item.getId(), positionOffset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof RemoveTileItemMessage) {
|
||||
RemoveTileItemMessage other = (RemoveTileItemMessage) obj;
|
||||
return id == other.id && positionOffset == other.positionOffset;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of the item to remove.
|
||||
*
|
||||
@@ -57,4 +69,15 @@ public final class RemoveTileItemMessage extends Message {
|
||||
return positionOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
return prime * id + positionOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int priority() {
|
||||
return HIGH_PRIORITY;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.entity.GameObject;
|
||||
import org.apollo.game.model.entity.obj.GameObject;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to spawn an object.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class SendObjectMessage extends Message {
|
||||
public final class SendObjectMessage extends RegionUpdateMessage {
|
||||
|
||||
/**
|
||||
* The id of the object.
|
||||
@@ -30,15 +30,6 @@ public final class SendObjectMessage extends Message {
|
||||
*/
|
||||
private final int type;
|
||||
|
||||
/**
|
||||
* Creates the SendObjectMessage.
|
||||
*
|
||||
* @param object The {@link GameObject} to send.
|
||||
*/
|
||||
public SendObjectMessage(GameObject object) {
|
||||
this(object, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the SendObjectMessage.
|
||||
*
|
||||
@@ -52,6 +43,20 @@ public final class SendObjectMessage extends Message {
|
||||
this.orientation = object.getOrientation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof SendObjectMessage) {
|
||||
SendObjectMessage other = (SendObjectMessage) obj;
|
||||
if (id != other.id || type != other.type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return positionOffset == other.positionOffset && type == other.type;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of the object.
|
||||
*
|
||||
@@ -88,4 +93,17 @@ public final class SendObjectMessage extends Message {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = prime * id + orientation;
|
||||
result = prime * result + type;
|
||||
return prime * result + positionOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int priority() {
|
||||
return LOW_PRIORITY;
|
||||
}
|
||||
|
||||
}
|
||||
+37
-25
@@ -8,7 +8,12 @@ import org.apollo.game.model.Item;
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class AddGlobalTileItemMessage extends Message {
|
||||
public final class SendPublicTileItemMessage extends RegionUpdateMessage {
|
||||
|
||||
/**
|
||||
* The index of the player who dropped the item.
|
||||
*/
|
||||
private final int index;
|
||||
|
||||
/**
|
||||
* The item to add to the tile.
|
||||
@@ -21,40 +26,26 @@ public final class AddGlobalTileItemMessage extends Message {
|
||||
private final int positionOffset;
|
||||
|
||||
/**
|
||||
* The index of the player who dropped the item.
|
||||
*/
|
||||
private final int index;
|
||||
|
||||
/**
|
||||
* Creates the add global tile item message.
|
||||
*
|
||||
* @param item The item to add to the tile.
|
||||
* @param index The index of the player who dropped the item.
|
||||
*/
|
||||
public AddGlobalTileItemMessage(Item item, int index) {
|
||||
this(item, index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the add global tile item message.
|
||||
* Creates the SendPublicTileItemMessage.
|
||||
*
|
||||
* @param item The item to add to the tile.
|
||||
* @param index The index of the player who dropped the item.
|
||||
* @param positionOffset The offset from the 'base' position.
|
||||
*/
|
||||
public AddGlobalTileItemMessage(Item item, int index, int positionOffset) {
|
||||
public SendPublicTileItemMessage(Item item, int index, int positionOffset) {
|
||||
this.item = item;
|
||||
this.index = index;
|
||||
this.positionOffset = positionOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of the item.
|
||||
*
|
||||
* @return The id.
|
||||
*/
|
||||
public int getId() {
|
||||
return item.getId();
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof SendPublicTileItemMessage) {
|
||||
SendPublicTileItemMessage other = (SendPublicTileItemMessage) obj;
|
||||
return item.equals(other.item) && index == other.index && positionOffset == other.positionOffset;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,6 +57,15 @@ public final class AddGlobalTileItemMessage extends Message {
|
||||
return item.getAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of the item.
|
||||
*
|
||||
* @return The id.
|
||||
*/
|
||||
public int getId() {
|
||||
return item.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the player who dropped the item.
|
||||
*
|
||||
@@ -84,4 +84,16 @@ public final class AddGlobalTileItemMessage extends Message {
|
||||
return positionOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = item.hashCode() * prime + index;
|
||||
return result * prime + positionOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int priority() {
|
||||
return LOW_PRIORITY;
|
||||
}
|
||||
|
||||
}
|
||||
+24
-12
@@ -8,7 +8,7 @@ import org.apollo.game.model.Item;
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class AddTileItemMessage extends Message {
|
||||
public final class SendTileItemMessage extends RegionUpdateMessage {
|
||||
|
||||
/**
|
||||
* The item to add to the tile.
|
||||
@@ -21,21 +21,12 @@ public final class AddTileItemMessage extends Message {
|
||||
private final int positionOffset;
|
||||
|
||||
/**
|
||||
* Creates an add tile item message.
|
||||
*
|
||||
* @param item The item to add to the tile.
|
||||
*/
|
||||
public AddTileItemMessage(Item item) {
|
||||
this(item, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an add tile item message.
|
||||
* Creates the SendTileItemMessage.
|
||||
*
|
||||
* @param item The item to add to the tile.
|
||||
* @param positionOffset The offset from the 'base' position.
|
||||
*/
|
||||
public AddTileItemMessage(Item item, int positionOffset) {
|
||||
public SendTileItemMessage(Item item, int positionOffset) {
|
||||
this.item = item;
|
||||
this.positionOffset = positionOffset;
|
||||
}
|
||||
@@ -67,4 +58,25 @@ public final class AddTileItemMessage extends Message {
|
||||
return positionOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof SendTileItemMessage) {
|
||||
SendTileItemMessage other = (SendTileItemMessage) obj;
|
||||
return item.equals(other.item) && positionOffset == other.positionOffset;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
return item.hashCode() * prime + positionOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int priority() {
|
||||
return LOW_PRIORITY;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.area.RegionCoordinates;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to set the coordinates of the Region currently being updated.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class SetUpdatedRegionMessage extends Message {
|
||||
|
||||
/**
|
||||
* The Position of the Player.
|
||||
*/
|
||||
private final Position player;
|
||||
|
||||
/**
|
||||
* The Position in the Region being cleared.
|
||||
*/
|
||||
private final Position region;
|
||||
|
||||
/**
|
||||
* Creates the SetUpdatedRegionMessage.
|
||||
*
|
||||
* @param player The {@link Position} of the Player this {@link Message} is being sent to.
|
||||
* @param region The {@link RegionCoordinates} of the Region being set.
|
||||
*/
|
||||
public SetUpdatedRegionMessage(Position player, RegionCoordinates region) {
|
||||
this.player = player;
|
||||
this.region = new Position(region.getAbsoluteX(), region.getAbsoluteY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Position} of the Player this {@link Message} is being sent to..
|
||||
*
|
||||
* @return The Position.
|
||||
*/
|
||||
public Position getPlayerPosition() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Position} of the Region being cleared.
|
||||
*
|
||||
* @return The Position.
|
||||
*/
|
||||
public Position getRegionPosition() {
|
||||
return region;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import org.apollo.game.model.Item;
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class UpdateTileItemMessage extends Message {
|
||||
public final class UpdateTileItemMessage extends RegionUpdateMessage {
|
||||
|
||||
/**
|
||||
* The {@link Item}.
|
||||
@@ -48,6 +48,16 @@ public final class UpdateTileItemMessage extends Message {
|
||||
this.positionOffset = positionOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof UpdateTileItemMessage) {
|
||||
UpdateTileItemMessage other = (UpdateTileItemMessage) obj;
|
||||
return item.equals(other.item) && previousAmount == other.previousAmount && positionOffset == other.positionOffset;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of the item.
|
||||
*
|
||||
@@ -84,4 +94,16 @@ public final class UpdateTileItemMessage extends Message {
|
||||
return previousAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = item.hashCode() * prime + positionOffset;
|
||||
return result * prime + previousAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int priority() {
|
||||
return LOW_PRIORITY;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,6 +50,16 @@ public final class Item {
|
||||
this.definition = ItemDefinition.lookup(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Item) {
|
||||
Item other = (Item) obj;
|
||||
return id == other.id && amount == other.amount;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount.
|
||||
*
|
||||
@@ -77,6 +87,12 @@ public final class Item {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
return amount * prime + id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("id", id).add("amount", amount).toString();
|
||||
|
||||
@@ -22,7 +22,8 @@ import org.apollo.game.model.def.ItemDefinition;
|
||||
import org.apollo.game.model.def.NpcDefinition;
|
||||
import org.apollo.game.model.def.ObjectDefinition;
|
||||
import org.apollo.game.model.entity.Entity;
|
||||
import org.apollo.game.model.entity.GameObject;
|
||||
import org.apollo.game.model.entity.Entity.EntityType;
|
||||
import org.apollo.game.model.entity.obj.GameObject;
|
||||
import org.apollo.game.model.entity.Npc;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.event.Event;
|
||||
@@ -36,6 +37,8 @@ import org.apollo.util.MobRepository;
|
||||
import org.apollo.util.NameUtil;
|
||||
import org.apollo.util.plugin.PluginManager;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
* The world class is a singleton which contains objects like the {@link MobRepository} for players and NPCs. It should
|
||||
* only contain things relevant to the in-game world and not classes which deal with I/O and such (these may be better
|
||||
@@ -123,6 +126,11 @@ public final class World {
|
||||
*/
|
||||
private PluginManager pluginManager;
|
||||
|
||||
/**
|
||||
* This world's {@link RegionRepository}.
|
||||
*/
|
||||
private final RegionRepository regions = RegionRepository.immutable();
|
||||
|
||||
/**
|
||||
* The release number (i.e. version) of this world.
|
||||
*/
|
||||
@@ -133,11 +141,6 @@ public final class World {
|
||||
*/
|
||||
private final Scheduler scheduler = new Scheduler();
|
||||
|
||||
/**
|
||||
* This world's {@link RegionRepository}.
|
||||
*/
|
||||
private final RegionRepository regions = RegionRepository.immutable();
|
||||
|
||||
/**
|
||||
* Creates the world.
|
||||
*/
|
||||
@@ -192,15 +195,6 @@ public final class World {
|
||||
return pluginManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the release number of this world.
|
||||
*
|
||||
* @return The release number.
|
||||
*/
|
||||
public int getReleaseNumber() {
|
||||
return releaseNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this world's {@link RegionRepository}.
|
||||
*
|
||||
@@ -210,6 +204,15 @@ public final class World {
|
||||
return regions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the release number of this world.
|
||||
*
|
||||
* @return The release number.
|
||||
*/
|
||||
public int getReleaseNumber() {
|
||||
return releaseNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the world by loading definitions from the specified file system.
|
||||
*
|
||||
@@ -288,7 +291,7 @@ public final class World {
|
||||
* @param npc The npc.
|
||||
* @return {@code true} if the npc registered successfully, otherwise {@code false}.
|
||||
*/
|
||||
public boolean register(final Npc npc) {
|
||||
public boolean register(Npc npc) {
|
||||
boolean success = npcRepository.add(npc);
|
||||
|
||||
if (success) {
|
||||
@@ -310,7 +313,7 @@ public final class World {
|
||||
* @param player The player.
|
||||
* @return A {@link RegistrationStatus}.
|
||||
*/
|
||||
public RegistrationStatus register(final Player player) {
|
||||
public RegistrationStatus register(Player player) {
|
||||
String username = player.getUsername();
|
||||
if (isPlayerOnline(username)) {
|
||||
return RegistrationStatus.ALREADY_ONLINE;
|
||||
@@ -319,8 +322,6 @@ public final class World {
|
||||
boolean success = playerRepository.add(player);
|
||||
if (success) {
|
||||
players.put(NameUtil.encodeBase37(username), player);
|
||||
Region region = regions.fromPosition(player.getPosition());
|
||||
region.addEntity(player);
|
||||
|
||||
logger.info("Registered player: " + player + " [count=" + playerRepository.size() + "]");
|
||||
return RegistrationStatus.OK;
|
||||
@@ -340,6 +341,20 @@ public final class World {
|
||||
return scheduler.schedule(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the specified {@link Entity}, which must not be a {@link Player} or an {@link Npc}, which have their own
|
||||
* register methods.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
*/
|
||||
public void spawn(Entity entity) {
|
||||
EntityType type = entity.getEntityType();
|
||||
Preconditions.checkArgument(type != EntityType.PLAYER && type != EntityType.NPC, "Cannot spawn a Mob.");
|
||||
|
||||
Region region = regions.fromPosition(entity.getPosition());
|
||||
region.addEntity(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the specified {@link Event}, passing it to the listeners..
|
||||
*
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.apollo.game.model.area;
|
||||
|
||||
/**
|
||||
* A type of update that an Entity in a {@link Region} may have.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public enum EntityUpdateType {
|
||||
|
||||
/**
|
||||
* The add type, when an Entity has been added to a {@link Region}.
|
||||
*/
|
||||
ADD,
|
||||
|
||||
/**
|
||||
* The remove type, when an Entity has been removed from a {@link Region}.
|
||||
*/
|
||||
REMOVE;
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package org.apollo.game.model.area;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -8,14 +10,18 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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.UpdateOperation;
|
||||
import org.apollo.game.model.entity.Entity;
|
||||
import org.apollo.game.model.entity.Entity.EntityType;
|
||||
import org.apollo.game.model.entity.obj.GameObject;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
@@ -25,10 +31,30 @@ import com.google.common.collect.ImmutableSet;
|
||||
*/
|
||||
public final class Region {
|
||||
|
||||
/**
|
||||
* A {@link RegionListener} for {@link UpdateOperation}s.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
private static final class UpdateRegionListener implements RegionListener {
|
||||
|
||||
@Override
|
||||
public void execute(Region region, Entity entity, EntityUpdateType update) {
|
||||
EntityType type = entity.getEntityType();
|
||||
if (type != EntityType.PLAYER && type != EntityType.NPC
|
||||
&& (type != EntityType.STATIC_OBJECT || update == EntityUpdateType.REMOVE)) {
|
||||
region.record(entity, update);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The width and length of a Region, in tiles.
|
||||
*/
|
||||
public static final int REGION_SIZE = 8;
|
||||
public static final int SIZE = 8;
|
||||
|
||||
static final long start = System.currentTimeMillis();
|
||||
|
||||
/**
|
||||
* The default size of newly-created sets, to reduce memory usage.
|
||||
@@ -53,7 +79,17 @@ public final class Region {
|
||||
/**
|
||||
* The CollisionMatrix.
|
||||
*/
|
||||
private final CollisionMatrix[] matrices = CollisionMatrix.createMatrices(Position.HEIGHT_LEVELS, REGION_SIZE, REGION_SIZE);
|
||||
private final CollisionMatrix[] matrices = CollisionMatrix.createMatrices(Position.HEIGHT_LEVELS, SIZE, SIZE);
|
||||
|
||||
/**
|
||||
* The Set containing RegionUpdateMessages which can be sent to add every non-Mob Entity in this Region.
|
||||
*/
|
||||
private final List<List<RegionUpdateMessage>> snapshots = new ArrayList<>(Position.HEIGHT_LEVELS);
|
||||
|
||||
/**
|
||||
* The Set containing UpdateOperations.
|
||||
*/
|
||||
private final List<List<RegionUpdateMessage>> updates = new ArrayList<>(Position.HEIGHT_LEVELS);
|
||||
|
||||
/**
|
||||
* Creates a new Region.
|
||||
@@ -72,6 +108,12 @@ public final class Region {
|
||||
*/
|
||||
public Region(RegionCoordinates coordinates) {
|
||||
this.coordinates = coordinates;
|
||||
listeners.add(new UpdateRegionListener());
|
||||
|
||||
for (int height = 0; height < Position.HEIGHT_LEVELS; height++) {
|
||||
snapshots.add(new ArrayList<>());
|
||||
updates.add(new ArrayList<>(DEFAULT_SET_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +130,11 @@ public final class Region {
|
||||
Set<Entity> local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE));
|
||||
local.add(entity);
|
||||
|
||||
notifyListeners(entity, RegionOperation.ADD);
|
||||
if ((System.currentTimeMillis() - start) / 1000 > 10 && (entity instanceof GameObject)) {
|
||||
System.out.println("Adding entity " + entity + " to " + entity.getPosition());
|
||||
}
|
||||
|
||||
notifyListeners(entity, EntityUpdateType.ADD);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,22 +174,24 @@ public final class Region {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a shallow copy of the {@link Set} of {@link Entity}s with the specified {@link EntityType}. The returned
|
||||
* Gets a shallow copy of the {@link Set} of {@link Entity}s with the specified {@link EntityType}(s). 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}.
|
||||
* @param types The {@link EntityType}s.
|
||||
* @return The set of entities.
|
||||
*/
|
||||
public <T extends Entity> Set<T> getEntities(Position position, EntityType type) {
|
||||
public <T extends Entity> Set<T> getEntities(Position position, EntityType... types) {
|
||||
Set<Entity> local = entities.get(position);
|
||||
if (local == null) {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
|
||||
Set<EntityType> set = new HashSet<>(Arrays.asList(types));
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<T> filtered = (Set<T>) local.stream().filter(Entity -> Entity.getEntityType() == type).collect(Collectors.toSet());
|
||||
Set<T> filtered = (Set<T>) local.stream().filter(entity -> set.contains(entity.getEntityType()))
|
||||
.collect(Collectors.toSet());
|
||||
return ImmutableSet.copyOf(filtered);
|
||||
}
|
||||
|
||||
@@ -159,40 +207,41 @@ public final class Region {
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the {@link Entity} that was in the specified {@code old} {@link Position}, to the current position of the
|
||||
* Entity.
|
||||
* <p>
|
||||
* Both the {@code old} and current positions of the Entity must belong to this Region.
|
||||
* Gets a {@link Set} containing {@link RegionUpdateMessage}s that add every {@link Entity} in this Region.
|
||||
*
|
||||
* @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 Region.
|
||||
* @param height The height level to get the Set of RegionUpdateMessages for.
|
||||
* @return The Set of RegionUpdateMessages.
|
||||
*/
|
||||
public void moveEntity(Position old, Entity entity) {
|
||||
Position position = entity.getPosition();
|
||||
checkPosition(old);
|
||||
checkPosition(position);
|
||||
public List<RegionUpdateMessage> getSnapshot(int height) {
|
||||
List<RegionUpdateMessage> copy = new ArrayList<>(snapshots.get(height));
|
||||
Collections.sort(copy);
|
||||
return ImmutableList.copyOf(copy);
|
||||
}
|
||||
|
||||
Set<Entity> local = entities.get(old);
|
||||
/**
|
||||
* Gets the updates that have occurred in the last tick in this Region, as a {@link Set} of
|
||||
* {@link RegionUpdateMessage}s.
|
||||
*
|
||||
* @param height The height level to get the Set of RegionUpdateMessages for.
|
||||
* @return The Set of RegionUpdateMessages.
|
||||
*/
|
||||
public List<RegionUpdateMessage> getUpdates(int height) {
|
||||
List<RegionUpdateMessage> original = this.updates.get(height);
|
||||
List<RegionUpdateMessage> updates = new ArrayList<>(original);
|
||||
original.clear();
|
||||
|
||||
if (local == null || !local.remove(entity)) {
|
||||
throw new IllegalArgumentException("Entity belongs in this Region (" + this + ") but does not exist.");
|
||||
}
|
||||
|
||||
local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE));
|
||||
|
||||
local.add(entity);
|
||||
notifyListeners(entity, RegionOperation.MOVE);
|
||||
Collections.sort(updates);
|
||||
return ImmutableList.copyOf(updates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the {@link RegionListener}s registered to this Region that an update has occurred.
|
||||
*
|
||||
* @param entity The {@link Entity} that was updated.
|
||||
* @param operation The {@link RegionOperation} that occurred.
|
||||
* @param type The {@link EntityUpdateType} that occurred.
|
||||
*/
|
||||
public void notifyListeners(Entity entity, RegionOperation operation) {
|
||||
listeners.forEach(listener -> listener.execute(this, entity, operation));
|
||||
public void notifyListeners(Entity entity, EntityUpdateType type) {
|
||||
listeners.forEach(listener -> listener.execute(this, entity, type));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,7 +260,12 @@ public final class Region {
|
||||
throw new IllegalArgumentException("Entity belongs in this Region (" + this + ") but does not exist.");
|
||||
}
|
||||
|
||||
notifyListeners(entity, RegionOperation.REMOVE);
|
||||
notifyListeners(entity, EntityUpdateType.REMOVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("coordinates", coordinates).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,12 +281,7 @@ public final class Region {
|
||||
CollisionMatrix matrix = matrices[position.getHeight()];
|
||||
int x = position.getX(), y = position.getY();
|
||||
|
||||
return !matrix.untraversable(x % REGION_SIZE, y % REGION_SIZE, entity, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("coordinates", coordinates).toString();
|
||||
return !matrix.untraversable(x % SIZE, y % SIZE, entity, direction);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,4 +295,19 @@ public final class Region {
|
||||
"Position is not included in this Region.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the specified {@link Entity} as being updated this pulse.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
* @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) {
|
||||
RegionUpdateMessage message = entity.toUpdateOperation(this, type).toMessage();
|
||||
int height = entity.getPosition().getHeight();
|
||||
|
||||
updates.get(height).add(message);
|
||||
snapshots.get(height).add(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,10 +14,10 @@ import com.google.common.base.MoreObjects;
|
||||
public final class RegionCoordinates {
|
||||
|
||||
/**
|
||||
* Gets a pair of region coordinates from a {@link Position}.
|
||||
* Gets the RegionCoordinates for the specified {@link Position}.
|
||||
*
|
||||
* @param position The position.
|
||||
* @return The region coordinates.
|
||||
* @param position The Position.
|
||||
* @return The RegionCoordinates.
|
||||
*/
|
||||
public static RegionCoordinates fromPosition(Position position) {
|
||||
return new RegionCoordinates(position.getTopLeftRegionX(), position.getTopLeftRegionY());
|
||||
@@ -54,6 +54,24 @@ public final class RegionCoordinates {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the absolute x coordinate of this Region (which can be compared directly against {@link Position#getX()}.
|
||||
*
|
||||
* @return The absolute x coordinate.
|
||||
*/
|
||||
public int getAbsoluteX() {
|
||||
return Region.SIZE * (x + 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the absolute y coordinate of this Region (which can be compared directly against {@link Position#getY()}.
|
||||
*
|
||||
* @return The absolute y coordinate.
|
||||
*/
|
||||
public int getAbsoluteY() {
|
||||
return Region.SIZE * (y + 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x coordinate (equivalent to the {@link Position#getTopLeftRegionX()} of a position within this region).
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@ public interface RegionListener {
|
||||
*
|
||||
* @param region The {@link Region} that was updated.
|
||||
* @param entity The affected {@link Entity}.
|
||||
* @param operation The type of {@link RegionOperation}.
|
||||
* @param type The type of {@link EntityUpdateType}.
|
||||
*/
|
||||
public abstract void execute(Region region, Entity entity, RegionOperation operation);
|
||||
public abstract void execute(Region region, Entity entity, EntityUpdateType type);
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.apollo.game.model.area;
|
||||
|
||||
/**
|
||||
* An operation that can be performed by a region, used by {@link RegionListener}s to differentiate between operations.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public enum RegionOperation {
|
||||
|
||||
/**
|
||||
* The add operation, when an entity has been added to a region.
|
||||
*/
|
||||
ADD,
|
||||
|
||||
/**
|
||||
* The move operation, when an entity has moved positions, but is still in the same region.
|
||||
*/
|
||||
MOVE,
|
||||
|
||||
/**
|
||||
* The remove operation, when an entity has been removed from a region.
|
||||
*/
|
||||
REMOVE;
|
||||
|
||||
}
|
||||
@@ -76,7 +76,13 @@ public final class CollisionMatrix {
|
||||
* @return {@code true} if all of the CollisionFlags are set, otherwise {@code false}.
|
||||
*/
|
||||
public boolean all(int x, int y, CollisionFlag... flags) {
|
||||
return Arrays.stream(flags).allMatch(flag -> (get(x, y) & flag.asByte()) != 0);
|
||||
for (CollisionFlag flag : flags) {
|
||||
if (!flagged(x, y, flag)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +95,13 @@ public final class CollisionMatrix {
|
||||
* @return {@code true} if any of the CollisionFlags are set, otherwise {@code false}.
|
||||
*/
|
||||
public boolean any(int x, int y, CollisionFlag... flags) {
|
||||
return Arrays.stream(flags).anyMatch(flag -> (get(x, y) & flag.asByte()) != 0);
|
||||
for (CollisionFlag flag : flags) {
|
||||
if (flagged(x, y, flag)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,6 +159,17 @@ public final class CollisionMatrix {
|
||||
set(x, y, ALL_ALLOWED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the appropriate index for the specified coordinate pair to the specified value.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param value The value.
|
||||
*/
|
||||
private void set(int x, int y, byte value) {
|
||||
matrix[indexOf(x, y)] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets (i.e. sets to {@code true}) the value of the specified {@link CollisionFlag} for the specified coordinate
|
||||
* pair.
|
||||
@@ -161,7 +184,8 @@ public final class CollisionMatrix {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("width", width).add("length", length).add("matrix", Arrays.toString(matrix)).toString();
|
||||
return MoreObjects.toStringHelper(this).add("width", width).add("length", length).add("matrix", Arrays.toString(matrix))
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,15 +239,4 @@ public final class CollisionMatrix {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the appropriate index for the specified coordinate pair to the specified value.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param value The value.
|
||||
*/
|
||||
public void set(int x, int y, byte value) {
|
||||
matrix[indexOf(x, y)] = value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.apollo.game.model.area.update;
|
||||
|
||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
||||
import org.apollo.game.message.impl.RemoveTileItemMessage;
|
||||
import org.apollo.game.message.impl.SendPublicTileItemMessage;
|
||||
import org.apollo.game.model.area.EntityUpdateType;
|
||||
import org.apollo.game.model.area.Region;
|
||||
import org.apollo.game.model.entity.GroundItem;
|
||||
|
||||
/**
|
||||
* A {@link UpdateOperation} for {@link GroundItem}s.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class ItemUpdateOperation extends UpdateOperation<GroundItem> {
|
||||
|
||||
/**
|
||||
* Creates the ItemUpdateOperation.
|
||||
*
|
||||
* @param region The {@link Region} the type occurred in. Must not be {@code null}.
|
||||
* @param type The {@link EntityUpdateType}. Must not be {@code null}.
|
||||
* @param item The modified {@link GroundItem}. Must not be {@code null}.
|
||||
*/
|
||||
public ItemUpdateOperation(Region region, EntityUpdateType type, GroundItem item) {
|
||||
super(region, type, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RegionUpdateMessage add(int offset) {
|
||||
return new SendPublicTileItemMessage(entity.getItem(), offset, entity.getOwnerIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RegionUpdateMessage remove(int offset) {
|
||||
return new RemoveTileItemMessage(entity.getItem(), offset);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.apollo.game.model.area.update;
|
||||
|
||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
||||
import org.apollo.game.message.impl.RemoveObjectMessage;
|
||||
import org.apollo.game.message.impl.SendObjectMessage;
|
||||
import org.apollo.game.model.area.EntityUpdateType;
|
||||
import org.apollo.game.model.area.Region;
|
||||
import org.apollo.game.model.entity.obj.GameObject;
|
||||
|
||||
/**
|
||||
* A {@link UpdateOperation} for addition or removal of {@link GameObject}s.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class ObjectUpdateOperation extends UpdateOperation<GameObject> {
|
||||
|
||||
/**
|
||||
* Creates the ObjectUpdateOperation.
|
||||
*
|
||||
* @param region The {@link Region} in which the ObjectUpdateOperation occurred. Must not be {@code null}.
|
||||
* @param type The {@link EntityUpdateType}. Must not be {@code null}.
|
||||
* @param object The {@linkGameObject}. Must not be {@code null}.
|
||||
*/
|
||||
public ObjectUpdateOperation(Region region, EntityUpdateType type, GameObject object) {
|
||||
super(region, type, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RegionUpdateMessage add(int offset) {
|
||||
return new SendObjectMessage(entity, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RegionUpdateMessage remove(int offset) {
|
||||
return new RemoveObjectMessage(entity, offset);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.apollo.game.model.area.update;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.area.EntityUpdateType;
|
||||
import org.apollo.game.model.area.Region;
|
||||
import org.apollo.game.model.area.RegionCoordinates;
|
||||
import org.apollo.game.model.entity.Entity;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
* An type that is contained in the snapshot of a {@link Region}, which consists of an {@link Entity} being added,
|
||||
* removed, or moved.
|
||||
*
|
||||
* @author Major
|
||||
* @param <E> The type of {@link Entity} in this type.
|
||||
*/
|
||||
public abstract class UpdateOperation<E extends Entity> {
|
||||
|
||||
/**
|
||||
* The Entity involved in this UpdateOperation.
|
||||
*/
|
||||
protected final E entity;
|
||||
|
||||
/**
|
||||
* The Region in which this type occurred.
|
||||
*/
|
||||
protected final Region region;
|
||||
|
||||
/**
|
||||
* The type of update.
|
||||
*/
|
||||
protected final EntityUpdateType type;
|
||||
|
||||
/**
|
||||
* Creates the UpdateOperation.
|
||||
*
|
||||
* @param region The region in which the UpdateOperation occurred. Must not be {@code null}.
|
||||
* @param type The type of {@link EntityUpdateType}. Must not be {@code null}.
|
||||
* @param entity The {@link Entity} being added or removed. Must not be {@code null}.
|
||||
*/
|
||||
public UpdateOperation(Region region, EntityUpdateType type, E entity) {
|
||||
this.region = region;
|
||||
this.type = type;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this UpdateOperation as a {@link Message}.
|
||||
*
|
||||
* @return The Message.
|
||||
*/
|
||||
public final RegionUpdateMessage toMessage() {
|
||||
int offset = getPositionOffset(entity.getPosition());
|
||||
|
||||
switch (type) {
|
||||
case ADD:
|
||||
return add(offset);
|
||||
case REMOVE:
|
||||
return remove(offset);
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported EntityUpdateType " + type + ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link RegionUpdateMessage} that adds the {@link Entity} in this UpdateOperation.
|
||||
*
|
||||
* @param offset The offset of the {@link Position} of the Entity from the Position of the {@link Region}.
|
||||
* @return The RegionUpdateMessage.
|
||||
*/
|
||||
protected abstract RegionUpdateMessage add(int offset);
|
||||
|
||||
/**
|
||||
* Returns a {@link RegionUpdateMessage} that removes the {@link Entity} in this UpdateOperation.
|
||||
*
|
||||
* @param offset The offset of the {@link Position} of the Entity from the Position of the {@link Region}.
|
||||
* @return The RegionUpdateMessage.
|
||||
*/
|
||||
protected abstract RegionUpdateMessage remove(int offset);
|
||||
|
||||
/**
|
||||
* Gets the position offset for the specified {@link Position}.
|
||||
*
|
||||
* @param position The Position.
|
||||
* @return The position offset.
|
||||
*/
|
||||
private final int getPositionOffset(Position position) {
|
||||
RegionCoordinates coordinates = region.getCoordinates();
|
||||
int dx = position.getX() - coordinates.getAbsoluteX();
|
||||
int dy = position.getY() - coordinates.getAbsoluteY();
|
||||
|
||||
Preconditions.checkArgument(dx >= 0 && dx < Region.SIZE, position + " not in expected Region of " + region + ".");
|
||||
Preconditions.checkArgument(dy >= 0 && dy < Region.SIZE, position + " not in expected Region of " + region + ".");
|
||||
|
||||
return (dx << 4) | dy;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Contains snapshot-related classes.
|
||||
*/
|
||||
package org.apollo.game.model.area.update;
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.apollo.game.model.def;
|
||||
|
||||
import org.apollo.game.model.entity.GameObject;
|
||||
import org.apollo.game.model.entity.obj.GameObject;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package org.apollo.game.model.entity;
|
||||
|
||||
import org.apollo.game.model.Position;
|
||||
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.
|
||||
@@ -11,28 +14,31 @@ public abstract class Entity {
|
||||
|
||||
/**
|
||||
* Represents a type of {@link Entity}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public enum EntityType {
|
||||
|
||||
/**
|
||||
* An item that has been dropped on the ground.
|
||||
* An Item that is positioned on the ground.
|
||||
*/
|
||||
DROPPED_ITEM,
|
||||
GROUND_ITEM,
|
||||
|
||||
/**
|
||||
* An object appearing in the game world.
|
||||
* A GameObject that is loaded statically (i.e. from the game resources) at start-up.
|
||||
*/
|
||||
GAME_OBJECT,
|
||||
STATIC_OBJECT,
|
||||
|
||||
/**
|
||||
* An npc.
|
||||
* A GameObject that is loaded dynamically, usually for specific Players.
|
||||
*/
|
||||
DYNAMIC_OBJECT,
|
||||
|
||||
/**
|
||||
* An Npc.
|
||||
*/
|
||||
NPC,
|
||||
|
||||
/**
|
||||
* A player.
|
||||
* A Player.
|
||||
*/
|
||||
PLAYER,
|
||||
|
||||
@@ -41,6 +47,15 @@ public abstract class Entity {
|
||||
*/
|
||||
PROJECTILE;
|
||||
|
||||
/**
|
||||
* Returns whether or not this EntityType is for a Mob.
|
||||
*
|
||||
* @return {@code true} if this EntityType is for a Mob, otherwise {@code false}.
|
||||
*/
|
||||
public boolean isMob() {
|
||||
return this == PLAYER || this == NPC;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,6 +72,9 @@ public abstract class Entity {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* Gets the {@link EntityType} of this entity.
|
||||
*
|
||||
@@ -73,10 +91,16 @@ public abstract class Entity {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(Object obj);
|
||||
|
||||
@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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package org.apollo.game.model.entity;
|
||||
|
||||
import org.apollo.game.model.Item;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.area.Region;
|
||||
import org.apollo.game.model.area.EntityUpdateType;
|
||||
import org.apollo.game.model.area.update.ItemUpdateOperation;
|
||||
import org.apollo.game.model.area.update.UpdateOperation;
|
||||
|
||||
/**
|
||||
* An {@link Item} displayed on the ground.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class GroundItem extends Entity {
|
||||
|
||||
/**
|
||||
* Creates a new GroundItem.
|
||||
*
|
||||
* @param position The {@link Position} of the Item.
|
||||
* @param item The Item displayed on the ground.
|
||||
* @return The GroundItem.
|
||||
*/
|
||||
public static GroundItem create(Position position, Item item) {
|
||||
return new GroundItem(position, item, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new dropped GroundItem.
|
||||
*
|
||||
* @param position The {@link Position} of the Item.
|
||||
* @param item The Item displayed on the ground.
|
||||
* @param owner The the {@link Player} who dropped this GroundItem.
|
||||
* @return The GroundItem.
|
||||
*/
|
||||
public static GroundItem dropped(Position position, Item item, Player owner) {
|
||||
return new GroundItem(position, item, owner.getIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* The index of the Player who dropped this GroundItem.
|
||||
*/
|
||||
private final int index;
|
||||
|
||||
/**
|
||||
* The Item displayed on the ground.
|
||||
*/
|
||||
private final Item item;
|
||||
|
||||
/**
|
||||
* Creates the GroundItem.
|
||||
*
|
||||
* @param position The {@link Position} of the Item.
|
||||
* @param item The Item displayed on the ground.
|
||||
* @param index The index of the {@link Player} who dropped this GroundItem.
|
||||
*/
|
||||
private GroundItem(Position position, Item item, int index) {
|
||||
super(position);
|
||||
this.item = item;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof GroundItem) {
|
||||
GroundItem other = (GroundItem) obj;
|
||||
return position.equals(other.position);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityType getEntityType() {
|
||||
return EntityType.GROUND_ITEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Item} displayed on the ground.
|
||||
*
|
||||
* @return The Item.
|
||||
*/
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the {@link Player} who dropped this GroundItem, or {@code -1} if this GroundItem was not
|
||||
* dropped by a Player.
|
||||
*
|
||||
* @return The index.
|
||||
*/
|
||||
public int getOwnerIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return position.hashCode() * 31 + item.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateOperation<GroundItem> toUpdateOperation(Region region, EntityUpdateType operation) {
|
||||
return new ItemUpdateOperation(region, operation, this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,8 +11,10 @@ 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.def.NpcDefinition;
|
||||
import org.apollo.game.model.entity.attr.Attribute;
|
||||
import org.apollo.game.model.entity.attr.AttributeMap;
|
||||
@@ -194,8 +196,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;
|
||||
@@ -248,6 +250,15 @@ public abstract class Mob extends Entity {
|
||||
return interactingMob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this mobs interacting index.
|
||||
*
|
||||
* @return The interaction index of this mob.
|
||||
*/
|
||||
public int getInteractionIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this mob's inventory.
|
||||
*
|
||||
@@ -404,15 +415,6 @@ public abstract class Mob extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this mobs interacting index.
|
||||
*
|
||||
* @return The interaction index of this mob.
|
||||
*/
|
||||
public int getInteractionIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates this mob's interacting mob.
|
||||
*
|
||||
@@ -425,22 +427,19 @@ public abstract class Mob extends Entity {
|
||||
|
||||
/**
|
||||
* Sets the {@link Position} of this mob.
|
||||
* <p>
|
||||
* This method may be intercepted using a {@link MobPositionUpdateEvent}, which can be terminated like any other.
|
||||
* Plugins that intercept this Event <strong>must</strong> be cautious, because movement will not be possible (even
|
||||
* through mechanisms such as teleporting) if the Event is terminated.
|
||||
*
|
||||
* @param position The position.
|
||||
* @param position The Position.
|
||||
*/
|
||||
public final void setPosition(Position position) {
|
||||
World.getWorld().submit(new MobPositionUpdateEvent(this, position));
|
||||
// Intentionally ignore the Event result - accidentally terminating this method would break the entire server.
|
||||
if (World.getWorld().submit(new MobPositionUpdateEvent(this, position))) {
|
||||
Position old = this.position;
|
||||
RegionRepository repository = World.getWorld().getRegionRepository();
|
||||
Region current = repository.fromPosition(old), next = repository.fromPosition(position);
|
||||
|
||||
Position old = this.position;
|
||||
RegionRepository repository = World.getWorld().getRegionRepository();
|
||||
Region current = repository.fromPosition(old);
|
||||
|
||||
if (position.inside(current)) {
|
||||
this.position = position;
|
||||
current.moveEntity(old, this);
|
||||
} else {
|
||||
Region next = repository.fromPosition(position);
|
||||
current.removeEntity(this);
|
||||
this.position = position; // addEntity relies on the position being updated, so do that first.
|
||||
|
||||
@@ -523,6 +522,11 @@ public abstract class Mob extends Entity {
|
||||
stopAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final UpdateOperation<Entity> 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}.
|
||||
*
|
||||
|
||||
@@ -3,8 +3,6 @@ package org.apollo.game.model.entity;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.area.Region;
|
||||
import org.apollo.game.model.def.NpcDefinition;
|
||||
import org.apollo.game.sync.block.SynchronizationBlock;
|
||||
|
||||
@@ -44,7 +42,6 @@ public final class Npc extends Mob {
|
||||
super(position, definition);
|
||||
|
||||
this.boundaries = Optional.ofNullable(boundaries);
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,14 +119,4 @@ public final class Npc extends Mob {
|
||||
blockSet.add(SynchronizationBlock.createTransformBlock(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises this Npc.
|
||||
*/
|
||||
private void init() {
|
||||
// This has to be here instead of in Mob#init because of ordering issues - the Npc cannot be added to the
|
||||
// region until their credentials have been set, which is only done after the super constructors are called.
|
||||
Region region = World.getWorld().getRegionRepository().get(position.getRegionCoordinates());
|
||||
region.addEntity(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,6 @@ 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.area.Region;
|
||||
import org.apollo.game.model.entity.attr.Attribute;
|
||||
import org.apollo.game.model.entity.attr.AttributeDefinition;
|
||||
import org.apollo.game.model.entity.attr.AttributeMap;
|
||||
@@ -155,6 +154,11 @@ public final class Player extends Mob {
|
||||
*/
|
||||
private final transient Deque<Message> queuedMessages = new ArrayDeque<>();
|
||||
|
||||
/**
|
||||
* A flag indicating if the region changed in the last cycle.
|
||||
*/
|
||||
private transient boolean regionChanged = false;
|
||||
|
||||
/**
|
||||
* A flag indicating if this player is running.
|
||||
*/
|
||||
@@ -165,11 +169,6 @@ public final class Player extends Mob {
|
||||
*/
|
||||
private ScreenBrightness screenBrightness = ScreenBrightness.NORMAL;
|
||||
|
||||
/**
|
||||
* A flag indicating if the region changed in the last cycle.
|
||||
*/
|
||||
private transient boolean regionChanged = false;
|
||||
|
||||
/**
|
||||
* The {@link GameSession} currently attached to this {@link Player}.
|
||||
*/
|
||||
@@ -407,6 +406,15 @@ public final class Player extends Mob {
|
||||
return lastKnownRegion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link MembershipStatus} of this Player.
|
||||
*
|
||||
* @return The MembershipStatus.
|
||||
*/
|
||||
public MembershipStatus getMembershipStatus() {
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's prayer icon.
|
||||
*
|
||||
@@ -558,15 +566,6 @@ public final class Player extends Mob {
|
||||
return members == MembershipStatus.PAID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link MembershipStatus} of this Player.
|
||||
*
|
||||
* @return The MembershipStatus.
|
||||
*/
|
||||
public MembershipStatus getMembershipStatus() {
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this player is running.
|
||||
*
|
||||
@@ -846,6 +845,15 @@ public final class Player extends Mob {
|
||||
this.privilegeLevel = privilegeLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the region changed flag.
|
||||
*
|
||||
* @param regionChanged A flag indicating if the region has changed.
|
||||
*/
|
||||
public void setRegionChanged(boolean regionChanged) {
|
||||
this.regionChanged = regionChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's run energy.
|
||||
*
|
||||
@@ -865,15 +873,6 @@ public final class Player extends Mob {
|
||||
this.screenBrightness = brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the region changed flag.
|
||||
*
|
||||
* @param regionChanged A flag indicating if the region has changed.
|
||||
*/
|
||||
public void setRegionChanged(boolean regionChanged) {
|
||||
this.regionChanged = regionChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's {@link GameSession}.
|
||||
*
|
||||
@@ -943,7 +942,8 @@ public final class Player extends Mob {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("username", getUsername()).add("privilege", privilegeLevel).add("client version", getClientVersion()).toString();
|
||||
return MoreObjects.toStringHelper(this).add("username", getUsername()).add("privilege", privilegeLevel)
|
||||
.add("client version", getClientVersion()).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -952,11 +952,6 @@ public final class Player extends Mob {
|
||||
private void init() {
|
||||
initInventories();
|
||||
initSkills();
|
||||
|
||||
// This has to be here instead of in Mob#init because of ordering issues - the player cannot be added to the
|
||||
// region until their credentials have been set, which is only done after the super constructors are called.
|
||||
Region region = World.getWorld().getRegionRepository().get(position.getRegionCoordinates());
|
||||
region.addEntity(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -967,7 +962,8 @@ public final class Player extends Mob {
|
||||
InventoryListener fullBankListener = new FullInventoryListener(this, FullInventoryListener.FULL_BANK_MESSAGE);
|
||||
InventoryListener appearanceListener = new AppearanceInventoryListener(this);
|
||||
|
||||
InventoryListener syncInventoryListener = new SynchronizationInventoryListener(this, SynchronizationInventoryListener.INVENTORY_ID);
|
||||
InventoryListener syncInventoryListener = new SynchronizationInventoryListener(this,
|
||||
SynchronizationInventoryListener.INVENTORY_ID);
|
||||
InventoryListener syncBankListener = new SynchronizationInventoryListener(this, BankConstants.BANK_INVENTORY_ID);
|
||||
InventoryListener syncEquipmentListener = new SynchronizationInventoryListener(this,
|
||||
SynchronizationInventoryListener.EQUIPMENT_ID);
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
package org.apollo.game.model.entity.obj;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
|
||||
/**
|
||||
* A {@link GameObject} that is loaded dynamically, usually for specific Players.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class DynamicGameObject extends GameObject {
|
||||
|
||||
/**
|
||||
* A {@link WeakReference} for {@link Player}s.
|
||||
*/
|
||||
private static final class WeakPlayerReference extends WeakReference<Player> {
|
||||
|
||||
/**
|
||||
* Creates the WeakPlayerReference.
|
||||
*
|
||||
* @param player The Player wrapped in this {@link WeakReference}.
|
||||
*/
|
||||
public WeakPlayerReference(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof WeakPlayerReference) {
|
||||
WeakPlayerReference other = (WeakPlayerReference) obj;
|
||||
|
||||
Player player = get();
|
||||
return player != null && player.equals(other.get());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
Player player = get();
|
||||
return (player == null) ? 0 : player.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DynamicGameObject that is visible only to {@link Player}s specified later.
|
||||
*
|
||||
* @param id The id of the DynamicGameObject
|
||||
* @param position The {@link Position} of the DynamicGameObject.
|
||||
* @param type The type of the DynamicGameObject.
|
||||
* @param orientation The orientation of the DynamicGameObject.
|
||||
* @return The DynamicGameObject.
|
||||
*/
|
||||
public static DynamicGameObject createLocal(int id, Position position, int type, int orientation) {
|
||||
return new DynamicGameObject(id, position, type, orientation, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DynamicGameObject that is always visible.
|
||||
*
|
||||
* @param id The id of the DynamicGameObject
|
||||
* @param position The {@link Position} of the DynamicGameObject.
|
||||
* @param type The type of the DynamicGameObject.
|
||||
* @param orientation The orientation of the DynamicGameObject.
|
||||
* @return The DynamicGameObject.
|
||||
*/
|
||||
public static DynamicGameObject createPublic(int id, Position position, int type, int orientation) {
|
||||
return new DynamicGameObject(id, position, type, orientation, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The flag indicating whether or not this DynamicGameObject is visible to every player.
|
||||
*/
|
||||
private final boolean alwaysVisible;
|
||||
|
||||
/**
|
||||
* The Set of Players that can view this DynamicGameObject.
|
||||
*/
|
||||
private final Set<WeakPlayerReference> players = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Creates the DynamicGameObject.
|
||||
*
|
||||
* @param id The id of the DynamicGameObject
|
||||
* @param position The {@link Position} of the DynamicGameObject.
|
||||
* @param type The type of the DynamicGameObject.
|
||||
* @param orientation The orientation of the DynamicGameObject.
|
||||
* @param alwaysVisible The flag indicates whether or not this DynamicGameObject is visible to every player.
|
||||
*/
|
||||
private DynamicGameObject(int id, Position position, int type, int orientation, boolean alwaysVisible) {
|
||||
super(id, position, type, orientation);
|
||||
this.alwaysVisible = alwaysVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public boolean addTo(Player player) {
|
||||
WeakPlayerReference reference = new WeakPlayerReference(player);
|
||||
return players.add(reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityType getEntityType() {
|
||||
return EntityType.DYNAMIC_OBJECT;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public boolean removeFrom(Player player) {
|
||||
WeakPlayerReference reference = new WeakPlayerReference(player);
|
||||
return players.remove(reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean viewableBy(Player player) {
|
||||
return alwaysVisible || players.contains(new WeakPlayerReference(player));
|
||||
}
|
||||
|
||||
}
|
||||
+28
-14
@@ -1,7 +1,12 @@
|
||||
package org.apollo.game.model.entity;
|
||||
package org.apollo.game.model.entity.obj;
|
||||
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.area.EntityUpdateType;
|
||||
import org.apollo.game.model.area.Region;
|
||||
import org.apollo.game.model.area.update.ObjectUpdateOperation;
|
||||
import org.apollo.game.model.def.ObjectDefinition;
|
||||
import org.apollo.game.model.entity.Entity;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
@@ -11,7 +16,7 @@ import com.google.common.base.MoreObjects;
|
||||
* @author Chris Fletcher
|
||||
* @author Major
|
||||
*/
|
||||
public final class GameObject extends Entity {
|
||||
public abstract class GameObject extends Entity {
|
||||
|
||||
/**
|
||||
* The packed value that stores this object's id, type, and orientation.
|
||||
@@ -19,12 +24,12 @@ public final class GameObject extends Entity {
|
||||
private final int packed;
|
||||
|
||||
/**
|
||||
* Creates the game object.
|
||||
* Creates the GameObject.
|
||||
*
|
||||
* @param id The object's id.
|
||||
* @param position The position.
|
||||
* @param type The type code of the object.
|
||||
* @param orientation The orientation of the object.
|
||||
* @param id The id of the GameObject
|
||||
* @param position The {@link Position} of the GameObject.
|
||||
* @param type The type of the GameObject.
|
||||
* @param orientation The orientation of the GameObject.
|
||||
*/
|
||||
public GameObject(int id, Position position, int type, int orientation) {
|
||||
super(position);
|
||||
@@ -50,18 +55,13 @@ public final class GameObject extends Entity {
|
||||
return ObjectDefinition.lookup(getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityType getEntityType() {
|
||||
return EntityType.GAME_OBJECT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this object's id.
|
||||
*
|
||||
* @return The id.
|
||||
*/
|
||||
public int getId() {
|
||||
return packed >> 8;
|
||||
return packed >>> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +89,21 @@ public final 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
|
||||
public ObjectUpdateOperation toUpdateOperation(Region region, EntityUpdateType operation) {
|
||||
return new ObjectUpdateOperation(region, operation, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this GameObject can be seen by the specified {@link Player}.
|
||||
*
|
||||
* @param player The Player.
|
||||
* @return {@code true} if the Player can see this GameObject, {@code false} if not.
|
||||
*/
|
||||
public abstract boolean viewableBy(Player player);
|
||||
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package org.apollo.game.model.area.obj;
|
||||
package org.apollo.game.model.entity.obj;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -21,7 +21,7 @@ public enum ObjectGroup {
|
||||
WALL_DECORATION(1),
|
||||
|
||||
/**
|
||||
* The interactable object group, for objects that can be clicked and interacted with.
|
||||
* The interactable object group, for objects that can be clicked and interacted with. TODO rename
|
||||
*/
|
||||
INTERACTABLE_OBJECT(2),
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.apollo.game.model.area.obj;
|
||||
package org.apollo.game.model.entity.obj;
|
||||
|
||||
/**
|
||||
* The type of an object, which affects specified behaviour (such as whether it displaces existing objects). TODO
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.apollo.game.model.entity.obj;
|
||||
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.area.RegionCoordinates;
|
||||
import org.apollo.game.model.area.RegionRepository;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
|
||||
/**
|
||||
* A {@link GameObject} that is a static part of the game world (i.e. is stored in the game resources).
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class StaticGameObject extends GameObject {
|
||||
|
||||
/**
|
||||
* Creates the StaticGameObject.
|
||||
*
|
||||
* @param id The id of the StaticGameObject
|
||||
* @param position The {@link Position} of the StaticGameObject.
|
||||
* @param type The type code of the StaticGameObject.
|
||||
* @param orientation The orientation of the StaticGameObject.
|
||||
*/
|
||||
public StaticGameObject(int id, Position position, int type, int orientation) {
|
||||
super(id, position, type, orientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityType getEntityType() {
|
||||
return EntityType.STATIC_OBJECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean viewableBy(Player player) {
|
||||
RegionRepository repository = World.getWorld().getRegionRepository();
|
||||
RegionCoordinates coordinates = position.getRegionCoordinates();
|
||||
|
||||
return repository.get(coordinates).contains(this);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* Contains object-related classes.
|
||||
*/
|
||||
package org.apollo.game.model.area.obj;
|
||||
package org.apollo.game.model.entity.obj;
|
||||
@@ -1,12 +1,17 @@
|
||||
package org.apollo.game.sync;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Phaser;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.apollo.game.GameService;
|
||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.area.RegionCoordinates;
|
||||
import org.apollo.game.model.entity.Npc;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.sync.task.NpcSynchronizationTask;
|
||||
@@ -59,9 +64,12 @@ public final class ParallelClientSynchronizer extends ClientSynchronizer {
|
||||
int playerCount = players.size();
|
||||
int npcCount = npcs.size();
|
||||
|
||||
Map<RegionCoordinates, List<RegionUpdateMessage>> updates = new HashMap<>();
|
||||
Map<RegionCoordinates, List<RegionUpdateMessage>> snapshots = new HashMap<>();
|
||||
|
||||
phaser.bulkRegister(playerCount);
|
||||
for (Player player : players) {
|
||||
SynchronizationTask task = new PrePlayerSynchronizationTask(player);
|
||||
SynchronizationTask task = new PrePlayerSynchronizationTask(player, updates, snapshots);
|
||||
executor.submit(new PhasedSynchronizationTask(phaser, task));
|
||||
}
|
||||
phaser.arriveAndAwaitAdvance();
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
package org.apollo.game.sync;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apollo.game.GameService;
|
||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.area.RegionCoordinates;
|
||||
import org.apollo.game.model.entity.Npc;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.sync.task.NpcSynchronizationTask;
|
||||
@@ -29,8 +35,11 @@ public final class SequentialClientSynchronizer extends ClientSynchronizer {
|
||||
MobRepository<Player> players = World.getWorld().getPlayerRepository();
|
||||
MobRepository<Npc> npcs = World.getWorld().getNpcRepository();
|
||||
|
||||
Map<RegionCoordinates, List<RegionUpdateMessage>> updates = new HashMap<>();
|
||||
Map<RegionCoordinates, List<RegionUpdateMessage>> snapshots = new HashMap<>();
|
||||
|
||||
for (Player player : players) {
|
||||
SynchronizationTask task = new PrePlayerSynchronizationTask(player);
|
||||
SynchronizationTask task = new PrePlayerSynchronizationTask(player, updates, snapshots);
|
||||
task.run();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +1,207 @@
|
||||
package org.apollo.game.sync.task;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apollo.game.message.impl.ClearRegionMessage;
|
||||
import org.apollo.game.message.impl.GroupedRegionUpdateMessage;
|
||||
import org.apollo.game.message.impl.RegionChangeMessage;
|
||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.area.Region;
|
||||
import org.apollo.game.model.area.RegionCoordinates;
|
||||
import org.apollo.game.model.area.RegionRepository;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* A {@link SynchronizationTask} which does pre-synchronization work for the specified {@link Player}.
|
||||
*
|
||||
* @author Graham
|
||||
* @author Major
|
||||
*/
|
||||
public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
|
||||
/**
|
||||
* The update mode used when sending a {@link GroupedRegionUpdateMessage}.
|
||||
*/
|
||||
private enum RegionUpdateMode {
|
||||
|
||||
/**
|
||||
* The difference update mode, which only sends updates for changes that have occurred in the last pulse.
|
||||
*/
|
||||
DIFFERENCE,
|
||||
|
||||
/**
|
||||
* The full update mode, which sends everything in the Region.
|
||||
*/
|
||||
FULL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount of Regions that are in view of a player, in one direction.
|
||||
*/
|
||||
private static final int REGION_COUNT = (int) Math.ceil(Position.MAX_DISTANCE / Region.SIZE);
|
||||
|
||||
/**
|
||||
* The width of the viewport of every Player, in tiles.
|
||||
*/
|
||||
private static final int VIEWPORT_WIDTH = Region.SIZE * 13;
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* Creates the {@link PrePlayerSynchronizationTask} for the specified player.
|
||||
*
|
||||
* @param player The player.
|
||||
* The Map of RegionCoordinates to Sets of RegionUpdateMessages, which contain all of the Entity information for a
|
||||
* Region.
|
||||
*/
|
||||
public PrePlayerSynchronizationTask(Player player) {
|
||||
private final Map<RegionCoordinates, List<RegionUpdateMessage>> snapshots;
|
||||
|
||||
/**
|
||||
* The Map of RegionCoordinates to Sets of RegionUpdateMessages, which contain the updates for a Region a Player can
|
||||
* already view.
|
||||
*/
|
||||
private final Map<RegionCoordinates, List<RegionUpdateMessage>> updates;
|
||||
|
||||
/**
|
||||
* Creates the {@link PrePlayerSynchronizationTask} for the specified {@link Player}.
|
||||
*
|
||||
* @param player The Player.
|
||||
* @param updates The {@link Map} containing {@link Region} updates.
|
||||
* @param snapshots The Map containing Region snapshots.
|
||||
*/
|
||||
public PrePlayerSynchronizationTask(Player player, Map<RegionCoordinates, List<RegionUpdateMessage>> updates,
|
||||
Map<RegionCoordinates, List<RegionUpdateMessage>> snapshots) {
|
||||
this.player = player;
|
||||
this.updates = updates;
|
||||
this.snapshots = snapshots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Position old = player.getPosition();
|
||||
player.getWalkingQueue().pulse();
|
||||
|
||||
RegionUpdateMode mode = RegionUpdateMode.DIFFERENCE;
|
||||
|
||||
if (player.isTeleporting()) {
|
||||
player.resetViewingDistance();
|
||||
mode = RegionUpdateMode.FULL;
|
||||
}
|
||||
|
||||
boolean hasKnownRegion = player.hasLastKnownRegion();
|
||||
if (!hasKnownRegion) {
|
||||
mode = RegionUpdateMode.FULL;
|
||||
}
|
||||
|
||||
if (!hasKnownRegion || isRegionUpdateRequired()) {
|
||||
player.setRegionChanged(true);
|
||||
|
||||
Position position = player.getPosition();
|
||||
player.setLastKnownRegion(position);
|
||||
player.send(new RegionChangeMessage(position));
|
||||
}
|
||||
|
||||
Set<RegionCoordinates> newRegions = getNewRegions(old, player.getPosition());
|
||||
sendRegionUpdates(mode, newRegions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Set} of {@link RegionCoordinates} of {@link Region}s that the {@link Player} in this task has
|
||||
* only just became able to view.
|
||||
*
|
||||
* @param old The old {@link Position} of the Player.
|
||||
* @param next The new Position of the Player.
|
||||
* @return The Set of RegionCoordinates. Will not be {@code null}, but may be empty.
|
||||
*/
|
||||
private Set<RegionCoordinates> getNewRegions(Position old, Position next) {
|
||||
RegionCoordinates oldRegion = old.getRegionCoordinates();
|
||||
RegionCoordinates nextRegion = next.getRegionCoordinates();
|
||||
|
||||
if (oldRegion.equals(nextRegion)) {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
|
||||
Set<RegionCoordinates> coordinates = new HashSet<>(9);
|
||||
int oldX = oldRegion.getX(), oldY = oldRegion.getY();
|
||||
|
||||
int dx = nextRegion.getX() - oldX;
|
||||
int dy = nextRegion.getY() - oldY;
|
||||
|
||||
if (dx != 0) {
|
||||
int x = oldX + dx;
|
||||
int maxY = oldY + REGION_COUNT;
|
||||
|
||||
for (int y = oldY - REGION_COUNT; y <= maxY; y++) {
|
||||
coordinates.add(new RegionCoordinates(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
if (dy != 0) {
|
||||
int y = oldY + dy;
|
||||
int maxX = oldX + REGION_COUNT;
|
||||
|
||||
for (int x = oldX - REGION_COUNT; x <= maxX; x++) {
|
||||
coordinates.add(new RegionCoordinates(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link List} of {@link GroupedRegionUpdateMessage}s.
|
||||
*
|
||||
* @param mode The {@link RegionUpdateMode} used when creating the Messages.
|
||||
* @param newRegions The {@link Set} of {@link RegionCoordinates} that should be sent as a full update.
|
||||
*/
|
||||
private void sendRegionUpdates(RegionUpdateMode mode, Set<RegionCoordinates> newRegions) {
|
||||
Position position = player.getPosition();
|
||||
RegionCoordinates base = position.getRegionCoordinates();
|
||||
int baseX = base.getX(), baseY = base.getY();
|
||||
|
||||
RegionRepository repository = World.getWorld().getRegionRepository();
|
||||
List<GroupedRegionUpdateMessage> messages = new ArrayList<>();
|
||||
|
||||
for (int x = baseX - REGION_COUNT; x <= baseX + REGION_COUNT; x++) {
|
||||
for (int y = baseY - REGION_COUNT; y <= baseY + REGION_COUNT; y++) {
|
||||
RegionCoordinates coordinates = new RegionCoordinates(x, y);
|
||||
|
||||
RegionUpdateMode local = mode;
|
||||
if (mode == RegionUpdateMode.DIFFERENCE && newRegions.contains(coordinates)) {
|
||||
local = RegionUpdateMode.FULL;
|
||||
|
||||
player.send(new ClearRegionMessage(position, coordinates));
|
||||
}
|
||||
|
||||
Optional<GroupedRegionUpdateMessage> message = toUpdateMessage(local, position, coordinates, repository);
|
||||
if (message.isPresent()) {
|
||||
messages.add(message.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messages.size() > 0) {
|
||||
System.out.println("Sending in mode " + mode + ", new regions=" + newRegions);
|
||||
|
||||
}
|
||||
|
||||
messages.forEach(player::send);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a region update is required.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} otherwise.
|
||||
* @return {@code true} if a Region update is required, {@code false} if not.
|
||||
*/
|
||||
private boolean isRegionUpdateRequired() {
|
||||
Position current = player.getPosition();
|
||||
@@ -37,24 +210,59 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
int deltaX = current.getLocalX(last);
|
||||
int deltaY = current.getLocalY(last);
|
||||
|
||||
return deltaX < 16 || deltaX >= 88 || deltaY < 16 || deltaY >= 88;
|
||||
return deltaX <= Position.MAX_DISTANCE || deltaX >= (VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1)
|
||||
|| deltaY <= Position.MAX_DISTANCE || deltaY >= (VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
player.getWalkingQueue().pulse();
|
||||
/**
|
||||
* Creates a {@link GroupedRegionUpdateMessage} using the specified {@link RegionUpdateMode}, returning
|
||||
* {@link Optional#empty()} if no update message is required.
|
||||
*
|
||||
* @param mode The RegionUpdateMode for the Message.
|
||||
* @param position The {@link Position} of the Player.
|
||||
* @param coordinates The {@link RegionCoordinates} of the {@link Region}.
|
||||
* @param repository The {@link RegionRepository} containing the Regions.
|
||||
* @return The Optional containing the GroupedRegionUpdateMessage.
|
||||
*/
|
||||
private Optional<GroupedRegionUpdateMessage> toUpdateMessage(RegionUpdateMode mode, Position position,
|
||||
RegionCoordinates coordinates, RegionRepository repository) {
|
||||
List<RegionUpdateMessage> messages;
|
||||
|
||||
if (player.isTeleporting()) {
|
||||
player.resetViewingDistance();
|
||||
/*
|
||||
* Here we used Map#computeIfAbsent because the value may have been inserted into the Map by another thread
|
||||
* after our Map#get call. This is done in two separate parts (rather than acquiring the lock every time, and
|
||||
* just calling Map#computeIfAbsent immediately) for performance - once the List<RegionUpdateMessage> has been
|
||||
* placed into the Map once, it will never be changed, and is therefore a read-only operation after this. The
|
||||
* alternative, acquiring the lock for every access, would be very slow.
|
||||
*/
|
||||
|
||||
switch (mode) {
|
||||
case DIFFERENCE:
|
||||
messages = updates.get(coordinates);
|
||||
if (messages == null) {
|
||||
synchronized (updates) {
|
||||
messages = updates.computeIfAbsent(coordinates,
|
||||
coords -> repository.get(coords).getUpdates(position.getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case FULL:
|
||||
messages = snapshots.get(coordinates);
|
||||
if (messages == null) {
|
||||
synchronized (snapshots) {
|
||||
messages = snapshots.computeIfAbsent(coordinates,
|
||||
coords -> repository.get(coords).getSnapshot(position.getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unrecognised RegionUpdateMode " + mode + ".");
|
||||
}
|
||||
|
||||
if (!player.hasLastKnownRegion() || isRegionUpdateRequired()) {
|
||||
player.setRegionChanged(true);
|
||||
|
||||
Position position = player.getPosition();
|
||||
player.setLastKnownRegion(position);
|
||||
player.send(new RegionChangeMessage(position));
|
||||
}
|
||||
return messages.isEmpty() ? Optional.empty() : Optional
|
||||
.of(new GroupedRegionUpdateMessage(position, coordinates, messages));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.AddGlobalTileItemMessage;
|
||||
import org.apollo.game.message.impl.SendPublicTileItemMessage;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
@@ -8,14 +8,14 @@ import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link AddGlobalTileItemMessage}.
|
||||
* A {@link MessageEncoder} for the {@link SendPublicTileItemMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class AddGlobalTileItemMessageEncoder extends MessageEncoder<AddGlobalTileItemMessage> {
|
||||
public final class AddGlobalTileItemMessageEncoder extends MessageEncoder<SendPublicTileItemMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(AddGlobalTileItemMessage message) {
|
||||
public GamePacket encode(SendPublicTileItemMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(215);
|
||||
builder.put(DataType.SHORT, DataTransformation.ADD, message.getId());
|
||||
builder.put(DataType.BYTE, DataTransformation.SUBTRACT, message.getPositionOffset());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.AddTileItemMessage;
|
||||
import org.apollo.game.message.impl.SendTileItemMessage;
|
||||
import org.apollo.net.codec.game.DataOrder;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
@@ -9,14 +9,14 @@ import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link AddTileItemMessage}.
|
||||
* A {@link MessageEncoder} for the {@link SendTileItemMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class AddTileItemMessageEncoder extends MessageEncoder<AddTileItemMessage> {
|
||||
public final class AddTileItemMessageEncoder extends MessageEncoder<SendTileItemMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(AddTileItemMessage message) {
|
||||
public GamePacket encode(SendTileItemMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(44);
|
||||
builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getId());
|
||||
builder.put(DataType.SHORT, message.getAmount());
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.ClearRegionMessage;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link ClearRegionMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class ClearRegionMessageEncoder extends MessageEncoder<ClearRegionMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(ClearRegionMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(64);
|
||||
Position player = message.getPlayerPosition(), region = message.getRegionPosition();
|
||||
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, region.getLocalX(player));
|
||||
builder.put(DataType.BYTE, DataTransformation.SUBTRACT, region.getLocalY(player));
|
||||
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.GroupedRegionUpdateMessage;
|
||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.meta.PacketType;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
import org.apollo.net.release.Release;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link GroupedRegionUpdateMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class GroupedRegionUpdateMessageEncoder extends MessageEncoder<GroupedRegionUpdateMessage> {
|
||||
|
||||
/**
|
||||
* The Release containing the MessageEncoders for the RegionUpdateMessages.
|
||||
*/
|
||||
private final Release release;
|
||||
|
||||
/**
|
||||
* Creates the GroupedRegionUpdateMessageEncoder.
|
||||
*
|
||||
* @param release The {@link Release} containing the {@link MessageEncoder}s for the {@link RegionUpdateMessage}s.
|
||||
*/
|
||||
public GroupedRegionUpdateMessageEncoder(Release release) {
|
||||
this.release = release;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GamePacket encode(GroupedRegionUpdateMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(60, PacketType.VARIABLE_SHORT);
|
||||
Position player = message.getPlayerPosition(), region = message.getRegionPosition();
|
||||
|
||||
builder.put(DataType.BYTE, player.getLocalY(region));
|
||||
System.out.println("Grum: local x: " + player.getLocalX(region) + ", local y: " + player.getLocalY(region));
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, player.getLocalX(region));
|
||||
|
||||
for (RegionUpdateMessage update : message.getMessages()) {
|
||||
System.out.println("==== Sending " + update + " as part of grum");
|
||||
@SuppressWarnings("unchecked")
|
||||
MessageEncoder<RegionUpdateMessage> encoder = (MessageEncoder<RegionUpdateMessage>) release.getMessageEncoder(update
|
||||
.getClass());
|
||||
|
||||
GamePacket packet = encoder.encode(update);
|
||||
builder.put(DataType.BYTE, packet.getOpcode());
|
||||
builder.putBytes(packet.getPayload());
|
||||
}
|
||||
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.PositionMessage;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link PositionMessage}.
|
||||
*
|
||||
* @author Chris Fletcher
|
||||
*/
|
||||
final class PositionMessageEncoder extends MessageEncoder<PositionMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(PositionMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(85);
|
||||
Position base = message.getBase(), pos = message.getPosition();
|
||||
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, pos.getLocalY(base));
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, pos.getLocalX(base));
|
||||
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.AddGlobalTileItemMessage;
|
||||
import org.apollo.game.message.impl.AddTileItemMessage;
|
||||
import org.apollo.game.message.impl.ClearRegionMessage;
|
||||
import org.apollo.game.message.impl.CloseInterfaceMessage;
|
||||
import org.apollo.game.message.impl.ConfigMessage;
|
||||
import org.apollo.game.message.impl.DisplayCrossbonesMessage;
|
||||
@@ -10,6 +9,7 @@ import org.apollo.game.message.impl.EnterAmountMessage;
|
||||
import org.apollo.game.message.impl.FlashTabInterfaceMessage;
|
||||
import org.apollo.game.message.impl.ForwardPrivateChatMessage;
|
||||
import org.apollo.game.message.impl.FriendServerStatusMessage;
|
||||
import org.apollo.game.message.impl.GroupedRegionUpdateMessage;
|
||||
import org.apollo.game.message.impl.HintIconMessage;
|
||||
import org.apollo.game.message.impl.IdAssignmentMessage;
|
||||
import org.apollo.game.message.impl.IgnoreListMessage;
|
||||
@@ -22,15 +22,17 @@ import org.apollo.game.message.impl.OpenInterfaceSidebarMessage;
|
||||
import org.apollo.game.message.impl.OpenOverlayMessage;
|
||||
import org.apollo.game.message.impl.OpenSidebarMessage;
|
||||
import org.apollo.game.message.impl.PlayerSynchronizationMessage;
|
||||
import org.apollo.game.message.impl.PositionMessage;
|
||||
import org.apollo.game.message.impl.PrivacyOptionMessage;
|
||||
import org.apollo.game.message.impl.RegionChangeMessage;
|
||||
import org.apollo.game.message.impl.RemoveObjectMessage;
|
||||
import org.apollo.game.message.impl.RemoveTileItemMessage;
|
||||
import org.apollo.game.message.impl.RegionChangeMessage;
|
||||
import org.apollo.game.message.impl.SendFriendMessage;
|
||||
import org.apollo.game.message.impl.SendObjectMessage;
|
||||
import org.apollo.game.message.impl.SendPublicTileItemMessage;
|
||||
import org.apollo.game.message.impl.SendTileItemMessage;
|
||||
import org.apollo.game.message.impl.ServerChatMessage;
|
||||
import org.apollo.game.message.impl.SetPlayerActionMessage;
|
||||
import org.apollo.game.message.impl.SetUpdatedRegionMessage;
|
||||
import org.apollo.game.message.impl.SetWidgetItemModelMessage;
|
||||
import org.apollo.game.message.impl.SetWidgetModelAnimationMessage;
|
||||
import org.apollo.game.message.impl.SetWidgetNpcModelMessage;
|
||||
@@ -194,7 +196,7 @@ public final class Release317 extends Release {
|
||||
register(SetWidgetModelAnimationMessage.class, new SetWidgetModelAnimationMessageEncoder());
|
||||
register(ConfigMessage.class, new ConfigMessageEncoder());
|
||||
register(DisplayTabInterfaceMessage.class, new DisplayTabInterfaceMessageEncoder());
|
||||
register(PositionMessage.class, new PositionMessageEncoder());
|
||||
register(SetUpdatedRegionMessage.class, new SetUpdatedRegionMessageEncoder());
|
||||
register(UpdateRunEnergyMessage.class, new UpdateRunEnergyMessageEncoder());
|
||||
register(PrivacyOptionMessage.class, new PrivacyOptionMessageEncoder());
|
||||
register(OpenDialogueInterfaceMessage.class, new OpenDialogueInterfaceMessageEncoder());
|
||||
@@ -202,13 +204,16 @@ public final class Release317 extends Release {
|
||||
register(SetPlayerActionMessage.class, new SetPlayerActionMessageEncoder());
|
||||
register(DisplayCrossbonesMessage.class, new DisplayCrossbonesMessageEncoder());
|
||||
|
||||
register(AddGlobalTileItemMessage.class, new AddGlobalTileItemMessageEncoder());
|
||||
register(AddTileItemMessage.class, new AddTileItemMessageEncoder());
|
||||
register(SendPublicTileItemMessage.class, new AddGlobalTileItemMessageEncoder());
|
||||
register(SendTileItemMessage.class, new AddTileItemMessageEncoder());
|
||||
register(UpdateTileItemMessage.class, new UpdateTileItemMessageEncoder());
|
||||
register(RemoveTileItemMessage.class, new RemoveTileItemMessageEncoder());
|
||||
register(SendObjectMessage.class, new SendObjectMessageEncoder());
|
||||
register(RemoveObjectMessage.class, new RemoveObjectMessageEncoder());
|
||||
|
||||
register(GroupedRegionUpdateMessage.class, new GroupedRegionUpdateMessageEncoder(this));
|
||||
register(ClearRegionMessage.class, new ClearRegionMessageEncoder());
|
||||
|
||||
register(ForwardPrivateChatMessage.class, new ForwardPrivateChatMessageEncoder());
|
||||
register(FriendServerStatusMessage.class, new FriendServerStatusMessageEncoder());
|
||||
register(IgnoreListMessage.class, new IgnoreListMessageEncoder());
|
||||
|
||||
@@ -19,6 +19,9 @@ public final class RemoveObjectMessageEncoder extends MessageEncoder<RemoveObjec
|
||||
GamePacketBuilder builder = new GamePacketBuilder(101);
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, message.getType() << 2 | message.getOrientation());
|
||||
builder.put(DataType.BYTE, message.getPositionOffset());
|
||||
|
||||
System.out.println("Sending rm obj: type=" + message.getType() + ", orient=" + message.getOrientation() + ",posoff="
|
||||
+ Integer.toBinaryString(message.getPositionOffset()));
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.SetUpdatedRegionMessage;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link SetUpdatedRegionMessage}.
|
||||
*
|
||||
* @author Chris Fletcher
|
||||
*/
|
||||
final class SetUpdatedRegionMessageEncoder extends MessageEncoder<SetUpdatedRegionMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(SetUpdatedRegionMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(85);
|
||||
Position player = message.getPlayerPosition(), region = message.getRegionPosition();
|
||||
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, region.getLocalY(player));
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, region.getLocalX(player));
|
||||
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.AddGlobalTileItemMessage;
|
||||
import org.apollo.game.message.impl.SendPublicTileItemMessage;
|
||||
import org.apollo.net.codec.game.DataOrder;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
@@ -9,14 +9,14 @@ import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link AddGlobalTileItemMessage}.
|
||||
* A {@link MessageEncoder} for the {@link SendPublicTileItemMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class AddGlobalTileItemMessageEncoder extends MessageEncoder<AddGlobalTileItemMessage> {
|
||||
public final class AddGlobalTileItemMessageEncoder extends MessageEncoder<SendPublicTileItemMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(AddGlobalTileItemMessage message) {
|
||||
public GamePacket encode(SendPublicTileItemMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(106);
|
||||
builder.put(DataType.BYTE, DataTransformation.ADD, message.getPositionOffset());
|
||||
builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getAmount());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.AddTileItemMessage;
|
||||
import org.apollo.game.message.impl.SendTileItemMessage;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
@@ -8,14 +8,14 @@ import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link AddTileItemMessage}.
|
||||
* A {@link MessageEncoder} for the {@link SendTileItemMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class AddTileItemMessageEncoder extends MessageEncoder<AddTileItemMessage> {
|
||||
public final class AddTileItemMessageEncoder extends MessageEncoder<SendTileItemMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(AddTileItemMessage message) {
|
||||
public GamePacket encode(SendTileItemMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(107);
|
||||
builder.put(DataType.SHORT, message.getId());
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, message.getPositionOffset());
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.ClearRegionMessage;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link ClearRegionMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class ClearRegionMessageEncoder extends MessageEncoder<ClearRegionMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(ClearRegionMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(40);
|
||||
Position player = message.getPlayerPosition(), region = message.getRegionPosition();
|
||||
|
||||
builder.put(DataType.BYTE, DataTransformation.SUBTRACT, region.getLocalY(player));
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, region.getLocalX(player));
|
||||
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apollo.game.message.impl.GroupedRegionUpdateMessage;
|
||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.meta.PacketType;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link GroupedRegionUpdateMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class GroupedRegionUpdateMessageEncoder extends MessageEncoder<GroupedRegionUpdateMessage> {
|
||||
|
||||
/**
|
||||
* The Map of RegionUpdateMessages to MessageEncoders.
|
||||
*/
|
||||
private final Map<Class<? extends RegionUpdateMessage>, MessageEncoder<? extends RegionUpdateMessage>> encoders;
|
||||
|
||||
/**
|
||||
* Creates the GroupedRegionUpdateMessageEncoder.
|
||||
*
|
||||
* @param encoders The Map of RegionUpdateMessages to MessageEncoders.
|
||||
*/
|
||||
public GroupedRegionUpdateMessageEncoder(
|
||||
Map<Class<? extends RegionUpdateMessage>, MessageEncoder<? extends RegionUpdateMessage>> encoders) {
|
||||
this.encoders = ImmutableMap.copyOf(encoders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GamePacket encode(GroupedRegionUpdateMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(183, PacketType.VARIABLE_SHORT);
|
||||
Position base = message.getPlayerPosition(), region = message.getRegionPosition();
|
||||
|
||||
builder.put(DataType.BYTE, region.getLocalX(base));
|
||||
builder.put(DataType.BYTE, DataTransformation.ADD, region.getLocalY(base));
|
||||
|
||||
for (RegionUpdateMessage update : message.getMessages()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
MessageEncoder<RegionUpdateMessage> encoder = (MessageEncoder<RegionUpdateMessage>) encoders.get(update);
|
||||
|
||||
Preconditions.checkState(encoder != null, update.getClass()
|
||||
+ " does not have a registered encoder in GroupedRegionUpdateMessageEncoder.");
|
||||
|
||||
GamePacket packet = encoder.encode(update);
|
||||
builder.put(DataType.BYTE, packet.getOpcode());
|
||||
builder.putBytes(packet.getPayload());
|
||||
}
|
||||
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.PositionMessage;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link PositionMessage}.
|
||||
*
|
||||
* @author Chris Fletcher
|
||||
* @author Major
|
||||
*/
|
||||
public final class PositionMessageEncoder extends MessageEncoder<PositionMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(PositionMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(75);
|
||||
Position base = message.getBase(), pos = message.getPosition();
|
||||
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, pos.getLocalX(base));
|
||||
builder.put(DataType.BYTE, DataTransformation.ADD, pos.getLocalY(base));
|
||||
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.AddGlobalTileItemMessage;
|
||||
import org.apollo.game.message.impl.AddTileItemMessage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apollo.game.message.impl.ClearRegionMessage;
|
||||
import org.apollo.game.message.impl.CloseInterfaceMessage;
|
||||
import org.apollo.game.message.impl.ConfigMessage;
|
||||
import org.apollo.game.message.impl.DisplayCrossbonesMessage;
|
||||
@@ -10,6 +12,7 @@ import org.apollo.game.message.impl.EnterAmountMessage;
|
||||
import org.apollo.game.message.impl.FlashTabInterfaceMessage;
|
||||
import org.apollo.game.message.impl.ForwardPrivateChatMessage;
|
||||
import org.apollo.game.message.impl.FriendServerStatusMessage;
|
||||
import org.apollo.game.message.impl.GroupedRegionUpdateMessage;
|
||||
import org.apollo.game.message.impl.HintIconMessage;
|
||||
import org.apollo.game.message.impl.IdAssignmentMessage;
|
||||
import org.apollo.game.message.impl.IgnoreListMessage;
|
||||
@@ -22,15 +25,18 @@ import org.apollo.game.message.impl.OpenInterfaceSidebarMessage;
|
||||
import org.apollo.game.message.impl.OpenOverlayMessage;
|
||||
import org.apollo.game.message.impl.OpenSidebarMessage;
|
||||
import org.apollo.game.message.impl.PlayerSynchronizationMessage;
|
||||
import org.apollo.game.message.impl.PositionMessage;
|
||||
import org.apollo.game.message.impl.PrivacyOptionMessage;
|
||||
import org.apollo.game.message.impl.RegionChangeMessage;
|
||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
||||
import org.apollo.game.message.impl.RemoveObjectMessage;
|
||||
import org.apollo.game.message.impl.RemoveTileItemMessage;
|
||||
import org.apollo.game.message.impl.RegionChangeMessage;
|
||||
import org.apollo.game.message.impl.SendFriendMessage;
|
||||
import org.apollo.game.message.impl.SendObjectMessage;
|
||||
import org.apollo.game.message.impl.SendPublicTileItemMessage;
|
||||
import org.apollo.game.message.impl.SendTileItemMessage;
|
||||
import org.apollo.game.message.impl.ServerChatMessage;
|
||||
import org.apollo.game.message.impl.SetPlayerActionMessage;
|
||||
import org.apollo.game.message.impl.SetUpdatedRegionMessage;
|
||||
import org.apollo.game.message.impl.SetWidgetItemModelMessage;
|
||||
import org.apollo.game.message.impl.SetWidgetModelAnimationMessage;
|
||||
import org.apollo.game.message.impl.SetWidgetNpcModelMessage;
|
||||
@@ -45,6 +51,7 @@ import org.apollo.game.message.impl.UpdateSlottedItemsMessage;
|
||||
import org.apollo.game.message.impl.UpdateTileItemMessage;
|
||||
import org.apollo.game.message.impl.UpdateWeightMessage;
|
||||
import org.apollo.net.meta.PacketMetaDataGroup;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
import org.apollo.net.release.Release;
|
||||
|
||||
/**
|
||||
@@ -190,7 +197,7 @@ public final class Release377 extends Release {
|
||||
register(SetWidgetModelAnimationMessage.class, new SetWidgetModelAnimationMessageEncoder());
|
||||
register(ConfigMessage.class, new ConfigMessageEncoder());
|
||||
register(DisplayTabInterfaceMessage.class, new DisplayTabInterfaceMessageEncoder());
|
||||
register(PositionMessage.class, new PositionMessageEncoder());
|
||||
register(SetUpdatedRegionMessage.class, new SetUpdatedRegionMessageEncoder());
|
||||
register(UpdateRunEnergyMessage.class, new UpdateRunEnergyMessageEncoder());
|
||||
register(PrivacyOptionMessage.class, new PrivacyOptionMessageEncoder());
|
||||
register(OpenDialogueInterfaceMessage.class, new OpenDialogueInterfaceMessageEncoder());
|
||||
@@ -198,13 +205,35 @@ public final class Release377 extends Release {
|
||||
register(SetPlayerActionMessage.class, new SetPlayerActionMessageEncoder());
|
||||
register(DisplayCrossbonesMessage.class, new DisplayCrossbonesMessageEncoder());
|
||||
|
||||
register(AddGlobalTileItemMessage.class, new AddGlobalTileItemMessageEncoder());
|
||||
register(AddTileItemMessage.class, new AddTileItemMessageEncoder());
|
||||
register(SendPublicTileItemMessage.class, new AddGlobalTileItemMessageEncoder());
|
||||
register(SendTileItemMessage.class, new AddTileItemMessageEncoder());
|
||||
register(UpdateTileItemMessage.class, new UpdateTileItemMessageEncoder());
|
||||
register(RemoveTileItemMessage.class, new RemoveTileItemMessageEncoder());
|
||||
register(SendObjectMessage.class, new SendObjectMessageEncoder());
|
||||
register(RemoveObjectMessage.class, new RemoveObjectMessageEncoder());
|
||||
|
||||
Map<Class<? extends RegionUpdateMessage>, MessageEncoder<? extends RegionUpdateMessage>> regionUpdates = new HashMap<>();
|
||||
|
||||
regionUpdates.put(SendPublicTileItemMessage.class, new AddGlobalTileItemMessageEncoder());
|
||||
regionUpdates.put(SendTileItemMessage.class, new AddTileItemMessageEncoder());
|
||||
regionUpdates.put(UpdateTileItemMessage.class, new UpdateTileItemMessageEncoder());
|
||||
regionUpdates.put(RemoveTileItemMessage.class, new RemoveTileItemMessageEncoder());
|
||||
regionUpdates.put(SendObjectMessage.class, new SendObjectMessageEncoder());
|
||||
regionUpdates.put(RemoveObjectMessage.class, new RemoveObjectMessageEncoder());
|
||||
|
||||
for (Map.Entry<Class<? extends RegionUpdateMessage>, MessageEncoder<? extends RegionUpdateMessage>> entry : regionUpdates
|
||||
.entrySet()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<RegionUpdateMessage> clazz = (Class<RegionUpdateMessage>) entry.getKey();
|
||||
@SuppressWarnings("unchecked")
|
||||
MessageEncoder<RegionUpdateMessage> encoder = (MessageEncoder<RegionUpdateMessage>) entry.getValue();
|
||||
|
||||
register(clazz, encoder);
|
||||
}
|
||||
|
||||
register(GroupedRegionUpdateMessage.class, new GroupedRegionUpdateMessageEncoder(regionUpdates));
|
||||
register(ClearRegionMessage.class, new ClearRegionMessageEncoder());
|
||||
|
||||
register(ForwardPrivateChatMessage.class, new ForwardPrivateChatMessageEncoder());
|
||||
register(FriendServerStatusMessage.class, new FriendServerStatusMessageEncoder());
|
||||
register(IgnoreListMessage.class, new IgnoreListMessageEncoder());
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.SetUpdatedRegionMessage;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link SetUpdatedRegionMessage}.
|
||||
*
|
||||
* @author Chris Fletcher
|
||||
* @author Major
|
||||
*/
|
||||
public final class SetUpdatedRegionMessageEncoder extends MessageEncoder<SetUpdatedRegionMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(SetUpdatedRegionMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(75);
|
||||
Position base = message.getPlayerPosition(), position = message.getRegionPosition();
|
||||
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, position.getLocalX(base));
|
||||
builder.put(DataType.BYTE, DataTransformation.ADD, position.getLocalY(base));
|
||||
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import com.mchange.v2.c3p0.ComboPooledDataSource;
|
||||
import org.apollo.util.xml.XmlNode;
|
||||
import org.apollo.util.xml.XmlParser;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Stuart
|
||||
*/
|
||||
public final class DatabaseUtil {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final ComboPooledDataSource pool = new ComboPooledDataSource();
|
||||
|
||||
static {
|
||||
try(InputStream is = new FileInputStream("data/database.xml")) {
|
||||
XmlNode config = new XmlParser().parse(is);
|
||||
if(!config.getName().equals("database")) {
|
||||
throw new IOException("Root node is not 'database'.");
|
||||
}
|
||||
|
||||
XmlNode url = config.getChild("url"), username = config.getChild("username"), password = config.getChild("password");
|
||||
if(url == null || username == null || password == null) {
|
||||
throw new IOException("Root node must contain these three children - 'url', 'username', 'password'.");
|
||||
}
|
||||
|
||||
pool.setJdbcUrl(url.getValue());
|
||||
pool.setUser(username.getValue());
|
||||
pool.setPassword(password.getValue());
|
||||
|
||||
// optional params
|
||||
XmlNode initialPoolSize = config.getChild("initial_pool_size"), acquireIncrement = config.getChild("acquire_increment"),
|
||||
maxPoolSize = config.getChild("max_pool_size"), minPoolSize = config.getChild("min_pool_size");
|
||||
|
||||
if(initialPoolSize != null) {
|
||||
pool.setInitialPoolSize(Integer.parseInt(initialPoolSize.getValue()));
|
||||
}
|
||||
if(acquireIncrement != null) {
|
||||
pool.setAcquireIncrement(Integer.parseInt(acquireIncrement.getValue()));
|
||||
}
|
||||
if(maxPoolSize != null) {
|
||||
pool.setMaxPoolSize(Integer.parseInt(maxPoolSize.getValue()));
|
||||
}
|
||||
if(minPoolSize != null) {
|
||||
pool.setMinPoolSize(Integer.parseInt(minPoolSize.getValue()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static Connection getConnection() throws SQLException {
|
||||
return pool.getConnection();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user