Minestom/src/main/java/net/minestom/server/utils/Utils.java

204 lines
7.5 KiB
Java
Raw Normal View History

2020-04-24 03:25:58 +02:00
package net.minestom.server.utils;
2019-08-03 15:25:24 +02:00
2020-04-17 01:16:02 +02:00
import io.netty.buffer.ByteBuf;
2020-04-26 19:17:04 +02:00
import net.minestom.server.instance.Chunk;
2020-11-01 22:53:36 +01:00
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.binary.BinaryWriter;
2019-08-03 15:25:24 +02:00
import java.util.UUID;
public final class Utils {
private Utils() {
}
2019-08-03 15:25:24 +02:00
public static int getVarIntSize(int input) {
return (input & 0xFFFFFF80) == 0
? 1 : (input & 0xFFFFC000) == 0
? 2 : (input & 0xFFE00000) == 0
? 3 : (input & 0xF0000000) == 0
? 4 : 5;
}
2020-04-17 01:16:02 +02:00
public static void writeVarIntBuf(ByteBuf buffer, int value) {
do {
byte temp = (byte) (value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
buffer.writeByte(temp);
} while (value != 0);
2020-02-13 15:14:41 +01:00
}
public static void writeVarInt(BinaryWriter writer, int value) {
2019-09-02 06:02:12 +02:00
do {
byte temp = (byte) (value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
2020-04-17 01:16:02 +02:00
writer.writeByte(temp);
2019-09-02 06:02:12 +02:00
} while (value != 0);
}
2020-04-17 01:16:02 +02:00
public static int readVarInt(ByteBuf buffer) {
int numRead = 0;
int result = 0;
byte read;
do {
read = buffer.readByte();
int value = (read & 0b01111111);
result |= (value << (7 * numRead));
numRead++;
if (numRead > 5) {
throw new RuntimeException("VarInt is too big");
}
} while ((read & 0b10000000) != 0);
return result;
2019-08-03 15:25:24 +02:00
}
public static void writeVarLong(BinaryWriter writer, long value) {
2020-05-26 19:22:47 +02:00
do {
byte temp = (byte) (value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
writer.writeByte(temp);
} while (value != 0);
}
public static int[] uuidToIntArray(UUID uuid) {
int[] array = new int[4];
final long uuidMost = uuid.getMostSignificantBits();
final long uuidLeast = uuid.getLeastSignificantBits();
array[0] = (int) (uuidMost >> 32);
array[1] = (int) uuidMost;
array[2] = (int) (uuidLeast >> 32);
array[3] = (int) uuidLeast;
return array;
}
public static UUID intArrayToUuid(int[] array) {
final long uuidMost = (long) array[0] << 32 | array[1] & 0xFFFFFFFFL;
final long uuidLeast = (long) array[2] << 32 | array[3] & 0xFFFFFFFFL;
return new UUID(uuidMost, uuidLeast);
}
2020-07-06 12:39:48 +02:00
private static final int[] MAGIC = {
-1, -1, 0, Integer.MIN_VALUE, 0, 0, 1431655765, 1431655765, 0, Integer.MIN_VALUE,
0, 1, 858993459, 858993459, 0, 715827882, 715827882, 0, 613566756, 613566756,
0, Integer.MIN_VALUE, 0, 2, 477218588, 477218588, 0, 429496729, 429496729, 0,
390451572, 390451572, 0, 357913941, 357913941, 0, 330382099, 330382099, 0, 306783378,
306783378, 0, 286331153, 286331153, 0, Integer.MIN_VALUE, 0, 3, 252645135, 252645135,
0, 238609294, 238609294, 0, 226050910, 226050910, 0, 214748364, 214748364, 0,
204522252, 204522252, 0, 195225786, 195225786, 0, 186737708, 186737708, 0, 178956970,
178956970, 0, 171798691, 171798691, 0, 165191049, 165191049, 0, 159072862, 159072862,
0, 153391689, 153391689, 0, 148102320, 148102320, 0, 143165576, 143165576, 0,
138547332, 138547332, 0, Integer.MIN_VALUE, 0, 4, 130150524, 130150524, 0, 126322567,
126322567, 0, 122713351, 122713351, 0, 119304647, 119304647, 0, 116080197, 116080197,
0, 113025455, 113025455, 0, 110127366, 110127366, 0, 107374182, 107374182, 0,
104755299, 104755299, 0, 102261126, 102261126, 0, 99882960, 99882960, 0, 97612893,
97612893, 0, 95443717, 95443717, 0, 93368854, 93368854, 0, 91382282, 91382282,
0, 89478485, 89478485, 0, 87652393, 87652393, 0, 85899345, 85899345, 0,
84215045, 84215045, 0, 82595524, 82595524, 0, 81037118, 81037118, 0, 79536431,
79536431, 0, 78090314, 78090314, 0, 76695844, 76695844, 0, 75350303, 75350303,
0, 74051160, 74051160, 0, 72796055, 72796055, 0, 71582788, 71582788, 0,
70409299, 70409299, 0, 69273666, 69273666, 0, 68174084, 68174084, 0, Integer.MIN_VALUE,
0, 5};
2020-11-11 17:13:36 +01:00
public static void writeBlocks(ByteBuf buffer, short[] palette, long[] blocksId, int bitsPerEntry) {
2020-11-01 22:53:36 +01:00
/*short count = 0;
2020-07-06 12:39:48 +02:00
for (short id : blocksId)
if (id != 0)
2020-11-01 22:53:36 +01:00
count++;*/
2020-07-06 12:39:48 +02:00
2020-11-01 22:53:36 +01:00
//buffer.writeShort(count);
buffer.writeShort(200);
buffer.writeByte((byte) bitsPerEntry);
2020-11-01 22:53:36 +01:00
2020-11-11 17:13:36 +01:00
// Palette
if (bitsPerEntry < 9) {
// Palette has to exist
writeVarIntBuf(buffer, palette.length);
for (short paletteValue : palette) {
writeVarIntBuf(buffer, paletteValue);
}
}
2020-11-01 22:53:36 +01:00
final long[] data = blocksId;//encodeBlocksTEST(bitsPerEntry);
writeVarIntBuf(buffer, data.length);
for (long datum : data) {
buffer.writeLong(datum);
}
}
public synchronized static long[] encodeBlocksTEST(int bitsPerEntry) {
//long test = (Block.TORCH.getBlockId() << (64 - 50 - bitsPerEntry + 1));
//System.out.println("BINARY: 0b" + Long.toBinaryString(test) + " " + (64 - 50 - bitsPerEntry + 1));
final int blockCount = 16 * 16 * 16; // A whole chunk section
final int longSize = Long.SIZE; // 64
final char valuesPerLong = (char) (longSize / bitsPerEntry);
final int arraySize = blockCount / valuesPerLong;
long[] data = new long[arraySize];
2020-11-11 17:13:36 +01:00
data[0] = 0b000000010001L;
data[1] = 0b000000010001L;
if (true) {
return data;
}
2020-11-01 22:53:36 +01:00
2020-07-06 12:39:48 +02:00
for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
for (int z = 0; z < Chunk.CHUNK_SIZE_Z; z++) {
2020-11-01 22:53:36 +01:00
final long blockId = x % 2 == 0 && z % 2 == 0 ? Block.AIR.getBlockId() : Block.LAVA.getBlockId();
int sectionIndex = (((y * 16) + z) * 16) + x;
final int index = sectionIndex / valuesPerLong;
final int bitIndex = sectionIndex % valuesPerLong * bitsPerEntry;
data[index] |= (blockId << bitIndex);
2020-07-06 12:39:48 +02:00
}
}
}
2020-11-01 22:53:36 +01:00
return data;
}
private static String binary(long value) {
return "0b" + Long.toBinaryString(value);
2020-07-06 12:39:48 +02:00
}
2020-06-25 21:05:58 +02:00
public static long[] encodeBlocks(int[] blocks, int bitsPerEntry) {
final long maxEntryValue = (1L << bitsPerEntry) - 1;
final char valuesPerLong = (char) (64 / bitsPerEntry);
final int magicIndex = 3 * (valuesPerLong - 1);
final long divideMul = Integer.toUnsignedLong(MAGIC[magicIndex]);
final long divideAdd = Integer.toUnsignedLong(MAGIC[magicIndex + 1]);
final int divideShift = MAGIC[magicIndex + 2];
final int size = (blocks.length + valuesPerLong - 1) / valuesPerLong;
2020-06-25 21:05:58 +02:00
long[] data = new long[size];
for (int i = 0; i < blocks.length; i++) {
final long value = blocks[i];
final int cellIndex = (int) (i * divideMul + divideAdd >> 32L >> divideShift);
final int bitIndex = (i - cellIndex * valuesPerLong) * bitsPerEntry;
2020-06-25 21:05:58 +02:00
data[cellIndex] = data[cellIndex] & ~(maxEntryValue << bitIndex) | (value & maxEntryValue) << bitIndex;
}
2019-08-10 04:16:01 +02:00
2020-06-25 21:05:58 +02:00
return data;
}
2020-11-01 22:53:36 +01:00
2019-08-03 15:25:24 +02:00
}