Minestom/src/main/java/fr/themode/minestom/utils/Utils.java

243 lines
7.5 KiB
Java
Raw Normal View History

2019-08-03 15:25:24 +02:00
package fr.themode.minestom.utils;
import fr.adamaq01.ozao.net.Buffer;
2019-08-22 14:52:32 +02:00
import fr.themode.minestom.chat.Chat;
2019-08-13 17:52:09 +02:00
import fr.themode.minestom.item.ItemStack;
2019-09-02 06:02:12 +02:00
import fr.themode.minestom.net.ConnectionUtils;
import fr.themode.minestom.utils.consumer.StringConsumer;
import simplenet.Client;
import simplenet.packet.Packet;
2019-08-03 15:25:24 +02:00
import java.io.UnsupportedEncodingException;
2019-09-02 06:02:12 +02:00
import java.util.function.Consumer;
2019-08-03 15:25:24 +02:00
public class Utils {
2019-09-02 06:02:12 +02:00
public static void writeString(Packet packet, String value) {
2019-08-03 15:25:24 +02:00
byte[] bytes = new byte[0];
try {
bytes = value.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (bytes.length > 32767) {
System.out.println("String too big (was " + value.length() + " bytes encoded, max " + 32767 + ")");
} else {
2019-09-02 06:02:12 +02:00
writeVarInt(packet, bytes.length);
packet.putBytes(bytes);
2019-08-03 15:25:24 +02:00
}
}
2019-09-02 06:02:12 +02:00
public static void readString(Client client, StringConsumer consumer) {
ConnectionUtils.readVarInt(client, length -> {
int stringLength = Utils.lengthVarInt(length) + length;
client.readBytes(length, bytes -> {
try {
consumer.accept(new String(bytes, "UTF-8"), stringLength);
} catch (UnsupportedEncodingException e) {
consumer.accept(null, stringLength);
e.printStackTrace();
}
});
});
2019-08-03 15:25:24 +02:00
}
2019-09-02 06:02:12 +02:00
public static void writeVarIntBuffer(Buffer buffer, int value) {
2019-08-03 15:25:24 +02:00
do {
byte temp = (byte) (value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
buffer.putByte(temp);
} while (value != 0);
}
2019-09-02 06:02:12 +02:00
public static void writeVarInt(Packet packet, int value) {
do {
byte temp = (byte) (value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
packet.putByte(temp);
} while (value != 0);
}
public static int readVarInt(Client client) {
2019-08-03 15:25:24 +02:00
int numRead = 0;
int result = 0;
byte read;
do {
2019-09-02 06:02:12 +02:00
read = client.readByte();
2019-08-03 15:25:24 +02:00
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;
}
// ??
public static int lengthVarInt(int value) {
int i = 0;
do {
i++;
byte temp = (byte) (value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
2019-08-07 03:42:48 +02:00
} while (value != 0);
return i;
}
public static int lengthVarLong(long value) {
int i = 0;
do {
i++;
byte temp = (byte) (value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
2019-08-03 15:25:24 +02:00
} while (value != 0);
return i;
}
2019-09-02 06:02:12 +02:00
public static void writeVarLong(Packet packet, long value) {
2019-08-03 15:25:24 +02:00
do {
byte temp = (byte) (value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
2019-09-02 06:02:12 +02:00
packet.putByte(temp);
2019-08-03 15:25:24 +02:00
} while (value != 0);
}
2019-09-02 06:02:12 +02:00
public static long readVarLong(Client client) {
2019-08-03 15:25:24 +02:00
int numRead = 0;
long result = 0;
byte read;
do {
2019-09-02 06:02:12 +02:00
read = client.readByte();
2019-08-03 15:25:24 +02:00
int value = (read & 0b01111111);
result |= (value << (7 * numRead));
numRead++;
if (numRead > 10) {
throw new RuntimeException("VarLong is too big");
}
} while ((read & 0b10000000) != 0);
return result;
}
2019-09-02 06:02:12 +02:00
public static void writePosition(Packet packet, int x, int y, int z) {
packet.putLong(SerializerUtils.positionToLong(x, y, z));
2019-08-18 20:38:09 +02:00
}
2019-09-02 06:02:12 +02:00
public static void writePosition(Packet packet, BlockPosition blockPosition) {
writePosition(packet, blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
2019-08-12 08:30:59 +02:00
}
2019-09-02 06:02:12 +02:00
public static void readPosition(Client client, Consumer<BlockPosition> consumer) {
client.readLong(value -> {
consumer.accept(SerializerUtils.longToBlockPosition(value));
});
2019-08-03 15:25:24 +02:00
}
2019-09-02 06:02:12 +02:00
public static void writeItemStack(Packet packet, ItemStack itemStack) {
2019-08-13 17:52:09 +02:00
if (itemStack == null) {
2019-09-02 06:02:12 +02:00
packet.putBoolean(false);
2019-08-13 17:52:09 +02:00
} else {
2019-09-02 06:02:12 +02:00
packet.putBoolean(true);
Utils.writeVarInt(packet, itemStack.getMaterial().getId());
packet.putByte(itemStack.getAmount());
2019-08-22 14:52:32 +02:00
2019-09-02 06:02:12 +02:00
packet.putByte((byte) 0x0A); // Compound
packet.putShort((short) 0);
2019-08-22 14:52:32 +02:00
// Unbreakable
if (itemStack.isUnbreakable()) {
2019-09-02 06:02:12 +02:00
packet.putByte((byte) 0x03); // Integer
packet.putString("Unbreakable");
packet.putInt(1);
2019-08-22 14:52:32 +02:00
}
// Display
2019-09-02 06:02:12 +02:00
packet.putByte((byte) 0x0A); // Compound
packet.putString("display");
2019-08-22 14:52:32 +02:00
if (itemStack.getDisplayName() != null) {
2019-09-02 06:02:12 +02:00
packet.putByte((byte) 0x08);
packet.putString("Name");
packet.putString(Chat.rawText(itemStack.getDisplayName()));
2019-08-22 14:52:32 +02:00
}
// TODO lore
2019-09-02 06:02:12 +02:00
packet.putByte((byte) 0x08);
packet.putString("Lore");
packet.putString(Chat.rawText("a line"));
2019-08-22 14:52:32 +02:00
2019-09-02 06:02:12 +02:00
packet.putByte((byte) 0); // End display compound
2019-08-22 14:52:32 +02:00
2019-09-02 06:02:12 +02:00
packet.putByte((byte) 0); // End nbt
2019-08-13 17:52:09 +02:00
}
2019-08-22 14:52:32 +02:00
2019-08-13 17:52:09 +02:00
}
2019-08-21 16:50:52 +02:00
public static void writeBlocks(Buffer buffer, short[] blocksId, int bitsPerEntry) {
short count = 0;
for (short id : blocksId)
if (id != 0)
count++;
buffer.putShort(count);
2019-08-10 04:16:01 +02:00
buffer.putByte((byte) bitsPerEntry);
int[] blocksData = new int[16 * 16 * 16];
for (int y = 0; y < 16; y++) {
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
int sectionIndex = (((y * 16) + x) * 16) + z;
int index = y << 8 | z << 4 | x;
2019-08-18 20:38:09 +02:00
blocksData[index] = blocksId[sectionIndex];
2019-08-10 04:16:01 +02:00
}
}
}
long[] data = encodeBlocks(blocksData, 14);
2019-09-02 06:02:12 +02:00
writeVarIntBuffer(buffer, data.length);
2019-08-10 04:16:01 +02:00
for (int i = 0; i < data.length; i++) {
buffer.putLong(data[i]);
}
}
public static long[] encodeBlocks(int[] blocks, int bitsPerEntry) {
long maxEntryValue = (1L << bitsPerEntry) - 1;
int length = (int) Math.ceil(blocks.length * bitsPerEntry / 64.0);
long[] data = new long[length];
for (int index = 0; index < blocks.length; index++) {
int value = blocks[index];
int bitIndex = index * bitsPerEntry;
int startIndex = bitIndex / 64;
int endIndex = ((index + 1) * bitsPerEntry - 1) / 64;
int startBitSubIndex = bitIndex % 64;
data[startIndex] = data[startIndex] & ~(maxEntryValue << startBitSubIndex) | ((long) value & maxEntryValue) << startBitSubIndex;
if (startIndex != endIndex) {
int endBitSubIndex = 64 - startBitSubIndex;
data[endIndex] = data[endIndex] >>> endBitSubIndex << endBitSubIndex | ((long) value & maxEntryValue) >> endBitSubIndex;
}
}
return data;
}
2019-08-03 15:25:24 +02:00
}