forked from MagicBane/Server
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
372 lines
9.7 KiB
372 lines
9.7 KiB
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . |
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· |
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ |
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ |
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ |
|
// Magicbane Emulator Project © 2013 - 2022 |
|
// www.magicbane.com |
|
|
|
|
|
package engine.net; |
|
|
|
import engine.math.Vector3f; |
|
import engine.math.Vector3fImmutable; |
|
import engine.util.ByteBufferUtils; |
|
import engine.util.ByteUtils; |
|
|
|
import java.nio.Buffer; |
|
import java.nio.ByteBuffer; |
|
import java.nio.ByteOrder; |
|
import java.util.UUID; |
|
|
|
public class ByteBufferReader { |
|
|
|
private final ByteBuffer bb; |
|
private final boolean endianFlip; |
|
|
|
/** |
|
* Helper class for getting structured information out of a ByteBuffer |
|
* easily. ByteBuffer passed in is copied to an internal ByteBuffer. |
|
* <B>bbin</B> must have the position attribute at the <i>end</i> of the |
|
* data to be copied over, since <b>bbin.flip()</b> is called in this |
|
* constructor. |
|
* |
|
* @param bbin |
|
* @param endianFlip |
|
*/ |
|
public ByteBufferReader(ByteBuffer bbin, boolean endianFlip) { |
|
super(); |
|
|
|
// Copy supplied BB. |
|
this.bb = ByteBuffer.allocate(bbin.position()); //FIXME Do we want to get this from pool? |
|
bbin.flip(); |
|
this.bb.put(bbin); |
|
|
|
// prepare bb for reading |
|
this.bb.flip(); |
|
|
|
this.endianFlip = endianFlip; |
|
} |
|
|
|
/* |
|
* Getters |
|
*/ |
|
|
|
/** |
|
* @return |
|
* @see java.nio.ByteBuffer#get() |
|
*/ |
|
public byte get() { |
|
return bb.get(); |
|
} |
|
|
|
public void get(byte[] ba) { |
|
this.bb.get(ba); |
|
} |
|
|
|
/** |
|
* @return |
|
* @see java.nio.ByteBuffer#getChar() |
|
*/ |
|
public char getChar() { |
|
char x = bb.getChar(); |
|
if (this.endianFlip) { |
|
x = Character.reverseBytes(x); |
|
} |
|
return x; |
|
} |
|
|
|
/** |
|
* @return |
|
* @see java.nio.ByteBuffer#getDouble() |
|
*/ |
|
public double getDouble() { |
|
double x = 0; |
|
if (this.endianFlip) { |
|
x = bb.order(ByteOrder.LITTLE_ENDIAN).getDouble(); |
|
bb.order(ByteOrder.BIG_ENDIAN); |
|
} else { |
|
x = bb.getDouble(); |
|
} |
|
return x; |
|
} |
|
|
|
/** |
|
* @return |
|
* @see java.nio.ByteBuffer#getFloat() |
|
*/ |
|
public float getFloat() { |
|
float x = 0; |
|
if (this.endianFlip) { |
|
x = bb.order(ByteOrder.LITTLE_ENDIAN).getFloat(); |
|
bb.order(ByteOrder.BIG_ENDIAN); |
|
} else { |
|
x = bb.getFloat(); |
|
} |
|
return x; |
|
} |
|
|
|
/** |
|
* @return |
|
* @see java.nio.ByteBuffer#getInt() |
|
*/ |
|
public int getInt() { |
|
int x = bb.getInt(); |
|
if (this.endianFlip) { |
|
x = Integer.reverseBytes(x); |
|
} |
|
return x; |
|
} |
|
|
|
/** |
|
* @return |
|
* @see java.nio.ByteBuffer#getLong() |
|
*/ |
|
public long getLong() { |
|
long x = bb.getLong(); |
|
if (this.endianFlip) { |
|
x = Long.reverseBytes(x); |
|
} |
|
return x; |
|
} |
|
|
|
/** |
|
* @return |
|
* @see java.nio.ByteBuffer#getShort() |
|
*/ |
|
public short getShort() { |
|
short x = bb.getShort(); |
|
if (this.endianFlip) { |
|
x = Short.reverseBytes(x); |
|
} |
|
return x; |
|
} |
|
|
|
public final String getString() { |
|
if (this.endianFlip) { |
|
return ByteBufferUtils.getString(this.bb, true, false); |
|
} else { |
|
return ByteBufferUtils.getString(this.bb, false, false); |
|
} |
|
} |
|
|
|
public final String getSmallString() { |
|
if (this.endianFlip) { |
|
return ByteBufferUtils.getString(this.bb, true, true); |
|
} else { |
|
return ByteBufferUtils.getString(this.bb, false, true); |
|
} |
|
} |
|
|
|
public final String getHexString() { |
|
if (this.endianFlip) { |
|
return ByteBufferUtils.getHexString(this.bb, true); |
|
} else { |
|
return ByteBufferUtils.getHexString(this.bb); |
|
} |
|
} |
|
|
|
public final String getUnicodeString() { |
|
if (this.endianFlip) { |
|
return ByteBufferUtils.getUnicodeString(this.bb, true); |
|
} else { |
|
return ByteBufferUtils.getUnicodeString(this.bb); |
|
} |
|
} |
|
|
|
public String get1ByteAsHexString() { |
|
return getBytesAsHexStringCommon(new byte[1]); |
|
} |
|
|
|
public String get2BytesAsHexString() { |
|
return getBytesAsHexStringCommon(new byte[2]); |
|
} |
|
|
|
public String get4BytesAsHexString() { |
|
return getBytesAsHexStringCommon(new byte[4]); |
|
} |
|
|
|
public String get8BytesAsHexString() { |
|
return getBytesAsHexStringCommon(new byte[8]); |
|
} |
|
|
|
private String getBytesAsHexStringCommon(byte[] ba) { |
|
this.bb.get(ba); |
|
if (this.endianFlip) { |
|
return ByteUtils.byteArrayToStringHex(ByteUtils |
|
.switchByteArrayEndianness(ba)); |
|
} else { |
|
return ByteUtils.byteArrayToStringHex(ba); |
|
} |
|
} |
|
|
|
public Vector3f getVector3f() { |
|
Vector3f out = new Vector3f(); |
|
if (this.endianFlip) { |
|
out.x = Float |
|
.intBitsToFloat(Integer.reverseBytes(this.bb.getInt())); |
|
out.y = Float |
|
.intBitsToFloat(Integer.reverseBytes(this.bb.getInt())); |
|
out.z = Float |
|
.intBitsToFloat(Integer.reverseBytes(this.bb.getInt())); |
|
} else { |
|
out.x = this.bb.getFloat(); |
|
out.y = this.bb.getFloat(); |
|
out.z = this.bb.getFloat(); |
|
} |
|
return out; |
|
} |
|
|
|
public Vector3fImmutable getVector3fImmutable() { |
|
Vector3fImmutable out; |
|
if (this.endianFlip) { |
|
out = new Vector3fImmutable(Float.intBitsToFloat(Integer |
|
.reverseBytes(this.bb.getInt())), Float |
|
.intBitsToFloat(Integer.reverseBytes(this.bb.getInt())), |
|
Float |
|
.intBitsToFloat(Integer.reverseBytes(this.bb |
|
.getInt()))); |
|
} else { |
|
out = new Vector3fImmutable(this.bb.getFloat(), this.bb.getFloat(), |
|
this.bb.getFloat()); |
|
} |
|
return out; |
|
} |
|
|
|
public final UUID getUUID() { |
|
final byte[] buffer = new byte[16]; |
|
this.bb.get(buffer); |
|
|
|
long msb = 0; |
|
long lsb = 0; |
|
|
|
for (int i = 0; i < 8; i++) { |
|
msb = (msb << 8) | (buffer[i] & 0xff); |
|
} |
|
|
|
for (int i = 8; i < 16; i++) { |
|
lsb = (lsb << 8) | (buffer[i] & 0xff); |
|
} |
|
|
|
return new UUID(msb, lsb); |
|
} |
|
|
|
|
|
/* |
|
* Monitors |
|
*/ |
|
|
|
public byte monitorByte(byte expectedValue, String label) { |
|
return this.monitorByte(expectedValue, label, false); |
|
} |
|
|
|
public byte monitorByte(byte expectedValue, String label, boolean peek) { |
|
// if (x != expectedValue) { |
|
// Logger.info("MonitorTrip: " + label + ". Expected: " |
|
// + expectedValue + " Got: " + x); |
|
// } |
|
return this.get(); |
|
} |
|
|
|
public short monitorShort(short expectedValue, String label) { |
|
return this.monitorShort(expectedValue, label, false); |
|
} |
|
|
|
public short monitorShort(short expectedValue, String label, boolean peek) { |
|
// if (x != expectedValue) { |
|
// Logger.info("MonitorTrip: " + label + ". Expected: " |
|
// + expectedValue + " Got: " + x); |
|
// } |
|
return this.getShort(); |
|
} |
|
|
|
public int monitorInt(int expectedValue, String label) { |
|
return this.monitorInt(expectedValue, label, false); |
|
} |
|
|
|
public int monitorInt(int expectedValue, String label, boolean peek) { |
|
// if (x != expectedValue) { |
|
// Logger.info("MonitorTrip: " + label + ". Expected: " |
|
// + expectedValue + " Got: " + x); |
|
// } |
|
return this.getInt(); |
|
} |
|
|
|
public long monitorLong(long expectedValue, String label) { |
|
return this.monitorLong(expectedValue, label, false); |
|
} |
|
|
|
public long monitorLong(long expectedValue, String label, boolean peek) { |
|
// if (x != expectedValue) { |
|
// Logger.info("MonitorTrip: " + label + ". Expected: " |
|
// + expectedValue + " Got: " + x); |
|
// } |
|
return this.getLong(); |
|
} |
|
|
|
/* |
|
* ByteBuffer delegates |
|
*/ |
|
|
|
/** |
|
* @return |
|
* @see java.nio.Buffer#hasRemaining() |
|
*/ |
|
public final boolean hasRemaining() { |
|
return bb.hasRemaining(); |
|
} |
|
|
|
/** |
|
* @return |
|
* @see java.nio.Buffer#limit() |
|
*/ |
|
public final int limit() { |
|
return bb.limit(); |
|
} |
|
|
|
/** |
|
* @return |
|
* @see java.nio.Buffer#position() |
|
*/ |
|
public final int position() { |
|
return bb.position(); |
|
} |
|
|
|
public final Buffer position(int newPosition) { |
|
return bb.position(newPosition); |
|
} |
|
|
|
/** |
|
* @return |
|
* @see java.nio.Buffer#remaining() |
|
*/ |
|
public final int remaining() { |
|
return bb.remaining(); |
|
} |
|
|
|
/* |
|
* Status getters |
|
*/ |
|
|
|
protected ByteBuffer getBb() { |
|
return bb; |
|
} |
|
|
|
protected boolean isEndianFlip() { |
|
return endianFlip; |
|
} |
|
|
|
public String getByteArray() { |
|
String ret = ""; |
|
if (this.bb == null) |
|
return ret; |
|
byte[] bbyte = bb.array(); |
|
if (bbyte == null) |
|
return ret; |
|
for (int i = 0; i < bbyte.length; i++) { |
|
ret += Integer.toString((bbyte[i] & 0xff) + 0x100, 16).substring(1).toUpperCase(); |
|
} |
|
return ret; |
|
} |
|
|
|
}
|
|
|