Optimise GameObjectDecoder for faster start-up time.

This commit is contained in:
Major-
2015-08-30 18:08:30 +01:00
parent a4eb31bab7
commit e3f10e200d
3 changed files with 49 additions and 28 deletions
@@ -14,6 +14,7 @@ import org.apollo.cache.decoder.MapFileDecoder;
import org.apollo.cache.decoder.MapFileDecoder.MapDefinition;
import org.apollo.cache.decoder.ObjectDefinitionDecoder;
import org.apollo.cache.def.ObjectDefinition;
import org.apollo.game.io.player.PlayerSerializer;
import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.area.Region;
@@ -65,6 +66,11 @@ public final class GameObjectDecoder implements Runnable {
*/
private final World world;
/**
* The most-recently used Region.
*/
private Region previous;
/**
* Creates the GameObjectDecoder.
*
@@ -75,6 +81,7 @@ public final class GameObjectDecoder implements Runnable {
this.fs = fs;
this.world = world;
regions = world.getRegionRepository();
previous = regions.fromPosition(PlayerSerializer.TUTORIAL_ISLAND_SPAWN); // dummy, so 'previous' is never null.
}
@Override
@@ -85,9 +92,7 @@ public final class GameObjectDecoder implements Runnable {
try {
Map<Integer, MapDefinition> definitions = MapFileDecoder.decode(fs);
for (Entry<Integer, MapDefinition> entry : definitions.entrySet()) {
MapDefinition definition = entry.getValue();
for (MapDefinition definition : definitions.values()) {
int packed = definition.getPackedCoordinates();
int x = (packed >> 8 & 0xFF) * 64;
int y = (packed & 0xFF) * 64;
@@ -117,10 +122,13 @@ public final class GameObjectDecoder implements Runnable {
ObjectDefinition definition = ObjectDefinition.lookup(object.getId());
int type = object.getType();
Region region = regions.fromPosition(position);
int x = position.getX(), y = position.getY(), height = position.getHeight();
CollisionMatrix matrix = region.getMatrix(height);
if (!previous.contains(position)) {
previous = regions.fromPosition(position);
}
CollisionMatrix matrix = previous.getMatrix(height);
boolean block = false;
if (type == ObjectType.FLOOR_DECORATION.getValue() && definition.isInteractive()) {
@@ -140,18 +148,19 @@ public final class GameObjectDecoder implements Runnable {
}
if (block) {
for (int dx = 0; dx < definition.getWidth(); dx++) {
for (int dy = 0; dy < definition.getLength(); dy++) {
int width = definition.getWidth(), length = definition.getLength();
for (int dx = 0; dx < width; dx++) {
for (int dy = 0; dy < length; 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;
int nextLocalY = localY > 7 ? y + localY - 7 : y - localY;
Position nextPosition = new Position(nextLocalX, nextLocalY);
Region next = regions.fromPosition(nextPosition);
Region next = regions.fromPosition(new Position(nextLocalX, nextLocalY));
int nextX = nextPosition.getX() % Region.SIZE + dx;
int nextY = nextPosition.getY() % Region.SIZE + dy;
int nextX = nextLocalX % Region.SIZE + dx;
int nextY = nextLocalY % Region.SIZE + dy;
if (nextX > 7) {
nextX -= 7;
@@ -175,12 +184,11 @@ public final class GameObjectDecoder implements Runnable {
* Decodes the attributes of a terrain file, blocking the tile if necessary.
*
* @param attributes The terrain attributes.
* @param position The {@link Position} of the tile whose attributes are being decoded.
* @param x The x coordinate of the tile the attributes belong to.
* @param y The y coordinate of the tile the attributes belong to.
* @param height The level level of the tile the attributes belong to.
*/
private void decodeAttributes(int attributes, Position position) {
Region region = regions.fromPosition(position);
int x = position.getX(), y = position.getY(), height = position.getHeight();
private void decodeAttributes(int attributes, int x, int y, int height) {
boolean block = false;
if ((attributes & BLOCKED_TILE) != 0) {
block = true;
@@ -195,7 +203,13 @@ public final class GameObjectDecoder implements Runnable {
if (block) {
int localX = x % Region.SIZE, localY = y % Region.SIZE;
region.getMatrix(height).block(localX, localY);
Position position = new Position(x, y, height);
if (!previous.contains(position)) {
previous = regions.fromPosition(new Position(x, y, height));
}
previous.getMatrix(height).block(localX, localY);
}
}
@@ -248,21 +262,18 @@ public final class GameObjectDecoder implements Runnable {
* @param y The y coordinate of the top left tile of the map file.
*/
private void decodeTerrain(ByteBuffer buffer, int x, int y) {
for (int height = 0; height < 4; height++) {
for (int localX = 0; localX < 64; localX++) {
for (int localY = 0; localY < 64; localY++) {
Position position = new Position(x + localX, y + localY, height);
for (int height = 0; height < Position.HEIGHT_LEVELS; height++) {
for (int localX = 0; localX < Region.SIZE * Region.SIZE; localX++) {
for (int localY = 0; localY < Region.SIZE * Region.SIZE; localY++) {
int attributes = 0;
while (true) {
int attributeId = buffer.get() & 0xFF;
if (attributeId == 0) {
decodeAttributes(attributes, position);
break;
} else if (attributeId == 1) {
if (attributeId == 1) {
buffer.get();
decodeAttributes(attributes, position);
} else if (attributeId == 0) {
decodeAttributes(attributes, x + localX, y + localY, height);
break;
} else if (attributeId <= 49) {
buffer.get();
@@ -17,7 +17,7 @@ public abstract class PlayerSerializer {
/**
* The spawn point for Players, on Tutorial Island.
*/
protected static final Position TUTORIAL_ISLAND_SPAWN = new Position(3093, 3104);
public static final Position TUTORIAL_ISLAND_SPAWN = new Position(3093, 3104);
/**
* The World this PlayerSerializer is for.
@@ -163,6 +163,16 @@ public final class Region {
return local != null && local.contains(entity);
}
/**
* Returns whether or not the specified {@link Position} is inside this Region.
*
* @param position The Position.
* @return {@code true} iff the specified Position is inside this Region.
*/
public boolean contains(Position position) {
return coordinates.equals(position.getRegionCoordinates());
}
/**
* Encodes the contents of this Region into a {@link Set} of {@link RegionUpdateMessage}s, to be sent to a client.
*