mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-03 00:38:21 +00:00
Fix travelback implementation.
This commit is contained in:
@@ -13,7 +13,7 @@ import org.apollo.game.service.GameService;
|
||||
public final class GamePulseHandler implements Runnable {
|
||||
|
||||
/**
|
||||
* The logger for this class.
|
||||
* The Logger for this class.
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger(GamePulseHandler.class.getName());
|
||||
|
||||
@@ -23,7 +23,7 @@ public final class GamePulseHandler implements Runnable {
|
||||
private final GameService service;
|
||||
|
||||
/**
|
||||
* Creates the game pulse handler object.
|
||||
* Creates the GamePulseHandler.
|
||||
*
|
||||
* @param service The {@link GameService}.
|
||||
*/
|
||||
@@ -35,8 +35,8 @@ public final class GamePulseHandler implements Runnable {
|
||||
public void run() {
|
||||
try {
|
||||
service.pulse();
|
||||
} catch (Throwable reason) {
|
||||
logger.log(Level.SEVERE, "Exception occured during pulse!", reason);
|
||||
} catch (Throwable throwable) {
|
||||
logger.log(Level.SEVERE, "Exception occurred during pulse!", throwable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,15 +30,13 @@ public final class WalkMessageHandler extends MessageHandler<WalkMessage> {
|
||||
for (int index = 0; index < steps.length; index++) {
|
||||
Position step = steps[index];
|
||||
if (index == 0) {
|
||||
if (!queue.addFirstStep(step)) {
|
||||
return; // ignore packet
|
||||
}
|
||||
queue.addFirstStep(step);
|
||||
} else {
|
||||
queue.addStep(step);
|
||||
}
|
||||
}
|
||||
|
||||
queue.setRunningQueue(message.isRunning() || player.isRunning());
|
||||
queue.setRunning(message.isRunning() || player.isRunning());
|
||||
player.getInterfaceSet().close();
|
||||
|
||||
if (queue.size() > 0) {
|
||||
|
||||
@@ -58,48 +58,43 @@ public enum Direction {
|
||||
public static final Direction[] EMPTY_DIRECTION_ARRAY = new Direction[0];
|
||||
|
||||
/**
|
||||
* Creates a direction from the differences between X and Y.
|
||||
* Gets the Direction between the two {@link Position}s..
|
||||
*
|
||||
* @param deltaX The difference between two X coordinates.
|
||||
* @param deltaY The difference between two Y coordinates.
|
||||
* @param current The difference between two X coordinates.
|
||||
* @param next The difference between two Y coordinates.
|
||||
* @return The direction.
|
||||
*/
|
||||
public static Direction fromDeltas(int deltaX, int deltaY) {
|
||||
public static Direction between(Position current, Position next) {
|
||||
int deltaX = next.getX() - current.getX();
|
||||
int deltaY = next.getY() - current.getY();
|
||||
|
||||
if (deltaY == 1) {
|
||||
if (deltaX == 1) {
|
||||
return Direction.NORTH_EAST;
|
||||
return NORTH_EAST;
|
||||
} else if (deltaX == 0) {
|
||||
return Direction.NORTH;
|
||||
return NORTH;
|
||||
} else if (deltaX == -1) {
|
||||
return NORTH_WEST;
|
||||
}
|
||||
return Direction.NORTH_WEST;
|
||||
} else if (deltaY == -1) {
|
||||
if (deltaX == 1) {
|
||||
return Direction.SOUTH_EAST;
|
||||
return SOUTH_EAST;
|
||||
} else if (deltaX == 0) {
|
||||
return Direction.SOUTH;
|
||||
}
|
||||
return Direction.SOUTH_WEST;
|
||||
} else {
|
||||
if (deltaX == 1) {
|
||||
return Direction.EAST;
|
||||
return SOUTH;
|
||||
} else if (deltaX == -1) {
|
||||
return Direction.WEST;
|
||||
return SOUTH_WEST;
|
||||
}
|
||||
} else if (deltaY == 0) {
|
||||
if (deltaX == 1) {
|
||||
return EAST;
|
||||
} else if (deltaX == 0) {
|
||||
return NONE;
|
||||
} else if (deltaX == -1) {
|
||||
return WEST;
|
||||
}
|
||||
}
|
||||
|
||||
return Direction.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the direction represented by the two delta values can connect two points together in a single
|
||||
* direction.
|
||||
*
|
||||
* @param deltaX The difference in X coordinates.
|
||||
* @param deltaY The difference in X coordinates.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public static boolean isConnectable(int deltaX, int deltaY) {
|
||||
return Math.abs(deltaX) == Math.abs(deltaY) || deltaX == 0 || deltaY == 0;
|
||||
throw new IllegalArgumentException("Difference between Positions must be [-1, 1].");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +107,7 @@ public enum Direction {
|
||||
*
|
||||
* @param intValue The direction as an integer.
|
||||
*/
|
||||
private Direction(int intValue) {
|
||||
Direction(int intValue) {
|
||||
this.intValue = intValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,16 +67,36 @@ public final class Player extends Mob {
|
||||
AttributeMap.define("run_energy", AttributeDefinition.forInt(100, AttributePersistence.PERSISTENT));
|
||||
}
|
||||
|
||||
/**
|
||||
* The player's appearance.
|
||||
*/
|
||||
private Appearance appearance = Appearance.DEFAULT_APPEARANCE;
|
||||
|
||||
/**
|
||||
* This player's bank.
|
||||
*/
|
||||
private final Inventory bank = new Inventory(InventoryConstants.BANK_CAPACITY, StackMode.STACK_ALWAYS);
|
||||
|
||||
/**
|
||||
* This player's credentials.
|
||||
*/
|
||||
private final PlayerCredentials credentials;
|
||||
|
||||
/**
|
||||
* This player's interface set.
|
||||
*/
|
||||
private final InterfaceSet interfaceSet = new InterfaceSet(this);
|
||||
|
||||
/**
|
||||
* The Set of DynamicGameObjects that are visible to this Player.
|
||||
*/
|
||||
private final Set<DynamicGameObject> localObjects = new HashSet<>();
|
||||
|
||||
/**
|
||||
* A temporary queue of messages sent during the login process.
|
||||
*/
|
||||
private final Deque<Message> queuedMessages = new ArrayDeque<>();
|
||||
|
||||
/**
|
||||
* The player's appearance.
|
||||
*/
|
||||
private Appearance appearance = Appearance.DEFAULT_APPEARANCE;
|
||||
|
||||
/**
|
||||
* The privacy state of this player's public chat.
|
||||
*/
|
||||
@@ -87,11 +107,6 @@ public final class Player extends Mob {
|
||||
*/
|
||||
private Deque<Point> clicks = new ArrayDeque<>();
|
||||
|
||||
/**
|
||||
* This player's credentials.
|
||||
*/
|
||||
private final PlayerCredentials credentials;
|
||||
|
||||
/**
|
||||
* A flag which indicates there are npcs that couldn't be added.
|
||||
*/
|
||||
@@ -122,11 +137,6 @@ public final class Player extends Mob {
|
||||
*/
|
||||
private List<String> ignores = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* This player's interface set.
|
||||
*/
|
||||
private final InterfaceSet interfaceSet = new InterfaceSet(this);
|
||||
|
||||
/**
|
||||
* Whether or not the player is skulled.
|
||||
*/
|
||||
@@ -137,11 +147,6 @@ public final class Player extends Mob {
|
||||
*/
|
||||
private Position lastKnownRegion;
|
||||
|
||||
/**
|
||||
* The Set of DynamicGameObjects that are visible to this Player.
|
||||
*/
|
||||
private final Set<DynamicGameObject> localObjects = new HashSet<>();
|
||||
|
||||
/**
|
||||
* The MembershipStatus of this Player.
|
||||
*/
|
||||
@@ -157,11 +162,6 @@ public final class Player extends Mob {
|
||||
*/
|
||||
private PrivilegeLevel privilegeLevel = PrivilegeLevel.STANDARD;
|
||||
|
||||
/**
|
||||
* A temporary queue of messages sent during the login process.
|
||||
*/
|
||||
private final Deque<Message> queuedMessages = new ArrayDeque<>();
|
||||
|
||||
/**
|
||||
* A flag indicating if the region changed in the last cycle.
|
||||
*/
|
||||
@@ -506,11 +506,6 @@ public final class Player extends Mob {
|
||||
return worldId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return credentials.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the player with the specified username is on this player's ignore list.
|
||||
*
|
||||
@@ -539,6 +534,11 @@ public final class Player extends Mob {
|
||||
return regionChanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return credentials.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments this player's viewing distance if it is less than the maximum viewing distance.
|
||||
*/
|
||||
@@ -790,15 +790,6 @@ public final class Player extends Mob {
|
||||
this.chatPrivacy = chatPrivacy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value denoting the client's modified version.
|
||||
*
|
||||
* @param version The client version.
|
||||
*/
|
||||
public void setClientVersion(int version) {
|
||||
attributes.set("client_version", new NumericalAttribute(version));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the friend {@link PrivacyState}.
|
||||
*
|
||||
@@ -939,6 +930,12 @@ public final class Player extends Mob {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("username", getUsername()).add("privilege", privilegeLevel)
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the message filter.
|
||||
*
|
||||
@@ -953,16 +950,10 @@ public final class Player extends Mob {
|
||||
*/
|
||||
public void toggleRunning() {
|
||||
running = !running;
|
||||
walkingQueue.setRunningQueue(running);
|
||||
walkingQueue.setRunning(running);
|
||||
send(new ConfigMessage(173, running ? 1 : 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("username", getUsername()).add("privilege", privilegeLevel)
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises this player.
|
||||
*/
|
||||
|
||||
@@ -7,8 +7,6 @@ import java.util.Queue;
|
||||
import org.apollo.game.model.Direction;
|
||||
import org.apollo.game.model.Position;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
/**
|
||||
* A queue of {@link Direction}s which a {@link Mob} will follow.
|
||||
*
|
||||
@@ -17,162 +15,167 @@ import com.google.common.base.MoreObjects;
|
||||
public final class WalkingQueue {
|
||||
|
||||
/**
|
||||
* Represents a single point in the queue.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
private static final class Point {
|
||||
|
||||
/**
|
||||
* The direction to walk to this point.
|
||||
*/
|
||||
private final Direction direction;
|
||||
|
||||
/**
|
||||
* The point's position.
|
||||
*/
|
||||
private final Position position;
|
||||
|
||||
/**
|
||||
* Creates a point.
|
||||
*
|
||||
* @param position The position.
|
||||
* @param direction The direction.
|
||||
*/
|
||||
public Point(Position position, Direction direction) {
|
||||
this.position = position;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("direction", direction).add("position", position)
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum size of the queue. If any additional steps are added, they are discarded.
|
||||
*/
|
||||
private static final int MAXIMUM_SIZE = 128;
|
||||
|
||||
/**
|
||||
* The mob whose walking queue this is.
|
||||
* The Mob this WalkingQueue belongs to.
|
||||
*/
|
||||
private final Mob mob;
|
||||
|
||||
/**
|
||||
* The old queue of directions.
|
||||
* The Deque of active points in this WalkingQueue.
|
||||
*/
|
||||
private final Deque<Point> oldPoints = new ArrayDeque<>();
|
||||
private final Deque<Position> points = new ArrayDeque<>();
|
||||
|
||||
/**
|
||||
* The queue of directions.
|
||||
* The Deque of previous points in this WalkingQueue.
|
||||
*/
|
||||
private final Deque<Point> points = new ArrayDeque<>();
|
||||
private final Deque<Position> previousPoints = new ArrayDeque<>();
|
||||
|
||||
/**
|
||||
* Flag indicating if this queue (only) should be ran.
|
||||
* The running status of this WalkingQueue.
|
||||
*/
|
||||
private boolean runningQueue;
|
||||
private boolean running;
|
||||
|
||||
/**
|
||||
* Creates a walking queue for the specified mob.
|
||||
* Creates the WalkingQueue.
|
||||
*
|
||||
* @param mob The mob.
|
||||
* @param mob The {@link Mob} the WalkingQueue is for.
|
||||
*/
|
||||
public WalkingQueue(Mob mob) {
|
||||
this.mob = mob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the first step to the queue, attempting to connect the server and client position by looking at the
|
||||
* previous queue.
|
||||
* Adds a first step into this WalkingQueue.
|
||||
*
|
||||
* @param clientPosition The first step.
|
||||
* @return {@code true} if the queues could be connected correctly, {@code false} if not.
|
||||
* @param next The {@link Position} of the step.
|
||||
*/
|
||||
public boolean addFirstStep(Position clientPosition) {
|
||||
Position serverPosition = mob.getPosition();
|
||||
public void addFirstStep(Position next) {
|
||||
points.clear();
|
||||
running = false;
|
||||
|
||||
int deltaX = clientPosition.getX() - serverPosition.getX();
|
||||
int deltaY = clientPosition.getY() - serverPosition.getY();
|
||||
/*
|
||||
* We need to connect 'current' and 'next' whilst accounting for the
|
||||
* fact that the client and server might be out of sync (i.e. what the
|
||||
* client thinks is 'current' is different to what the server thinks is
|
||||
* 'current').
|
||||
*
|
||||
* First try to connect them via points from the previous queue.
|
||||
*/
|
||||
Queue<Position> backtrack = new ArrayDeque<>();
|
||||
|
||||
if (Direction.isConnectable(deltaX, deltaY)) {
|
||||
points.clear();
|
||||
oldPoints.clear();
|
||||
while (!previousPoints.isEmpty()) {
|
||||
Position position = previousPoints.pollLast();
|
||||
backtrack.add(position);
|
||||
|
||||
addStep(clientPosition);
|
||||
return true;
|
||||
}
|
||||
|
||||
Queue<Position> travelBackQueue = new ArrayDeque<>();
|
||||
|
||||
Point oldPoint;
|
||||
while ((oldPoint = oldPoints.pollLast()) != null) {
|
||||
Position oldPosition = oldPoint.position;
|
||||
|
||||
deltaX = oldPosition.getX() - serverPosition.getX();
|
||||
deltaY = oldPosition.getX() - serverPosition.getY();
|
||||
|
||||
travelBackQueue.add(oldPosition);
|
||||
|
||||
if (Direction.isConnectable(deltaX, deltaY)) {
|
||||
points.clear();
|
||||
oldPoints.clear();
|
||||
|
||||
travelBackQueue.forEach(this::addStep);
|
||||
|
||||
addStep(clientPosition);
|
||||
return true;
|
||||
if (position.equals(next)) {
|
||||
backtrack.forEach(this::addStep);
|
||||
previousPoints.clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
oldPoints.clear();
|
||||
return false;
|
||||
/* If that doesn't work, connect the points directly. */
|
||||
previousPoints.clear();
|
||||
addStep(next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a step.
|
||||
* Adds a step to this WalkingQueue.
|
||||
*
|
||||
* @param x The x coordinate of this step.
|
||||
* @param y The y coordinate of this step.
|
||||
* @param next The {@link Position} of the step.
|
||||
*/
|
||||
private void addStep(int x, int y) {
|
||||
if (points.size() >= MAXIMUM_SIZE) {
|
||||
return;
|
||||
public void addStep(Position next) {
|
||||
Position current = points.peekLast();
|
||||
|
||||
/*
|
||||
* If current equals next, addFirstStep doesn't end up adding anything points queue. This makes peekLast()
|
||||
* return null. If it does, the correct behaviour is to fill it in with mob.getPosition().
|
||||
*/
|
||||
if (current == null) {
|
||||
current = mob.getPosition();
|
||||
}
|
||||
|
||||
Point last = getLast();
|
||||
|
||||
int deltaX = x - last.position.getX();
|
||||
int deltaY = y - last.position.getY();
|
||||
|
||||
Direction direction = Direction.fromDeltas(deltaX, deltaY);
|
||||
|
||||
if (direction != Direction.NONE) {
|
||||
Point point = new Point(new Position(x, y, mob.getPosition().getHeight()), direction);
|
||||
points.add(point);
|
||||
oldPoints.add(point);
|
||||
}
|
||||
addStep(current, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a step to the queue.
|
||||
*
|
||||
* @param step The step to add.
|
||||
* Clears this WalkingQueue.
|
||||
*/
|
||||
public void addStep(Position step) {
|
||||
int x = step.getX(), y = step.getY();
|
||||
Point last = getLast();
|
||||
public void clear() {
|
||||
points.clear();
|
||||
running = false;
|
||||
previousPoints.clear();
|
||||
}
|
||||
|
||||
int deltaX = x - last.position.getX();
|
||||
int deltaY = y - last.position.getY();
|
||||
/**
|
||||
* Returns whether or not this WalkingQueue has running enabled.
|
||||
*
|
||||
* @return {@code true} iff this WalkingQueue has running enabled.
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulses this WalkingQueue.
|
||||
*/
|
||||
public void pulse() {
|
||||
Position position = mob.getPosition();
|
||||
|
||||
Direction firstDirection = Direction.NONE;
|
||||
Direction secondDirection = Direction.NONE;
|
||||
|
||||
Position next = points.poll();
|
||||
if (next != null) {
|
||||
previousPoints.add(next);
|
||||
firstDirection = Direction.between(position, next);
|
||||
position = next;
|
||||
|
||||
if (running) {
|
||||
next = points.poll();
|
||||
if (next != null) {
|
||||
previousPoints.add(next);
|
||||
secondDirection = Direction.between(position, next);
|
||||
position = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mob.setDirections(firstDirection, secondDirection);
|
||||
mob.setPosition(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the running flag status of this WalkingQueue.
|
||||
*
|
||||
* @param running The running flag.
|
||||
*/
|
||||
public void setRunning(boolean running) {
|
||||
this.running = running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of this WalkingQueue, which is the number of points remaining in it.
|
||||
*
|
||||
* @return The size.
|
||||
*/
|
||||
public int size() {
|
||||
return points.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@code next} step to this WalkingQueue.
|
||||
*
|
||||
* @param current The current {@link Position}.
|
||||
* @param next The next Position.
|
||||
*/
|
||||
private void addStep(Position current, Position next) {
|
||||
int nextX = next.getX(), nextY = next.getY(), height = next.getHeight();
|
||||
int deltaX = nextX - current.getX();
|
||||
int deltaY = nextY - current.getY();
|
||||
|
||||
int max = Math.max(Math.abs(deltaX), Math.abs(deltaY));
|
||||
|
||||
for (int i = 0; i < max; i++) {
|
||||
for (int count = 0; count < max; count++) {
|
||||
if (deltaX < 0) {
|
||||
deltaX++;
|
||||
} else if (deltaX > 0) {
|
||||
@@ -185,70 +188,8 @@ public final class WalkingQueue {
|
||||
deltaY--;
|
||||
}
|
||||
|
||||
addStep(x - deltaX, y - deltaY);
|
||||
points.add(new Position(nextX - deltaX, nextY - deltaY, height));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the walking queue.
|
||||
*/
|
||||
public void clear() {
|
||||
points.clear();
|
||||
oldPoints.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last point.
|
||||
*
|
||||
* @return The last point.
|
||||
*/
|
||||
private Point getLast() {
|
||||
return points.isEmpty() ? new Point(mob.getPosition(), Direction.NONE) : points.peekLast();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every pulse, updates the queue.
|
||||
*/
|
||||
public void pulse() {
|
||||
Position position = mob.getPosition();
|
||||
Direction first = Direction.NONE, second = Direction.NONE;
|
||||
|
||||
Point next = points.poll();
|
||||
if (next != null) {
|
||||
first = next.direction;
|
||||
position = next.position;
|
||||
|
||||
if (runningQueue /* and enough energy */) {
|
||||
next = points.poll();
|
||||
|
||||
if (next != null) {
|
||||
second = next.direction;
|
||||
position = next.position;
|
||||
}
|
||||
}
|
||||
|
||||
mob.setPosition(position);
|
||||
}
|
||||
|
||||
mob.setDirections(first, second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the running queue flag.
|
||||
*
|
||||
* @param running The running queue flag.
|
||||
*/
|
||||
public void setRunningQueue(boolean running) {
|
||||
runningQueue = running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the queue.
|
||||
*
|
||||
* @return The size of the queue.
|
||||
*/
|
||||
public int size() {
|
||||
return points.size();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -93,7 +93,9 @@ public final class NpcMovementTask extends ScheduledTask {
|
||||
WalkingQueue queue = npc.getWalkingQueue();
|
||||
|
||||
Position first = positions.pollFirst();
|
||||
if (first != null && queue.addFirstStep(first)) {
|
||||
|
||||
if (first != null) {
|
||||
queue.addFirstStep(first);
|
||||
positions.forEach(queue::addStep);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,6 @@ import org.xml.sax.SAXException;
|
||||
*/
|
||||
public final class GameService extends Service {
|
||||
|
||||
/**
|
||||
* The World this Service is for.
|
||||
*/
|
||||
protected final World world;
|
||||
|
||||
/**
|
||||
* The number of times to unregister players per cycle. This is to ensure the saving threads don't get swamped with
|
||||
* requests and slow everything down.
|
||||
@@ -45,9 +40,9 @@ public final class GameService extends Service {
|
||||
private static final int UNREGISTERS_PER_CYCLE = 50;
|
||||
|
||||
/**
|
||||
* The {@link MessageHandlerChainSet}.
|
||||
* The World this Service is for.
|
||||
*/
|
||||
private MessageHandlerChainSet messageHandlerChainSet;
|
||||
protected final World world;
|
||||
|
||||
/**
|
||||
* A queue of players to remove.
|
||||
@@ -60,6 +55,11 @@ public final class GameService extends Service {
|
||||
private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(ThreadUtil
|
||||
.create("GameService"));
|
||||
|
||||
/**
|
||||
* The {@link MessageHandlerChainSet}.
|
||||
*/
|
||||
private MessageHandlerChainSet handlers;
|
||||
|
||||
/**
|
||||
* The {@link ClientSynchronizer}.
|
||||
*/
|
||||
@@ -90,30 +90,28 @@ public final class GameService extends Service {
|
||||
/**
|
||||
* Gets the MessageHandlerChainSet
|
||||
*
|
||||
* @return The set of MessageHandlerChain's.
|
||||
* @return The MessageHandlerChainSet.
|
||||
*/
|
||||
public MessageHandlerChainSet getMessageHandlerChainSet() {
|
||||
return messageHandlerChainSet;
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every pulse.
|
||||
*/
|
||||
public void pulse() {
|
||||
synchronized (this) {
|
||||
finalizeUnregisters();
|
||||
public synchronized void pulse() {
|
||||
finalizeUnregistrations();
|
||||
|
||||
MobRepository<Player> players = world.getPlayerRepository();
|
||||
for (Player player : players) {
|
||||
GameSession session = player.getSession();
|
||||
if (session != null) {
|
||||
session.handlePendingMessages(messageHandlerChainSet);
|
||||
}
|
||||
MobRepository<Player> players = world.getPlayerRepository();
|
||||
for (Player player : players) {
|
||||
GameSession session = player.getSession();
|
||||
if (session != null) {
|
||||
session.handlePendingMessages(handlers);
|
||||
}
|
||||
|
||||
world.pulse();
|
||||
synchronizer.synchronize(players, world.getNpcRepository());
|
||||
}
|
||||
|
||||
world.pulse();
|
||||
synchronizer.synchronize(players, world.getNpcRepository());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,18 +121,16 @@ public final class GameService extends Service {
|
||||
* @param session The {@link GameSession} of the Player.
|
||||
* @return A {@link RegistrationStatus}.
|
||||
*/
|
||||
public RegistrationStatus registerPlayer(Player player, GameSession session) {
|
||||
synchronized (this) {
|
||||
RegistrationStatus status = world.register(player);
|
||||
if (status == RegistrationStatus.OK) {
|
||||
player.setSession(session);
|
||||
public synchronized RegistrationStatus registerPlayer(Player player, GameSession session) {
|
||||
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;
|
||||
Region region = world.getRegionRepository().fromPosition(player.getPosition());
|
||||
region.addEntity(player);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +161,7 @@ public final class GameService extends Service {
|
||||
/**
|
||||
* Finalizes the unregistration of Player's queued to be unregistered.
|
||||
*/
|
||||
private void finalizeUnregisters() {
|
||||
private void finalizeUnregistrations() {
|
||||
LoginService loginService = context.getLoginService();
|
||||
|
||||
for (int count = 0; count < UNREGISTERS_PER_CYCLE; count++) {
|
||||
@@ -188,7 +184,7 @@ public final class GameService extends Service {
|
||||
private void init() throws IOException, SAXException, ReflectiveOperationException {
|
||||
try (InputStream input = new FileInputStream("data/messages.xml")) {
|
||||
MessageHandlerChainSetParser chainSetParser = new MessageHandlerChainSetParser(input);
|
||||
messageHandlerChainSet = chainSetParser.parse(world);
|
||||
handlers = chainSetParser.parse(world);
|
||||
}
|
||||
|
||||
try (InputStream input = new FileInputStream("data/synchronizer.xml")) {
|
||||
|
||||
@@ -67,9 +67,10 @@ public final class PlayerSynchronizationTask extends SynchronizationTask {
|
||||
int oldLocalPlayers = localPlayers.size();
|
||||
List<SynchronizationSegment> segments = new ArrayList<>();
|
||||
|
||||
for (Iterator<Player> it = localPlayers.iterator(); it.hasNext();) {
|
||||
for (Iterator<Player> it = localPlayers.iterator(); it.hasNext(); ) {
|
||||
Player other = it.next();
|
||||
if (!other.isActive() || other.isTeleporting() || other.getPosition().getLongestDelta(player.getPosition()) > player.getViewingDistance() || !other.getPosition().isWithinDistance(player.getPosition(), player.getViewingDistance())) {
|
||||
|
||||
if (removePlayer(other)) {
|
||||
it.remove();
|
||||
segments.add(new RemoveMobSegment());
|
||||
} else {
|
||||
@@ -103,8 +104,27 @@ public final class PlayerSynchronizationTask extends SynchronizationTask {
|
||||
}
|
||||
}
|
||||
|
||||
PlayerSynchronizationMessage message = new PlayerSynchronizationMessage(lastKnownRegion, player.getPosition(), regionChanged, segment, oldLocalPlayers, segments);
|
||||
PlayerSynchronizationMessage message = new PlayerSynchronizationMessage(lastKnownRegion, player.getPosition(),
|
||||
regionChanged, segment, oldLocalPlayers, segments);
|
||||
player.send(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified {@link Player} should be removed.
|
||||
*
|
||||
* @param other The Player being tested.
|
||||
* @return {@code true} iff the specified Player should be removed.
|
||||
*/
|
||||
private boolean removePlayer(Player other) {
|
||||
if (other.isTeleporting() || !other.isActive()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Position position = player.getPosition();
|
||||
Position otherPosition = other.getPosition();
|
||||
int distance = player.getViewingDistance();
|
||||
|
||||
return otherPosition.getLongestDelta(position) > distance || !otherPosition.isWithinDistance(position, distance);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -66,7 +66,8 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
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
|
||||
* 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;
|
||||
@@ -78,7 +79,8 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
* @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) {
|
||||
public PrePlayerSynchronizationTask(Player player, Map<RegionCoordinates, List<RegionUpdateMessage>> updates,
|
||||
Map<RegionCoordinates, List<RegionUpdateMessage>> snapshots) {
|
||||
this.player = player;
|
||||
this.updates = updates;
|
||||
this.snapshots = snapshots;
|
||||
@@ -156,6 +158,22 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a region update is required.
|
||||
*
|
||||
* @return {@code true} if a Region update is required, {@code false} if not.
|
||||
*/
|
||||
private boolean isRegionUpdateRequired() {
|
||||
Position current = player.getPosition();
|
||||
Position last = player.getLastKnownRegion();
|
||||
|
||||
int deltaX = current.getLocalX(last);
|
||||
int deltaY = current.getLocalY(last);
|
||||
|
||||
return deltaX <= Position.MAX_DISTANCE || deltaX >= VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1
|
||||
|| deltaY <= Position.MAX_DISTANCE || deltaY >= VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link List} of {@link GroupedRegionUpdateMessage}s.
|
||||
*
|
||||
@@ -181,31 +199,13 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
player.send(new ClearRegionMessage(position, coordinates));
|
||||
}
|
||||
|
||||
Optional<GroupedRegionUpdateMessage> message = toUpdateMessage(local, player.getLastKnownRegion(), coordinates, repository);
|
||||
if (message.isPresent()) {
|
||||
messages.add(message.get());
|
||||
}
|
||||
toUpdateMessage(local, player.getLastKnownRegion(), coordinates, repository).ifPresent(messages::add);
|
||||
}
|
||||
}
|
||||
|
||||
messages.forEach(player::send);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a region update is required.
|
||||
*
|
||||
* @return {@code true} if a Region update is required, {@code false} if not.
|
||||
*/
|
||||
private boolean isRegionUpdateRequired() {
|
||||
Position current = player.getPosition();
|
||||
Position last = player.getLastKnownRegion();
|
||||
|
||||
int deltaX = current.getLocalX(last);
|
||||
int deltaY = current.getLocalY(last);
|
||||
|
||||
return deltaX <= Position.MAX_DISTANCE || deltaX >= VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1 || deltaY <= Position.MAX_DISTANCE || deltaY >= VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GroupedRegionUpdateMessage} using the specified {@link RegionUpdateMode}, returning
|
||||
* {@link Optional#empty()} if no update message is required.
|
||||
@@ -216,7 +216,8 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
* @param repository The {@link RegionRepository} containing the Regions.
|
||||
* @return The Optional containing the GroupedRegionUpdateMessage.
|
||||
*/
|
||||
private Optional<GroupedRegionUpdateMessage> toUpdateMessage(RegionUpdateMode mode, Position lastKnownRegion, RegionCoordinates coordinates, RegionRepository repository) {
|
||||
private Optional<GroupedRegionUpdateMessage> toUpdateMessage(RegionUpdateMode mode, Position lastKnownRegion,
|
||||
RegionCoordinates coordinates, RegionRepository repository) {
|
||||
List<RegionUpdateMessage> messages;
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user