Merge branch 'dev/utils' into dev/world
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
apply from: rootDir.toPath().resolve('logic.gradle').toFile()
|
apply from: rootDir.toPath().resolve('logic.gradle').toFile()
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
api project(':utils')
|
||||||
|
|
||||||
implementation libs.objpool
|
implementation libs.objpool
|
||||||
implementation libs.netty.transport
|
implementation libs.netty.transport
|
||||||
implementation libs.netty.codec
|
implementation libs.netty.codec
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package mc.protocol.handler;
|
|||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import mc.protocol.State;
|
import mc.protocol.State;
|
||||||
import mc.protocol.packets.ClientSidePacket;
|
import mc.protocol.packets.ClientSidePacket;
|
||||||
import mc.protocol.utils.Table;
|
import mc.utils.Table;
|
||||||
|
|
||||||
public class ProtocolHandlersBus {
|
public class ProtocolHandlersBus {
|
||||||
|
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ rootProject.projectDir.toPath().resolve('gradle.properties').readLines().forEach
|
|||||||
rootProject.name = map.get('prj.name')
|
rootProject.name = map.get('prj.name')
|
||||||
|
|
||||||
include('cli-parser')
|
include('cli-parser')
|
||||||
|
include('utils')
|
||||||
include('protocol')
|
include('protocol')
|
||||||
include('server')
|
include('server')
|
||||||
|
|||||||
1
utils/build.gradle
Normal file
1
utils/build.gradle
Normal file
@@ -0,0 +1 @@
|
|||||||
|
apply from: rootDir.toPath().resolve('logic.gradle').toFile()
|
||||||
2
utils/gradle.properties
Normal file
2
utils/gradle.properties
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# suppress inspection "UnusedProperty" for whole file
|
||||||
|
module.name=utils
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package mc.protocol.utils;
|
package mc.utils;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package mc.utils.array;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public abstract class AbstractBitBufferArray implements BitArray {
|
||||||
|
|
||||||
|
protected int bitPerEntity;
|
||||||
|
protected int arraySize;
|
||||||
|
protected long maxEntityValue;
|
||||||
|
protected ByteBuffer byteBuffer;
|
||||||
|
|
||||||
|
protected int writePosition = 0;
|
||||||
|
|
||||||
|
protected AbstractBitBufferArray(int bitPerEntity, int arraySize, boolean direct) {
|
||||||
|
this.bitPerEntity = bitPerEntity;
|
||||||
|
this.arraySize = arraySize;
|
||||||
|
this.maxEntityValue = (1L << bitPerEntity) - 1L;
|
||||||
|
|
||||||
|
int capaticy = calculateCapacity();
|
||||||
|
if (direct) {
|
||||||
|
this.byteBuffer = ByteBuffer.allocateDirect(capaticy);
|
||||||
|
} else {
|
||||||
|
this.byteBuffer = ByteBuffer.allocate(capaticy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(int value) {
|
||||||
|
put(writePosition, value);
|
||||||
|
writePosition++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer byteBuffer() {
|
||||||
|
return this.byteBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateIndex(int index) {
|
||||||
|
if (index < 0 || index > arraySize - 1) {
|
||||||
|
throw new IllegalArgumentException("Index " + index + " out of range [0;" + arraySize + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateValue(int value) {
|
||||||
|
if ((value | maxEntityValue) > maxEntityValue) {
|
||||||
|
throw new IllegalArgumentException("Invalide value " + value + ". Value bits: " + Integer.bitCount(value) + ", maximum bits: " + bitPerEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract int calculateCapacity();
|
||||||
|
}
|
||||||
13
utils/src/main/java/mc/utils/array/BitArray.java
Normal file
13
utils/src/main/java/mc/utils/array/BitArray.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package mc.utils.array;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public interface BitArray {
|
||||||
|
|
||||||
|
void put(int value);
|
||||||
|
void put(int index, int value);
|
||||||
|
|
||||||
|
int get(int index);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer();
|
||||||
|
}
|
||||||
62
utils/src/main/java/mc/utils/array/BitByteArray.java
Normal file
62
utils/src/main/java/mc/utils/array/BitByteArray.java
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package mc.utils.array;
|
||||||
|
|
||||||
|
public class BitByteArray extends AbstractBitBufferArray {
|
||||||
|
|
||||||
|
public BitByteArray(int bitPerEntity, int arraySize, boolean direct) {
|
||||||
|
super(bitPerEntity, arraySize, direct);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitByteArray(int bitPerEntity, int arraySize) {
|
||||||
|
this(bitPerEntity, arraySize, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(int index, int value) {
|
||||||
|
validateIndex(index);
|
||||||
|
validateValue(value);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
int headValueIndex = ((index + 1) * bitPerEntity - 1) / Byte.SIZE;
|
||||||
|
int var1 = index * bitPerEntity;
|
||||||
|
int tailValueIndex = var1 / Byte.SIZE;
|
||||||
|
int offsetValue = var1 % Byte.SIZE;
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
byteBuffer.put(tailValueIndex,
|
||||||
|
(byte) (byteBuffer.get(tailValueIndex) & ~(maxEntityValue << offsetValue)
|
||||||
|
| ((byte) value & maxEntityValue) << offsetValue));
|
||||||
|
|
||||||
|
if (headValueIndex != tailValueIndex) {
|
||||||
|
int shift1 = Byte.SIZE - offsetValue;
|
||||||
|
int shift2 = bitPerEntity - shift1;
|
||||||
|
|
||||||
|
byteBuffer.put(headValueIndex,
|
||||||
|
(byte) (byteBuffer.get(headValueIndex) >>> shift2 << shift2
|
||||||
|
| ((byte) value & maxEntityValue) >> shift1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int get(int index) {
|
||||||
|
validateIndex(index);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
int headValueIndex = ((index + 1) * bitPerEntity - 1) / Byte.SIZE;
|
||||||
|
int var1 = index * bitPerEntity;
|
||||||
|
int tailValueIndex = var1 / Byte.SIZE;
|
||||||
|
int offsetValue = var1 % Byte.SIZE;
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
if (headValueIndex == tailValueIndex) {
|
||||||
|
return (int) (byteBuffer.get(tailValueIndex) >>> offsetValue & maxEntityValue);
|
||||||
|
} else {
|
||||||
|
return (int) ((byteBuffer.get(tailValueIndex) >>> offsetValue
|
||||||
|
| byteBuffer.get(headValueIndex) << (Byte.SIZE - offsetValue)) & maxEntityValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calculateCapacity() {
|
||||||
|
return (arraySize * bitPerEntity / Byte.SIZE + 1) * Byte.BYTES;
|
||||||
|
}
|
||||||
|
}
|
||||||
67
utils/src/main/java/mc/utils/array/BitLongArray.java
Normal file
67
utils/src/main/java/mc/utils/array/BitLongArray.java
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package mc.utils.array;
|
||||||
|
|
||||||
|
import java.nio.LongBuffer;
|
||||||
|
|
||||||
|
public class BitLongArray extends AbstractBitBufferArray {
|
||||||
|
|
||||||
|
private final LongBuffer longBuffer;
|
||||||
|
|
||||||
|
public BitLongArray(int bitPerEntity, int arraySize, boolean direct) {
|
||||||
|
super(bitPerEntity, arraySize, direct);
|
||||||
|
this.longBuffer = this.byteBuffer.asLongBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitLongArray(int bitPerEntity, int arraySize) {
|
||||||
|
this(bitPerEntity, arraySize, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(int index, int value) {
|
||||||
|
validateIndex(index);
|
||||||
|
validateValue(value);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
int headValueIndex = ((index + 1) * bitPerEntity - 1) / Long.SIZE;
|
||||||
|
int var1 = index * bitPerEntity;
|
||||||
|
int tailValueIndex = var1 / Long.SIZE;
|
||||||
|
int offsetValue = var1 % Long.SIZE;
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
longBuffer.put(tailValueIndex,
|
||||||
|
longBuffer.get(tailValueIndex) & ~(maxEntityValue << offsetValue)
|
||||||
|
| ((long) value & maxEntityValue) << offsetValue);
|
||||||
|
|
||||||
|
if (headValueIndex != tailValueIndex) {
|
||||||
|
int shift1 = Long.SIZE - offsetValue;
|
||||||
|
int shift2 = bitPerEntity - shift1;
|
||||||
|
|
||||||
|
longBuffer.put(headValueIndex,
|
||||||
|
longBuffer.get(headValueIndex) >>> shift2 << shift2
|
||||||
|
| ((long) value & maxEntityValue) >> shift1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int get(int index) {
|
||||||
|
validateIndex(index);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
int headValueIndex = ((index + 1) * bitPerEntity - 1) / Long.SIZE;
|
||||||
|
int var1 = index * bitPerEntity;
|
||||||
|
int tailValueIndex = var1 / Long.SIZE;
|
||||||
|
int offsetValue = var1 % Long.SIZE;
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
if (headValueIndex == tailValueIndex) {
|
||||||
|
return (int) (longBuffer.get(tailValueIndex) >>> offsetValue & maxEntityValue);
|
||||||
|
} else {
|
||||||
|
return (int) ((longBuffer.get(tailValueIndex) >>> offsetValue
|
||||||
|
| longBuffer.get(headValueIndex) << (Long.SIZE - offsetValue)) & maxEntityValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calculateCapacity() {
|
||||||
|
return (arraySize * bitPerEntity / Long.SIZE + 1) * Long.BYTES;
|
||||||
|
}
|
||||||
|
}
|
||||||
80
utils/src/test/java/mc/utils/array/BitByteArrayTest.java
Normal file
80
utils/src/test/java/mc/utils/array/BitByteArrayTest.java
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package mc.utils.array;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class BitByteArrayTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void initTest() {
|
||||||
|
BitArray bitArray = new BitByteArray(4, 1, false);
|
||||||
|
ByteBuffer byteBuffer = bitArray.byteBuffer();
|
||||||
|
|
||||||
|
assertEquals(1, byteBuffer.capacity());
|
||||||
|
assertEquals(1, byteBuffer.limit());
|
||||||
|
assertEquals(0, byteBuffer.position());
|
||||||
|
assertEquals(1, byteBuffer.array().length);
|
||||||
|
|
||||||
|
bitArray = new BitByteArray(4, 2);
|
||||||
|
byteBuffer = bitArray.byteBuffer();
|
||||||
|
|
||||||
|
assertEquals(2, byteBuffer.capacity());
|
||||||
|
assertEquals(2, byteBuffer.limit());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeTest1() {
|
||||||
|
int value = 0b00001001;
|
||||||
|
int expected = 0b10011001;
|
||||||
|
|
||||||
|
BitArray bitArray = new BitByteArray(4, 2);
|
||||||
|
bitArray.put(value);
|
||||||
|
bitArray.put(value);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = bitArray.byteBuffer();
|
||||||
|
assertEquals(expected, byteBuffer.get(0) & 0xFF); //Unsigned Byte
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeTest2() {
|
||||||
|
int value1 = 0b00001001;
|
||||||
|
int value2 = 0b00001111;
|
||||||
|
int expected1 = 0b10011001;
|
||||||
|
int expected2 = 0b11111111;
|
||||||
|
|
||||||
|
BitArray bitArray = new BitByteArray(4, 4);
|
||||||
|
bitArray.put(value1);
|
||||||
|
bitArray.put(value1);
|
||||||
|
bitArray.put(value2);
|
||||||
|
bitArray.put(value2);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = bitArray.byteBuffer();
|
||||||
|
assertEquals(expected1, byteBuffer.get(0) & 0xFF); //Unsigned Byte
|
||||||
|
assertEquals(expected2, byteBuffer.get(1) & 0xFF); //Unsigned Byte
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeOffsetTest() {
|
||||||
|
int value = 0b00001001;
|
||||||
|
int expected = 0b10010000;
|
||||||
|
|
||||||
|
BitArray bitArray = new BitByteArray(4, 2);
|
||||||
|
bitArray.put(1, value);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = bitArray.byteBuffer();
|
||||||
|
assertEquals(expected, byteBuffer.get(0) & 0xFF); //Unsigned Byte
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void readTest() {
|
||||||
|
int excepted = 0b00000110;
|
||||||
|
|
||||||
|
BitArray bitArray = new BitByteArray(4, 2);
|
||||||
|
bitArray.put(1, excepted);
|
||||||
|
|
||||||
|
assertEquals(excepted, bitArray.get(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
81
utils/src/test/java/mc/utils/array/BitLongArrayTest.java
Normal file
81
utils/src/test/java/mc/utils/array/BitLongArrayTest.java
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package mc.utils.array;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.LongBuffer;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class BitLongArrayTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void initTest() {
|
||||||
|
BitArray bitArray = new BitLongArray(13, 1, false);
|
||||||
|
ByteBuffer byteBuffer = bitArray.byteBuffer();
|
||||||
|
|
||||||
|
assertEquals(8, byteBuffer.capacity());
|
||||||
|
assertEquals(8, byteBuffer.limit());
|
||||||
|
assertEquals(0, byteBuffer.position());
|
||||||
|
assertEquals(8, byteBuffer.array().length);
|
||||||
|
|
||||||
|
bitArray = new BitLongArray(13, 5);
|
||||||
|
byteBuffer = bitArray.byteBuffer();
|
||||||
|
|
||||||
|
assertEquals(16, byteBuffer.capacity());
|
||||||
|
assertEquals(16, byteBuffer.limit());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeTest1() {
|
||||||
|
int value = 0b00010000_00000011;
|
||||||
|
long expected = 0b00000000_00000000_00000000_00000000_00000010_00000000_01110000_00000011L;
|
||||||
|
|
||||||
|
BitArray bitArray = new BitLongArray(13, 2);
|
||||||
|
bitArray.put(value);
|
||||||
|
bitArray.put(value);
|
||||||
|
|
||||||
|
LongBuffer longBuffer = bitArray.byteBuffer().asLongBuffer();
|
||||||
|
assertEquals(expected, longBuffer.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeTest2() {
|
||||||
|
int value = 0b00010000_00000011;
|
||||||
|
long expected1 = 0b00000000_00111000_00000001_11000000_00001110_00000000_01110000_00000011L;
|
||||||
|
long expected2 = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001L;
|
||||||
|
|
||||||
|
BitArray bitArray = new BitLongArray(13, 5);
|
||||||
|
bitArray.put(value);
|
||||||
|
bitArray.put(value);
|
||||||
|
bitArray.put(value);
|
||||||
|
bitArray.put(value);
|
||||||
|
bitArray.put(value);
|
||||||
|
|
||||||
|
LongBuffer longBuffer = bitArray.byteBuffer().asLongBuffer();
|
||||||
|
assertEquals(expected1, longBuffer.get(0));
|
||||||
|
assertEquals(expected2, longBuffer.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeOffsetTest() {
|
||||||
|
int value = 0b00010000_00000011;
|
||||||
|
long expected = 0b00000000_00000000_00000000_00000000_00000010_00000000_01100000_00000000;
|
||||||
|
|
||||||
|
BitArray bitArray = new BitLongArray(13, 2);
|
||||||
|
bitArray.put(1, value);
|
||||||
|
|
||||||
|
LongBuffer longBuffer = bitArray.byteBuffer().asLongBuffer();
|
||||||
|
assertEquals(expected, longBuffer.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void readTest() {
|
||||||
|
int excepted = 0b00010000_00000011;
|
||||||
|
|
||||||
|
BitArray bitArray = new BitLongArray(13, 2);
|
||||||
|
bitArray.put(1, excepted);
|
||||||
|
|
||||||
|
assertEquals(excepted, bitArray.get(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user