Cleanup object-related code

This commit is contained in:
Major-
2016-02-11 15:14:42 +00:00
parent d6ac9eeeaa
commit 4b744e5e86
4 changed files with 46 additions and 50 deletions
@@ -6,8 +6,6 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Predicate;
import org.apollo.cache.IndexedFileSystem;
import org.apollo.cache.decoder.MapFileDecoder;
@@ -26,8 +24,6 @@ import org.apollo.game.model.entity.obj.StaticGameObject;
import org.apollo.util.BufferUtil;
import org.apollo.util.CompressionUtil;
import com.google.common.collect.Iterables;
/**
* Parses static object definitions, which include map tiles and landscapes.
*
@@ -94,12 +90,12 @@ public final class GameObjectDecoder implements Runnable {
for (MapDefinition definition : definitions.values()) {
int packed = definition.getPackedCoordinates();
int x = (packed >> 8 & 0xFF) * 64;
int y = (packed & 0xFF) * 64;
int x = (packed >> 8 & 0xFF) * (Region.SIZE * Region.SIZE);
int y = (packed & 0xFF) * (Region.SIZE * Region.SIZE);
ByteBuffer objects = fs.getFile(4, definition.getObjectFile());
ByteBuffer decompressed = ByteBuffer.wrap(CompressionUtil.degzip(objects));
decodeObjects(world, decompressed, x, y);
decodeObjects(decompressed, x, y);
ByteBuffer terrain = fs.getFile(4, definition.getTerrainFile());
decompressed = ByteBuffer.wrap(CompressionUtil.degzip(terrain));
@@ -129,25 +125,7 @@ public final class GameObjectDecoder implements Runnable {
}
CollisionMatrix matrix = previous.getMatrix(height);
boolean block = false;
if (type == ObjectType.FLOOR_DECORATION.getValue() && definition.isInteractive()) {
block = true;
}
// TODO figure out the other ObjectTypes and get rid of all the getValue() calls
Predicate<Integer> walls = value -> value >= ObjectType.LENGTHWISE_WALL.getValue()
&& value <= ObjectType.RECTANGULAR_CORNER.getValue() || value == ObjectType.DIAGONAL_WALL.getValue();
Predicate<Integer> roofs = value -> value > ObjectType.DIAGONAL_INTERACTABLE.getValue()
&& value < ObjectType.FLOOR_DECORATION.getValue();
if (walls.test(type) || roofs.test(type) || type == ObjectType.INTERACTABLE.getValue() && definition.isSolid()) {
block = true;
}
if (block) {
if (unwalkable(definition, type)) {
int width = definition.getWidth(), length = definition.getLength();
for (int dx = 0; dx < width; dx++) {
@@ -216,12 +194,11 @@ public final class GameObjectDecoder implements Runnable {
/**
* Decodes object data stored in the specified {@link ByteBuffer}.
*
* @param world The {@link World} containing the StaticGameObjects.
* @param buffer The ByteBuffer.
* @param buffer The ByteBuffer to decode data from.
* @param x The x coordinate of the top left tile of the map file.
* @param y The y coordinate of the top left tile of the map file.
*/
private void decodeObjects(World world, ByteBuffer buffer, int x, int y) {
private void decodeObjects(ByteBuffer buffer, int x, int y) {
int id = -1;
int idOffset = BufferUtil.readSmart(buffer);
@@ -288,4 +265,21 @@ public final class GameObjectDecoder implements Runnable {
}
}
/**
* Returns whether or not an object with the specified {@link ObjectDefinition} and {@code type} should result in
* the tile(s) it is located on being blocked.
*
* @param definition The {@link ObjectDefinition} of the object.
* @param type The type of the object.
* @return {@code true} iff the tile(s) the object is on should be blocked.
*/
private boolean unwalkable(ObjectDefinition definition, int type) {
// TODO figure out the other ObjectTypes and get rid of all the getValue() calls
return (type == ObjectType.FLOOR_DECORATION.getValue() && definition.isInteractive()) ||
(type >= ObjectType.LENGTHWISE_WALL.getValue() && type <= ObjectType.RECTANGULAR_CORNER.getValue()) ||
(type > ObjectType.DIAGONAL_INTERACTABLE.getValue() && type < ObjectType.FLOOR_DECORATION.getValue()) ||
(type == ObjectType.INTERACTABLE.getValue() && definition.isSolid()) ||
type == ObjectType.DIAGONAL_WALL.getValue();
}
}
@@ -1,12 +1,15 @@
package org.apollo.game.fs.decoder;
import org.apollo.util.ThreadUtil;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toList;
import org.apollo.util.ThreadUtil;
/**
* A composite decoder that executes each child in parallel.
@@ -16,7 +19,7 @@ import static java.util.stream.Collectors.toList;
public final class SynchronousDecoder {
/**
* The time to wait before cancelling the decoding.
* The time to wait before cancelling the decoding, in milliseconds.
*/
private static final int TIMEOUT = 15_000;
@@ -24,7 +27,7 @@ public final class SynchronousDecoder {
* The Executor used to execute the Runnable(s).
*/
private final ExecutorService executor = Executors.newFixedThreadPool(ThreadUtil.AVAILABLE_PROCESSORS,
ThreadUtil.create("SynchronousDecoder"));
ThreadUtil.create("SynchronousDecoder"));
/**
* The List of Runnables.
@@ -47,19 +50,18 @@ public final class SynchronousDecoder {
* @throws SynchronousDecoderException If a decoder failed to complete successfully.
*/
public void block() throws InterruptedException, SynchronousDecoderException {
List<Future> futureList = runnables.stream()
.map(executor::submit)
.collect(toList());
List<Future> futures = runnables.stream().map(executor::submit).collect(Collectors.toList());
executor.shutdown();
executor.awaitTermination(TIMEOUT, TimeUnit.MILLISECONDS);
for (Future future : futureList) {
for (Future future : futures) {
try {
future.get();
} catch (ExecutionException e) {
throw new SynchronousDecoderException("Unable to run all decoder tasks", e.getCause());
} catch (ExecutionException cause) {
throw new SynchronousDecoderException("Unable to run all decoder tasks.", cause);
}
}
}
}
@@ -1,6 +1,7 @@
package org.apollo.game.model.entity.obj;
import java.util.Arrays;
import java.util.Optional;
/**
* The group of an object, which indicates its general class (e.g. if it's a wall, or a floor decoration).
@@ -21,7 +22,7 @@ public enum ObjectGroup {
WALL_DECORATION(1),
/**
* The interactable object group, for objects that can be clicked and interacted with. TODO rename
* The interactable object group, for objects that can be clicked and interacted with.
*/
INTERACTABLE_OBJECT(2),
@@ -31,14 +32,13 @@ public enum ObjectGroup {
GROUND_DECORATION(3);
/**
* Gets the ObjectGroup with the specified integer value.
* Attempts to find the ObjectGroup with the specified integer value.
*
* @param value The integer value of the ObjectGroup.
* @return The ObjectGroup.
* @throws IllegalArgumentException If there is no ObjectGroup with the specified value.
* @return The {@link Optional} possibly containing the ObjectGroup, if found.
*/
public static ObjectGroup valueOf(int value) {
return Arrays.stream(values()).filter(group -> group.value == value).findAny().orElseThrow(() -> new IllegalArgumentException("No ObjectGroup with a value of " + value + " exists."));
public static Optional<ObjectGroup> valueOf(int value) {
return Arrays.stream(values()).filter(group -> group.value == value).findAny();
}
/**
@@ -49,9 +49,9 @@ public enum ObjectGroup {
/**
* Creates the ObjectGroup.
*
* @param value The integer value of the group.
* @param value The integer value of the group. Must be unique.
*/
private ObjectGroup(int value) {
ObjectGroup(int value) {
this.value = value;
}
@@ -65,7 +65,7 @@ public enum ObjectType {
* @param value The integer value of this ObjectType.
* @param group The ObjectGroup of this type.
*/
private ObjectType(int value, ObjectGroup group) {
ObjectType(int value, ObjectGroup group) {
this.value = value;
this.group = group;
}