mirror of
https://github.com/ProjectSWGCore/pswgcommon.git
synced 2026-01-17 00:04:25 -05:00
Basic updates to existing classes and added EnumLookup
This commit is contained in:
@@ -32,31 +32,65 @@ import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
public class Delay {
|
||||
|
||||
/**
|
||||
* Sleeps for the specified number of nanoseconds
|
||||
* @param nanos the number of nanoseconds to sleep
|
||||
* @return TRUE if this operation has been interrupted
|
||||
*/
|
||||
public static boolean sleepNano(long nanos) {
|
||||
LockSupport.parkNanos(nanos);
|
||||
return isInterrupted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleeps for the specified number of microseconds
|
||||
* @param micro the number of microseconds to sleep
|
||||
* @return TRUE if this operation has been interrupted
|
||||
*/
|
||||
public static boolean sleepMicro(long micro) {
|
||||
return sleepNano(micro * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleeps for the specified number of milliseconds
|
||||
* @param milli the number of milliseconds to sleep
|
||||
* @return TRUE if this operation has been interrupted
|
||||
*/
|
||||
public static boolean sleepMilli(long milli) {
|
||||
return sleepNano(milli * 1000000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleeps for the specified number of seconds
|
||||
* @param sec the number of seconds to sleep
|
||||
* @return TRUE if this operation has been interrupted
|
||||
*/
|
||||
public static boolean sleepSeconds(long sec) {
|
||||
return sleepNano(sec * 1000000000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleeps for the specified amount of time
|
||||
* @param time the amount of time to sleep
|
||||
* @param unit the unit of time
|
||||
* @return TRUE if this operation has been interrupted
|
||||
*/
|
||||
public static boolean sleep(long time, TimeUnit unit) {
|
||||
return sleepNano(unit.toNanos(time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this thread has been interrupted
|
||||
* @return TRUE if interrupted, FALSE otherwise
|
||||
*/
|
||||
public static boolean isInterrupted() {
|
||||
return Thread.currentThread().isInterrupted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the interrupted flag so future calls to isInterrupted will return
|
||||
* FALSE
|
||||
*/
|
||||
public static void clearInterrupted() {
|
||||
Thread.interrupted();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.control;
|
||||
|
||||
import com.projectswg.common.debug.Assert;
|
||||
|
||||
public class IntentChain {
|
||||
|
||||
private final IntentManager intentManager;
|
||||
@@ -64,4 +66,12 @@ public class IntentChain {
|
||||
}
|
||||
}
|
||||
|
||||
public static void broadcastChain(Intent ... intents) {
|
||||
Assert.test(intents.length > 0, "Intent length must be greater than 0!");
|
||||
for (int i = 1; i < intents.length; i++) {
|
||||
intents[i].broadcastAfterIntent(intents[i-1]);
|
||||
}
|
||||
intents[0].broadcast();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.data;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.projectswg.common.encoding.Encodable;
|
||||
@@ -110,11 +108,16 @@ public class CRC implements Encodable, Persistable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {
|
||||
this.crc = data.order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||
public void decode(NetBuffer data) {
|
||||
this.crc = data.getInt();
|
||||
this.str = getString(crc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(NetBufferStream stream) {
|
||||
stream.addInt(crc);
|
||||
|
||||
36
src/com/projectswg/common/data/EnumLookup.java
Normal file
36
src/com/projectswg/common/data/EnumLookup.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package com.projectswg.common.data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EnumLookup<K, T extends Enum<?>> {
|
||||
|
||||
private final Map<K, T> lookup;
|
||||
|
||||
public EnumLookup(Class<T> c, CustomLookupAdder<K, T> adder) {
|
||||
lookup = new HashMap<>();
|
||||
for (T t : c.getEnumConstants()) {
|
||||
lookup.put(adder.getKey(t), t);
|
||||
}
|
||||
}
|
||||
|
||||
public T getEnum(K k, T def) {
|
||||
T t = lookup.get(k);
|
||||
if (t == null)
|
||||
return def;
|
||||
return t;
|
||||
}
|
||||
|
||||
public boolean containsEnum(K k) {
|
||||
return lookup.containsKey(k);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return lookup.size();
|
||||
}
|
||||
|
||||
public interface CustomLookupAdder<K, T> {
|
||||
K getKey(T t);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,6 @@
|
||||
package com.projectswg.common.data;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.projectswg.common.encoding.Encodable;
|
||||
import com.projectswg.common.network.NetBuffer;
|
||||
@@ -63,10 +62,15 @@ public class RGB implements Encodable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {
|
||||
r = data.get();
|
||||
g = data.get();
|
||||
b = data.get();
|
||||
public void decode(NetBuffer data) {
|
||||
r = data.getByte();
|
||||
g = data.getByte();
|
||||
b = data.getByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
public byte getR() {
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.data.location;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.projectswg.common.encoding.Encodable;
|
||||
import com.projectswg.common.network.NetBuffer;
|
||||
import com.projectswg.common.network.NetBufferStream;
|
||||
@@ -44,7 +42,7 @@ public class Location implements Encodable, Persistable {
|
||||
this(Double.NaN, Double.NaN, Double.NaN, null);
|
||||
}
|
||||
|
||||
public Location(Location l) {
|
||||
public Location(Location l) {
|
||||
this(l.getX(), l.getY(), l.getZ(), l.terrain);
|
||||
orientation.set(l.orientation);
|
||||
}
|
||||
@@ -55,19 +53,44 @@ public class Location implements Encodable, Persistable {
|
||||
this.terrain = terrain;
|
||||
}
|
||||
|
||||
public void setTerrain(Terrain terrain) { this.terrain = terrain; }
|
||||
public void setX(double x) { point.setX(x); }
|
||||
public void setY(double y) { point.setY(y); }
|
||||
public void setZ(double z) { point.setZ(z); }
|
||||
public void setOrientationX(double oX) { orientation.setX(oX); }
|
||||
public void setOrientationY(double oY) { orientation.setY(oY); }
|
||||
public void setOrientationZ(double oZ) { orientation.setZ(oZ); }
|
||||
public void setOrientationW(double oW) { orientation.setW(oW); }
|
||||
public void setTerrain(Terrain terrain) {
|
||||
this.terrain = terrain;
|
||||
}
|
||||
|
||||
public void setX(double x) {
|
||||
point.setX(x);
|
||||
}
|
||||
|
||||
public void setY(double y) {
|
||||
point.setY(y);
|
||||
}
|
||||
|
||||
public void setZ(double z) {
|
||||
point.setZ(z);
|
||||
}
|
||||
|
||||
public void setOrientationX(double oX) {
|
||||
orientation.setX(oX);
|
||||
}
|
||||
|
||||
public void setOrientationY(double oY) {
|
||||
orientation.setY(oY);
|
||||
}
|
||||
|
||||
public void setOrientationZ(double oZ) {
|
||||
orientation.setZ(oZ);
|
||||
}
|
||||
|
||||
public void setOrientationW(double oW) {
|
||||
orientation.setW(oW);
|
||||
}
|
||||
|
||||
public void setPosition(double x, double y, double z) {
|
||||
setX(x);
|
||||
setY(y);
|
||||
setZ(z);
|
||||
}
|
||||
|
||||
public void setOrientation(double oX, double oY, double oZ, double oW) {
|
||||
setOrientationX(oX);
|
||||
setOrientationY(oY);
|
||||
@@ -75,24 +98,56 @@ public class Location implements Encodable, Persistable {
|
||||
setOrientationW(oW);
|
||||
}
|
||||
|
||||
public Terrain getTerrain() { return terrain; }
|
||||
public double getX() { return point.getX(); }
|
||||
public double getY() { return point.getY(); }
|
||||
public double getZ() { return point.getZ(); }
|
||||
public Point3D getPosition() { return new Point3D(point); }
|
||||
public double getOrientationX() { return orientation.getX(); }
|
||||
public double getOrientationY() { return orientation.getY(); }
|
||||
public double getOrientationZ() { return orientation.getZ(); }
|
||||
public double getOrientationW() { return orientation.getW(); }
|
||||
public Quaternion getOrientation() { return new Quaternion(orientation); }
|
||||
public Terrain getTerrain() {
|
||||
return terrain;
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return point.getX();
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return point.getY();
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return point.getZ();
|
||||
}
|
||||
|
||||
public Point3D getPosition() {
|
||||
return new Point3D(point);
|
||||
}
|
||||
|
||||
public double getOrientationX() {
|
||||
return orientation.getX();
|
||||
}
|
||||
|
||||
public double getOrientationY() {
|
||||
return orientation.getY();
|
||||
}
|
||||
|
||||
public double getOrientationZ() {
|
||||
return orientation.getZ();
|
||||
}
|
||||
|
||||
public double getOrientationW() {
|
||||
return orientation.getW();
|
||||
}
|
||||
|
||||
public Quaternion getOrientation() {
|
||||
return new Quaternion(orientation);
|
||||
}
|
||||
|
||||
public boolean isWithinDistance(Location l, double x, double y, double z) {
|
||||
if (getTerrain() != l.getTerrain())
|
||||
return false;
|
||||
double xD = Math.abs(getX() - l.getX());
|
||||
double yD = Math.abs(getY() - l.getY());
|
||||
double zD = Math.abs(getZ() - l.getZ());
|
||||
return xD <= x && yD <= y && zD <= z;
|
||||
if (Math.abs(getX() - l.getX()) > x)
|
||||
return false;
|
||||
if (Math.abs(getY() - l.getY()) > y)
|
||||
return false;
|
||||
if (Math.abs(getZ() - l.getZ()) > z)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isWithinDistance(Location l, double radius) {
|
||||
@@ -102,14 +157,14 @@ public class Location implements Encodable, Persistable {
|
||||
public boolean isWithinDistance(Terrain t, double x, double y, double z, double radius) {
|
||||
if (getTerrain() != t)
|
||||
return false;
|
||||
return square(getX()-x) + square(getY()-y) + square(getZ()-z) <= square(radius);
|
||||
return square(getX() - x) + square(getY() - y) + square(getZ() - z) <= square(radius);
|
||||
}
|
||||
|
||||
public boolean isWithinFlatDistance(Location l, double radius) {
|
||||
return isWithinFlatDistance(l.point, radius);
|
||||
}
|
||||
|
||||
public boolean isWithinFlatDistance(Point3D target, double radius){
|
||||
public boolean isWithinFlatDistance(Point3D target, double radius) {
|
||||
return square(getX() - target.getX()) + square(getZ() - target.getZ()) <= square(radius);
|
||||
}
|
||||
|
||||
@@ -120,7 +175,7 @@ public class Location implements Encodable, Persistable {
|
||||
}
|
||||
|
||||
public void translateLocation(Location l) {
|
||||
point.rotateAround(l.getX(), l.getY(), l.getZ(), l.orientation);
|
||||
point.rotateAround(l.getX(), l.getY(), l.getZ(), l.orientation);
|
||||
orientation.rotateByQuaternion(l.orientation);
|
||||
}
|
||||
|
||||
@@ -132,6 +187,7 @@ public class Location implements Encodable, Persistable {
|
||||
|
||||
/**
|
||||
* Sets the orientation to be facing the specified heading
|
||||
*
|
||||
* @param heading the heading to face, in degrees
|
||||
*/
|
||||
public void setHeading(double heading) {
|
||||
@@ -140,6 +196,7 @@ public class Location implements Encodable, Persistable {
|
||||
|
||||
/**
|
||||
* Rotates the orientation by the specified angle along the Y-axis
|
||||
*
|
||||
* @param angle the angle to rotate by in degrees
|
||||
*/
|
||||
public void rotateHeading(double angle) {
|
||||
@@ -148,6 +205,7 @@ public class Location implements Encodable, Persistable {
|
||||
|
||||
/**
|
||||
* Rotates the orientation by the specified angle along the specified axises
|
||||
*
|
||||
* @param angle the angle to rotate by in degrees
|
||||
* @param axisX the amount of rotation about the x-axis
|
||||
* @param axisY the amount of rotation about the x-axis
|
||||
@@ -158,34 +216,13 @@ public class Location implements Encodable, Persistable {
|
||||
}
|
||||
|
||||
public void mergeWith(Location l) {
|
||||
if (terrain == null || terrain != l.getTerrain())
|
||||
terrain = l.getTerrain();
|
||||
mergeLocation(l.getX(), l.getY(), l.getZ());
|
||||
mergeOrientation(l);
|
||||
}
|
||||
|
||||
public void mergeLocation(double lX, double lY, double lZ) {
|
||||
if (!isEqual(getX(), lX))
|
||||
point.setX(lX);
|
||||
if (!isEqual(getY(), lY))
|
||||
point.setY(lY);
|
||||
if (!isEqual(getZ(), lZ))
|
||||
point.setZ(lZ);
|
||||
}
|
||||
|
||||
private void mergeOrientation(Location l) {
|
||||
if (!isEqual(getOrientationX(), l.getOrientationX()))
|
||||
orientation.setX(l.getOrientationX());
|
||||
if (!isEqual(getOrientationY(), l.getOrientationY()))
|
||||
orientation.setY(l.getOrientationY());
|
||||
if (!isEqual(getOrientationZ(), l.getOrientationZ()))
|
||||
orientation.setZ(l.getOrientationZ());
|
||||
if (!isEqual(getOrientationW(), l.getOrientationW()))
|
||||
orientation.setW(l.getOrientationW());
|
||||
this.terrain = l.getTerrain();
|
||||
this.point.set(l.getX(), l.getY(), l.getZ());
|
||||
this.orientation.set(l.getOrientationX(), l.getOrientationY(), l.getOrientationZ(), l.getOrientationW());
|
||||
}
|
||||
|
||||
public double getSpeed(Location l, double deltaTime) {
|
||||
double dist = Math.sqrt(square(getX()-l.getX()) + square(getY()-l.getY()) + square(getZ()-l.getZ()));
|
||||
double dist = Math.sqrt(square(getX() - l.getX()) + square(getY() - l.getY()) + square(getZ() - l.getZ()));
|
||||
return dist / deltaTime;
|
||||
}
|
||||
|
||||
@@ -194,9 +231,10 @@ public class Location implements Encodable, Persistable {
|
||||
}
|
||||
|
||||
private double square(double x) {
|
||||
return x*x;
|
||||
return x * x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Location))
|
||||
return false;
|
||||
@@ -223,13 +261,14 @@ public class Location implements Encodable, Persistable {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash(getX())*13 + hash(getY())*17 + hash(getZ())*19 + hash(getOrientationX())*23 + hash(getOrientationY())*29 + hash(getOrientationZ())*31 + hash(getOrientationW())*37;
|
||||
return hash(getX()) * 13 + hash(getY()) * 17 + hash(getZ()) * 19 + hash(getOrientationX()) * 23 + hash(getOrientationY()) * 29 + hash(getOrientationZ()) * 31 + hash(getOrientationW()) * 37;
|
||||
}
|
||||
|
||||
private int hash(double x) {
|
||||
long v = Double.doubleToLongBits(x);
|
||||
return (int)(v^(v>>>32));
|
||||
return (int) (v ^ (v >>> 32));
|
||||
}
|
||||
|
||||
private boolean isEqual(double x, double y) {
|
||||
@@ -239,26 +278,31 @@ public class Location implements Encodable, Persistable {
|
||||
return false;
|
||||
return Math.abs(x - y) <= 1E-7;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] encode() {
|
||||
NetBuffer buf = NetBuffer.allocate(28);
|
||||
buf.addFloat(safeEncodeDouble(orientation.getX()));
|
||||
buf.addFloat(safeEncodeDouble(orientation.getY()));
|
||||
buf.addFloat(safeEncodeDouble(orientation.getZ()));
|
||||
buf.addFloat(safeEncodeDouble(orientation.getW()));
|
||||
buf.addFloat(safeEncodeDouble(point.getX()));
|
||||
buf.addFloat(safeEncodeDouble(point.getY()));
|
||||
buf.addFloat(safeEncodeDouble(point.getZ()));
|
||||
buf.addFloat((float) orientation.getX());
|
||||
buf.addFloat((float) orientation.getY());
|
||||
buf.addFloat((float) orientation.getZ());
|
||||
buf.addFloat((float) orientation.getW());
|
||||
buf.addFloat((float) point.getX());
|
||||
buf.addFloat((float) point.getY());
|
||||
buf.addFloat((float) point.getZ());
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {
|
||||
public void decode(NetBuffer data) {
|
||||
orientation.decode(data);
|
||||
point.decode(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return 28;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(NetBufferStream stream) {
|
||||
stream.addByte(0);
|
||||
@@ -277,7 +321,7 @@ public class Location implements Encodable, Persistable {
|
||||
if (stream.getBoolean())
|
||||
terrain = Terrain.valueOf(stream.getAscii());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Location[TRN=%s, %s %s]", terrain, point, orientation);
|
||||
@@ -295,8 +339,12 @@ public class Location implements Encodable, Persistable {
|
||||
return Math.sqrt(square(dstX - getX()) + square(dstY - getY()) + square(dstZ - getZ()));
|
||||
}
|
||||
|
||||
private float safeEncodeDouble(double d) {
|
||||
return (float) (Double.isNaN(d) ? 0 : d);
|
||||
public double flatDistanceTo(Location destination) {
|
||||
return flatDistanceTo(destination.getX(), destination.getZ());
|
||||
}
|
||||
|
||||
public double flatDistanceTo(double dstX, double dstZ) {
|
||||
return Math.sqrt(square(dstX - getX()) + square(dstZ - getZ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.data.location;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.projectswg.common.encoding.Encodable;
|
||||
import com.projectswg.common.network.NetBuffer;
|
||||
import com.projectswg.common.network.NetBufferStream;
|
||||
@@ -107,11 +105,15 @@ public class Point3D implements Encodable, Persistable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {
|
||||
NetBuffer buf = NetBuffer.wrap(data);
|
||||
x = buf.getFloat();
|
||||
y = buf.getFloat();
|
||||
z = buf.getFloat();
|
||||
public void decode(NetBuffer data) {
|
||||
x = data.getFloat();
|
||||
y = data.getFloat();
|
||||
z = data.getFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,6 +130,7 @@ public class Point3D implements Encodable, Persistable {
|
||||
z = stream.getFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Point3D))
|
||||
return false;
|
||||
@@ -140,10 +143,12 @@ public class Point3D implements Encodable, Persistable {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Double.hashCode(getX()) ^ Double.hashCode(getY()) ^ Double.hashCode(getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Point3D[%.2f, %.2f, %.2f]", x, y, z);
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.data.location;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.projectswg.common.encoding.Encodable;
|
||||
import com.projectswg.common.network.NetBuffer;
|
||||
import com.projectswg.common.network.NetBufferStream;
|
||||
@@ -162,15 +160,19 @@ public class Quaternion implements Encodable, Persistable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {
|
||||
NetBuffer buf = NetBuffer.wrap(data);
|
||||
x = buf.getFloat();
|
||||
y = buf.getFloat();
|
||||
z = buf.getFloat();
|
||||
w = buf.getFloat();
|
||||
public void decode(NetBuffer data) {
|
||||
x = data.getFloat();
|
||||
y = data.getFloat();
|
||||
z = data.getFloat();
|
||||
w = data.getFloat();
|
||||
updateRotationMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(NetBufferStream stream) {
|
||||
stream.addFloat((float) x);
|
||||
@@ -188,6 +190,7 @@ public class Quaternion implements Encodable, Persistable {
|
||||
updateRotationMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Quaternion[%.3f, %.3f, %.3f, %.3f]", x, y, z, w);
|
||||
}
|
||||
|
||||
@@ -28,11 +28,10 @@
|
||||
package com.projectswg.common.data.location;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.projectswg.common.data.CRC;
|
||||
import com.projectswg.common.data.EnumLookup;
|
||||
|
||||
public enum Terrain {
|
||||
ADVENTURE1 ("terrain/adventure1.trn"),
|
||||
@@ -103,35 +102,34 @@ public enum Terrain {
|
||||
WATERTABLETEST ("terrain/watertabletest.trn"),
|
||||
YAVIN4 ("terrain/yavin4.trn");
|
||||
|
||||
private static final Map <Integer, String> CRC_TO_NAME = new ConcurrentHashMap<>();
|
||||
private static final Map <String, Integer> NAME_TO_CRC = new ConcurrentHashMap<>();
|
||||
private static final Map <String, Terrain> NAME_TO_TERRAIN = new ConcurrentHashMap<>();
|
||||
private static final Map <Integer, Terrain> CRC_TO_TERRAIN = new ConcurrentHashMap<>();
|
||||
private static final EnumLookup<Integer, Terrain> CRC_LOOKUP = new EnumLookup<>(Terrain.class, t -> t.getCrc());
|
||||
private static final EnumLookup<String, Terrain> NAME_LOOKUP = new EnumLookup<>(Terrain.class, t -> t.getName());
|
||||
|
||||
private String file;
|
||||
private String name;
|
||||
private int crc;
|
||||
|
||||
static {
|
||||
for (Terrain p : values()) {
|
||||
CRC_TO_TERRAIN.put(p.getCrc(), p);
|
||||
CRC_TO_NAME.put(p.getCrc(), p.name());
|
||||
NAME_TO_CRC.put(p.name().toLowerCase(Locale.US), p.getCrc());
|
||||
NAME_TO_CRC.put(p.name().toLowerCase(Locale.US), p.getCrc());
|
||||
NAME_TO_TERRAIN.put(p.name().toLowerCase(Locale.US), p);
|
||||
}
|
||||
}
|
||||
|
||||
Terrain(String file) {
|
||||
this.file = file;
|
||||
this.name = file.substring(8, file.length() - 4);
|
||||
this.crc = CRC.getCrc(name);
|
||||
}
|
||||
|
||||
public String getFile() { return file; }
|
||||
public String getName() { return name; }
|
||||
public String getNameCapitalized() { return Character.toUpperCase(name.charAt(0)) + name.substring(1); }
|
||||
public int getCrc() { return crc; }
|
||||
public String getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getNameCapitalized() {
|
||||
return Character.toUpperCase(name.charAt(0)) + name.substring(1);
|
||||
}
|
||||
|
||||
public int getCrc() {
|
||||
return crc;
|
||||
}
|
||||
|
||||
public Location getStartLocation() {
|
||||
Location l = new Location();
|
||||
@@ -149,45 +147,35 @@ public enum Terrain {
|
||||
}
|
||||
|
||||
public static int getTerrainCount() {
|
||||
return CRC_TO_TERRAIN.size();
|
||||
return CRC_LOOKUP.size();
|
||||
}
|
||||
|
||||
public static String getNameFromCrc(int crc) {
|
||||
String name = CRC_TO_NAME.get(crc);
|
||||
if (name == null)
|
||||
return "";
|
||||
return name;
|
||||
Terrain t = CRC_LOOKUP.getEnum(crc, null);
|
||||
return (t == null) ? "" : t.getName();
|
||||
}
|
||||
|
||||
public static int getCrcFromName(String name) {
|
||||
Integer crc = NAME_TO_CRC.get(name.toLowerCase(Locale.ENGLISH));
|
||||
if (crc == null)
|
||||
return 0;
|
||||
return crc;
|
||||
Terrain t = NAME_LOOKUP.getEnum(name.toLowerCase(Locale.ENGLISH), null);
|
||||
return (t == null) ? 0 : t.getCrc();
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: Defaults to TATOOINE
|
||||
*/
|
||||
public static Terrain getTerrainFromCrc(int crc) {
|
||||
Terrain p = CRC_TO_TERRAIN.get(crc);
|
||||
if (p == null)
|
||||
return TATOOINE;
|
||||
return p;
|
||||
return CRC_LOOKUP.getEnum(crc, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: Defaults to TATOOINE
|
||||
*/
|
||||
public static Terrain getTerrainFromName(String name) {
|
||||
Terrain p = NAME_TO_TERRAIN.get(name.toLowerCase(Locale.ENGLISH));
|
||||
if (p == null)
|
||||
return TATOOINE;
|
||||
return p;
|
||||
return NAME_LOOKUP.getEnum(name.toLowerCase(Locale.ENGLISH), null);
|
||||
}
|
||||
|
||||
public static boolean doesTerrainExistForName(String name) {
|
||||
return NAME_TO_TERRAIN.containsKey(name.toLowerCase(Locale.ENGLISH));
|
||||
return NAME_LOOKUP.containsEnum(name.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public class Assert {
|
||||
Log.e(e);
|
||||
}
|
||||
|
||||
private static class AssertionException extends RuntimeException {
|
||||
public static class AssertionException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@@ -26,9 +26,10 @@
|
||||
******************************************************************************/
|
||||
package com.projectswg.common.encoding;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import com.projectswg.common.network.NetBuffer;
|
||||
|
||||
public interface Encodable {
|
||||
void decode(NetBuffer data);
|
||||
byte [] encode();
|
||||
void decode(ByteBuffer data);
|
||||
int getLength();
|
||||
}
|
||||
|
||||
@@ -29,8 +29,10 @@ package com.projectswg.common.network;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.projectswg.common.debug.Log;
|
||||
import com.projectswg.common.encoding.Encodable;
|
||||
@@ -39,8 +41,8 @@ import com.projectswg.common.encoding.StringType;
|
||||
|
||||
public class NetBuffer {
|
||||
|
||||
public static final Charset ASCII = Charset.forName("UTF-8");
|
||||
public static final Charset UNICODE = Charset.forName("UTF-16LE");
|
||||
public final Charset ASCII = Charset.forName("UTF-8");
|
||||
public final Charset UNICODE = Charset.forName("UTF-16LE");
|
||||
|
||||
private final ByteBuffer data;
|
||||
private final int size;
|
||||
@@ -74,6 +76,14 @@ public class NetBuffer {
|
||||
return data.position();
|
||||
}
|
||||
|
||||
public int limit() {
|
||||
return data.limit();
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return data.capacity();
|
||||
}
|
||||
|
||||
public void position(int position) {
|
||||
data.position(position);
|
||||
}
|
||||
@@ -82,32 +92,32 @@ public class NetBuffer {
|
||||
data.position(data.position()+relative);
|
||||
}
|
||||
|
||||
public void flip() {
|
||||
data.flip();
|
||||
}
|
||||
|
||||
public ByteBuffer getBuffer() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void add(NetBuffer buffer) {
|
||||
add(buffer.getBuffer());
|
||||
}
|
||||
|
||||
public void add(ByteBuffer buffer) {
|
||||
data.put(buffer);
|
||||
}
|
||||
|
||||
public void addBoolean(boolean b) {
|
||||
data.put(b ? (byte)1 : (byte)0);
|
||||
}
|
||||
|
||||
public void addAscii(String s) {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
data.putShort((short)s.length());
|
||||
data.put(s.getBytes(ASCII));
|
||||
}
|
||||
|
||||
public void addAscii(char [] s) {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
data.putShort((short)s.length);
|
||||
ByteBuffer bb = ASCII.encode(CharBuffer.wrap(s));
|
||||
byte [] bData = new byte[bb.limit()];
|
||||
bb.get(bData);
|
||||
data.put(bData);
|
||||
addArray(s.getBytes(ASCII));
|
||||
}
|
||||
|
||||
public void addUnicode(String s) {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
data.putInt(s.length());
|
||||
addInt(s.length());
|
||||
data.put(s.getBytes(UNICODE));
|
||||
}
|
||||
|
||||
@@ -120,7 +130,7 @@ public class NetBuffer {
|
||||
}
|
||||
|
||||
public void addFloat(float f) {
|
||||
data.putFloat(f);
|
||||
data.order(ByteOrder.LITTLE_ENDIAN).putFloat(f);
|
||||
}
|
||||
|
||||
public void addShort(int i) {
|
||||
@@ -148,10 +158,47 @@ public class NetBuffer {
|
||||
data.put(b);
|
||||
}
|
||||
|
||||
public void addArrayLarge(byte [] b) {
|
||||
addInt(b.length);
|
||||
data.put(b);
|
||||
}
|
||||
|
||||
public void addRawArray(byte [] b) {
|
||||
data.put(b);
|
||||
}
|
||||
|
||||
public void addList(Collection<? extends Encodable> list) {
|
||||
if (list == null) {
|
||||
addInt(0);
|
||||
return;
|
||||
}
|
||||
|
||||
addInt(list.size());
|
||||
for (Encodable encodable : list) {
|
||||
addEncodable(encodable);
|
||||
}
|
||||
}
|
||||
|
||||
public void addList(List<String> list, StringType type) {
|
||||
addInt(list.size());
|
||||
|
||||
switch (type) {
|
||||
case ASCII:
|
||||
for (String s : list) {
|
||||
addAscii(s);
|
||||
}
|
||||
break;
|
||||
case UNICODE:
|
||||
for (String s : list) {
|
||||
addUnicode(s);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.e("Cannot encode StringType " + type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void addEncodable(Encodable e) {
|
||||
data.put(e.encode());
|
||||
}
|
||||
@@ -161,23 +208,11 @@ public class NetBuffer {
|
||||
}
|
||||
|
||||
public String getAscii() {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
short length = data.getShort();
|
||||
if (length > data.remaining())
|
||||
return "";
|
||||
byte [] str = new byte[length];
|
||||
data.get(str);
|
||||
return new String(str, ASCII);
|
||||
return new String(getArray(), ASCII);
|
||||
}
|
||||
|
||||
public String getUnicode() {
|
||||
data.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int length = data.getInt() * 2;
|
||||
if (length > data.remaining())
|
||||
return "";
|
||||
byte [] str = new byte[length];
|
||||
data.get(str);
|
||||
return new String(str, UNICODE);
|
||||
return new String(getArray(getInt() * 2), UNICODE);
|
||||
}
|
||||
|
||||
public String getString(StringType type) {
|
||||
@@ -221,9 +256,11 @@ public class NetBuffer {
|
||||
}
|
||||
|
||||
public byte [] getArray() {
|
||||
byte [] bData = new byte[getShort()];
|
||||
data.get(bData);
|
||||
return bData;
|
||||
return getArray(getShort());
|
||||
}
|
||||
|
||||
public byte [] getArrayLarge() {
|
||||
return getArray(getInt());
|
||||
}
|
||||
|
||||
public byte [] getArray(int size) {
|
||||
@@ -232,12 +269,33 @@ public class NetBuffer {
|
||||
return bData;
|
||||
}
|
||||
|
||||
public int [] getIntArray() {
|
||||
int [] ints = new int[getInt()];
|
||||
for (int i = 0; i < ints.length; i++)
|
||||
ints[i] = getInt();
|
||||
return ints;
|
||||
}
|
||||
|
||||
public int [] getIntArray(int size) {
|
||||
int [] ints = new int[size];
|
||||
for (int i = 0; i < ints.length; i++)
|
||||
ints[i] = getInt();
|
||||
return ints;
|
||||
}
|
||||
|
||||
public boolean[] getBooleanArray() {
|
||||
boolean[] booleans = new boolean[getInt()];
|
||||
for(int i = 0; i < booleans.length; i++)
|
||||
booleans[i] = getBoolean();
|
||||
return booleans;
|
||||
}
|
||||
|
||||
public <T> Object getGeneric(Class<T> type) {
|
||||
if (Encodable.class.isAssignableFrom(type)) {
|
||||
T instance = null;
|
||||
try {
|
||||
instance = type.newInstance();
|
||||
((Encodable) instance).decode(data);
|
||||
((Encodable) instance).decode(this);
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
@@ -256,11 +314,69 @@ public class NetBuffer {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T extends Encodable> List<T> getList(Class<T> type) {
|
||||
int size = getInt();
|
||||
|
||||
if (size < 0) {
|
||||
Log.e("Read list with size less than zero!");
|
||||
return null;
|
||||
} else if (size == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<T> list = new ArrayList<>();
|
||||
|
||||
try {
|
||||
for (int i = 0; i < size; i++) {
|
||||
T instance = type.newInstance();
|
||||
instance.decode(this);
|
||||
list.add(instance);
|
||||
}
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
|
||||
if (size != list.size())
|
||||
Log.e("Expected list size %d but only have %d elements in the list", size, list.size());
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<String> getList(StringType type) {
|
||||
int size = getInt();
|
||||
|
||||
if (size < 0) {
|
||||
Log.e("Read list with size less than zero!");
|
||||
return null;
|
||||
} else if (size == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<String> list = new ArrayList<>();
|
||||
|
||||
switch (type) {
|
||||
case ASCII:
|
||||
for (int i = 0; i < size; i++) {
|
||||
list.add(getAscii());
|
||||
}
|
||||
break;
|
||||
case UNICODE:
|
||||
for (int i = 0; i < size; i++) {
|
||||
list.add(getUnicode());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.e("Do not know how to read list of StringType " + type);
|
||||
break;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public <T extends Encodable> T getEncodable(Class<T> type) {
|
||||
T instance = null;
|
||||
try {
|
||||
instance = type.newInstance();
|
||||
instance.decode(data);
|
||||
instance.decode(this);
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
|
||||
@@ -110,10 +110,12 @@ public class NetBufferStream extends OutputStream {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte [] data) {
|
||||
write(data, 0, data.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte [] data, int offset, int length) {
|
||||
ensureCapacity(size + length);
|
||||
synchronized (bufferMutex) {
|
||||
@@ -281,14 +283,6 @@ public class NetBufferStream extends OutputStream {
|
||||
}
|
||||
}
|
||||
|
||||
public void addAscii(char[] s) {
|
||||
ensureCapacity(size+2+s.length);
|
||||
synchronized (bufferMutex) {
|
||||
buffer.addAscii(s);
|
||||
size += 2 + s.length;
|
||||
}
|
||||
}
|
||||
|
||||
public void addUnicode(String s) {
|
||||
ensureCapacity(size+4+s.length()*2);
|
||||
synchronized (bufferMutex) {
|
||||
|
||||
@@ -30,7 +30,6 @@ package com.projectswg.common.network;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedByInterruptException;
|
||||
@@ -95,12 +94,12 @@ public class TCPServer {
|
||||
Assert.notNull(sock);
|
||||
synchronized (sockets) {
|
||||
SocketChannel sc = sockets.get(sock);
|
||||
Assert.notNull(sc);
|
||||
if (sc == null)
|
||||
return true;
|
||||
sockets.remove(sock);
|
||||
try {
|
||||
Socket s = sc.socket();
|
||||
sc.close();
|
||||
callbackManager.callOnEach((callback) -> callback.onConnectionDisconnect(s, sock));
|
||||
callbackManager.callOnEach((callback) -> callback.onConnectionDisconnect(sc, sock));
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
@@ -133,22 +132,10 @@ public class TCPServer {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean send(InetSocketAddress sock, ByteBuffer data) {
|
||||
public SocketChannel getChannel(SocketAddress sock) {
|
||||
synchronized (sockets) {
|
||||
SocketChannel sc = sockets.get(sock);
|
||||
Assert.notNull(sc);
|
||||
Assert.test(sc.isConnected());
|
||||
Assert.test(data.hasRemaining());
|
||||
try {
|
||||
while (data.hasRemaining())
|
||||
sc.write(data);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.e("TCPServer", "Terminated connection with %s. Error: %s", sock.toString(), e.getMessage());
|
||||
disconnect(sc);
|
||||
}
|
||||
return sockets.get(sock);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setCallback(TCPCallback callback) {
|
||||
@@ -156,9 +143,9 @@ public class TCPServer {
|
||||
}
|
||||
|
||||
public interface TCPCallback {
|
||||
void onIncomingConnection(Socket s);
|
||||
void onConnectionDisconnect(Socket s, SocketAddress addr);
|
||||
void onIncomingData(Socket s, byte [] data);
|
||||
void onIncomingConnection(SocketChannel s, SocketAddress addr);
|
||||
void onConnectionDisconnect(SocketChannel s, SocketAddress addr);
|
||||
void onIncomingData(SocketChannel s, SocketAddress addr, byte [] data);
|
||||
}
|
||||
|
||||
private class TCPServerListener implements Runnable {
|
||||
@@ -186,6 +173,7 @@ public class TCPServer {
|
||||
thread = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try (Selector selector = setupSelector()) {
|
||||
while (running) {
|
||||
@@ -241,7 +229,8 @@ public class TCPServer {
|
||||
sockets.put(sc.getRemoteAddress(), sc);
|
||||
sc.configureBlocking(false);
|
||||
sc.register(selector, SelectionKey.OP_READ);
|
||||
callbackManager.callOnEach((callback) -> callback.onIncomingConnection(sc.socket()));
|
||||
SocketAddress addr = sc.getRemoteAddress();
|
||||
callbackManager.callOnEach((callback) -> callback.onIncomingConnection(sc, addr));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(e);
|
||||
@@ -260,7 +249,8 @@ public class TCPServer {
|
||||
} else if (n > 0) {
|
||||
ByteBuffer smaller = ByteBuffer.allocate(n);
|
||||
smaller.put(buffer);
|
||||
callbackManager.callOnEach((callback) -> callback.onIncomingData(s.socket(), smaller.array()));
|
||||
SocketAddress addr = s.getRemoteAddress();
|
||||
callbackManager.callOnEach((callback) -> callback.onIncomingData(s, addr, smaller.array()));
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
||||
Reference in New Issue
Block a user