mirror of
https://github.com/Nan1t/NanoLimbo.git
synced 2025-07-09 11:30:13 +02:00
commit
93ad159833
@ -25,9 +25,10 @@ dependencies {
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
|
||||
|
||||
implementation 'org.spongepowered:configurate-yaml:4.1.2'
|
||||
implementation 'io.netty:netty-all:4.1.99.Final'
|
||||
implementation 'io.netty:netty-all:4.1.101.Final'
|
||||
implementation 'net.kyori:adventure-nbt:4.14.0'
|
||||
implementation 'com.grack:nanojson:1.8'
|
||||
implementation 'com.google.code.gson:gson:2.10.1'
|
||||
}
|
||||
|
||||
buildConfig {
|
||||
|
@ -30,6 +30,7 @@ import ua.nanit.limbo.connection.pipeline.PacketDecoder;
|
||||
import ua.nanit.limbo.connection.pipeline.PacketEncoder;
|
||||
import ua.nanit.limbo.protocol.ByteMessage;
|
||||
import ua.nanit.limbo.protocol.Packet;
|
||||
import ua.nanit.limbo.protocol.PacketSnapshot;
|
||||
import ua.nanit.limbo.protocol.packets.login.PacketDisconnect;
|
||||
import ua.nanit.limbo.protocol.packets.play.PacketKeepAlive;
|
||||
import ua.nanit.limbo.protocol.registry.State;
|
||||
@ -175,6 +176,14 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
||||
if (PacketSnapshots.PACKET_HEADER_AND_FOOTER != null && clientVersion.moreOrEqual(Version.V1_8))
|
||||
writePacket(PacketSnapshots.PACKET_HEADER_AND_FOOTER);
|
||||
|
||||
if (clientVersion.moreOrEqual(Version.V1_20_3)) {
|
||||
writePacket(PacketSnapshots.PACKET_START_WAITING_CHUNKS);
|
||||
|
||||
for (PacketSnapshot chunk : PacketSnapshots.PACKETS_EMPTY_CHUNKS) {
|
||||
writePacket(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
sendKeepAlive();
|
||||
};
|
||||
|
||||
|
@ -25,9 +25,12 @@ import ua.nanit.limbo.protocol.packets.login.PacketLoginSuccess;
|
||||
import ua.nanit.limbo.protocol.packets.play.*;
|
||||
import ua.nanit.limbo.server.LimboServer;
|
||||
import ua.nanit.limbo.server.data.Title;
|
||||
import ua.nanit.limbo.util.NbtMessageUtil;
|
||||
import ua.nanit.limbo.util.UuidUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@ -59,6 +62,9 @@ public final class PacketSnapshots {
|
||||
public static PacketSnapshot PACKET_REGISTRY_DATA;
|
||||
public static PacketSnapshot PACKET_FINISH_CONFIGURATION;
|
||||
|
||||
public static List<PacketSnapshot> PACKETS_EMPTY_CHUNKS;
|
||||
public static PacketSnapshot PACKET_START_WAITING_CHUNKS;
|
||||
|
||||
private PacketSnapshots() { }
|
||||
|
||||
public static void initPackets(LimboServer server) {
|
||||
@ -121,8 +127,8 @@ public final class PacketSnapshots {
|
||||
|
||||
if (server.getConfig().isUseHeaderAndFooter()) {
|
||||
PacketPlayerListHeader header = new PacketPlayerListHeader();
|
||||
header.setHeader(server.getConfig().getPlayerListHeader());
|
||||
header.setFooter(server.getConfig().getPlayerListFooter());
|
||||
header.setHeader(NbtMessageUtil.create(server.getConfig().getPlayerListHeader()));
|
||||
header.setFooter(NbtMessageUtil.create(server.getConfig().getPlayerListFooter()));
|
||||
PACKET_HEADER_AND_FOOTER = PacketSnapshot.of(header);
|
||||
}
|
||||
|
||||
@ -135,7 +141,7 @@ public final class PacketSnapshots {
|
||||
|
||||
if (server.getConfig().isUseJoinMessage()) {
|
||||
PacketChatMessage joinMessage = new PacketChatMessage();
|
||||
joinMessage.setJsonData(server.getConfig().getJoinMessage());
|
||||
joinMessage.setMessage(NbtMessageUtil.create(server.getConfig().getJoinMessage()));
|
||||
joinMessage.setPosition(PacketChatMessage.PositionLegacy.SYSTEM_MESSAGE);
|
||||
joinMessage.setSender(UUID.randomUUID());
|
||||
PACKET_JOIN_MESSAGE = PacketSnapshot.of(joinMessage);
|
||||
@ -188,5 +194,27 @@ public final class PacketSnapshots {
|
||||
|
||||
PACKET_REGISTRY_DATA = PacketSnapshot.of(packetRegistryData);
|
||||
PACKET_FINISH_CONFIGURATION = PacketSnapshot.of(new PacketFinishConfiguration());
|
||||
|
||||
PacketGameEvent packetGameEvent = new PacketGameEvent();
|
||||
packetGameEvent.setType((byte) 13); // Waiting for chunks type
|
||||
packetGameEvent.setValue(0);
|
||||
PACKET_START_WAITING_CHUNKS = PacketSnapshot.of(packetGameEvent);
|
||||
|
||||
int chunkXOffset = (int) 0 >> 4; // Default x position is 0
|
||||
int chunkZOffset = (int) 0 >> 4; // Default z position is 0
|
||||
int chunkEdgeSize = 1; // TODO Make configurable?
|
||||
|
||||
List<PacketSnapshot> emptyChunks = new ArrayList<>();
|
||||
// Make multiple chunks for edges
|
||||
for (int chunkX = chunkXOffset - chunkEdgeSize; chunkX <= chunkXOffset + chunkEdgeSize; ++chunkX) {
|
||||
for (int chunkZ = chunkZOffset - chunkEdgeSize; chunkZ <= chunkZOffset + chunkEdgeSize; ++chunkZ) {
|
||||
PacketEmptyChunk packetEmptyChunk = new PacketEmptyChunk();
|
||||
packetEmptyChunk.setX(chunkX);
|
||||
packetEmptyChunk.setZ(chunkZ);
|
||||
|
||||
emptyChunks.add(PacketSnapshot.of(packetEmptyChunk));
|
||||
}
|
||||
}
|
||||
PACKETS_EMPTY_CHUNKS = emptyChunks;
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,8 @@ import io.netty.buffer.*;
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
import io.netty.handler.codec.EncoderException;
|
||||
import io.netty.util.ByteProcessor;
|
||||
import net.kyori.adventure.nbt.BinaryTagIO;
|
||||
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.nbt.*;
|
||||
import ua.nanit.limbo.protocol.registry.Version;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -194,16 +193,63 @@ public class ByteMessage extends ByteBuf {
|
||||
}
|
||||
}
|
||||
|
||||
public void writeNamelessCompoundTag(CompoundBinaryTag compoundTag) {
|
||||
public void writeNamelessCompoundTag(BinaryTag binaryTag) {
|
||||
try (ByteBufOutputStream stream = new ByteBufOutputStream(buf)) {
|
||||
stream.writeByte(10); // CompoundTag ID
|
||||
BinaryTagTypes.COMPOUND.write(compoundTag, stream);
|
||||
stream.writeByte(binaryTag.type().id());
|
||||
|
||||
// TODO Find a way to improve this...
|
||||
if (binaryTag instanceof CompoundBinaryTag) {
|
||||
CompoundBinaryTag tag = (CompoundBinaryTag) binaryTag;
|
||||
tag.type().write(tag, stream);
|
||||
}
|
||||
else if (binaryTag instanceof ByteBinaryTag) {
|
||||
ByteBinaryTag tag = (ByteBinaryTag) binaryTag;
|
||||
tag.type().write(tag, stream);
|
||||
}
|
||||
else if (binaryTag instanceof ShortBinaryTag) {
|
||||
ShortBinaryTag tag = (ShortBinaryTag) binaryTag;
|
||||
tag.type().write(tag, stream);
|
||||
}
|
||||
else if (binaryTag instanceof IntBinaryTag) {
|
||||
IntBinaryTag tag = (IntBinaryTag) binaryTag;
|
||||
tag.type().write(tag, stream);
|
||||
}
|
||||
else if (binaryTag instanceof LongBinaryTag) {
|
||||
LongBinaryTag tag = (LongBinaryTag) binaryTag;
|
||||
tag.type().write(tag, stream);
|
||||
}
|
||||
else if (binaryTag instanceof DoubleBinaryTag) {
|
||||
DoubleBinaryTag tag = (DoubleBinaryTag) binaryTag;
|
||||
tag.type().write(tag, stream);
|
||||
}
|
||||
else if (binaryTag instanceof StringBinaryTag) {
|
||||
StringBinaryTag tag = (StringBinaryTag) binaryTag;
|
||||
tag.type().write(tag, stream);
|
||||
}
|
||||
else if (binaryTag instanceof ListBinaryTag) {
|
||||
ListBinaryTag tag = (ListBinaryTag) binaryTag;
|
||||
tag.type().write(tag, stream);
|
||||
}
|
||||
else if (binaryTag instanceof EndBinaryTag) {
|
||||
EndBinaryTag tag = (EndBinaryTag) binaryTag;
|
||||
tag.type().write(tag, stream);
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new EncoderException("Cannot write NBT CompoundTag");
|
||||
}
|
||||
}
|
||||
|
||||
public void writeNbtMessage(NbtMessage nbtMessage, Version version) {
|
||||
if (version.moreOrEqual(Version.V1_20_3)) {
|
||||
writeNamelessCompoundTag(nbtMessage.getTag());
|
||||
}
|
||||
else {
|
||||
writeString(nbtMessage.getJson());
|
||||
}
|
||||
}
|
||||
|
||||
public <E extends Enum<E>> void writeEnumSet(EnumSet<E> enumset, Class<E> oclass) {
|
||||
E[] enums = oclass.getEnumConstants();
|
||||
BitSet bits = new BitSet(enums.length);
|
||||
|
30
src/main/java/ua/nanit/limbo/protocol/NbtMessage.java
Normal file
30
src/main/java/ua/nanit/limbo/protocol/NbtMessage.java
Normal file
@ -0,0 +1,30 @@
|
||||
package ua.nanit.limbo.protocol;
|
||||
|
||||
import net.kyori.adventure.nbt.BinaryTag;
|
||||
|
||||
public class NbtMessage {
|
||||
|
||||
private String json;
|
||||
private BinaryTag tag;
|
||||
|
||||
public NbtMessage(String json, BinaryTag tag) {
|
||||
this.json = json;
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getJson() {
|
||||
return json;
|
||||
}
|
||||
|
||||
public void setJson(String json) {
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
public BinaryTag getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(BinaryTag tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
}
|
@ -49,7 +49,7 @@ public class PacketBossBar implements PacketOut {
|
||||
public void encode(ByteMessage msg, Version version) {
|
||||
msg.writeUuid(uuid);
|
||||
msg.writeVarInt(0); // Create bossbar
|
||||
msg.writeString(bossBar.getText());
|
||||
msg.writeNbtMessage(bossBar.getText(), version);
|
||||
msg.writeFloat(bossBar.getHealth());
|
||||
msg.writeVarInt(bossBar.getColor().getIndex());
|
||||
msg.writeVarInt(bossBar.getDivision().getIndex());
|
||||
|
@ -18,6 +18,7 @@
|
||||
package ua.nanit.limbo.protocol.packets.play;
|
||||
|
||||
import ua.nanit.limbo.protocol.ByteMessage;
|
||||
import ua.nanit.limbo.protocol.NbtMessage;
|
||||
import ua.nanit.limbo.protocol.PacketOut;
|
||||
import ua.nanit.limbo.protocol.registry.Version;
|
||||
|
||||
@ -25,12 +26,12 @@ import java.util.UUID;
|
||||
|
||||
public class PacketChatMessage implements PacketOut {
|
||||
|
||||
private String jsonData;
|
||||
private NbtMessage message;
|
||||
private PositionLegacy position;
|
||||
private UUID sender;
|
||||
|
||||
public void setJsonData(String jsonData) {
|
||||
this.jsonData = jsonData;
|
||||
public void setMessage(NbtMessage message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public void setPosition(PositionLegacy position) {
|
||||
@ -43,7 +44,7 @@ public class PacketChatMessage implements PacketOut {
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg, Version version) {
|
||||
msg.writeString(jsonData);
|
||||
msg.writeNbtMessage(message, version);
|
||||
if (version.moreOrEqual(Version.V1_19_1)) {
|
||||
msg.writeBoolean(position.index == PositionLegacy.ACTION_BAR.index);
|
||||
} else if (version.moreOrEqual(Version.V1_19)) {
|
||||
|
@ -0,0 +1,47 @@
|
||||
package ua.nanit.limbo.protocol.packets.play;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.nbt.LongArrayBinaryTag;
|
||||
import ua.nanit.limbo.protocol.ByteMessage;
|
||||
import ua.nanit.limbo.protocol.PacketOut;
|
||||
import ua.nanit.limbo.protocol.registry.Version;
|
||||
|
||||
public class PacketEmptyChunk implements PacketOut {
|
||||
|
||||
private int x;
|
||||
private int z;
|
||||
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public void setZ(int z) {
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg, Version version) {
|
||||
msg.writeInt(x);
|
||||
msg.writeInt(z);
|
||||
|
||||
LongArrayBinaryTag longArrayTag = LongArrayBinaryTag.longArrayBinaryTag(new long[37]);
|
||||
CompoundBinaryTag tag = CompoundBinaryTag.builder()
|
||||
.put("MOTION_BLOCKING", longArrayTag).build();
|
||||
CompoundBinaryTag rootTag = CompoundBinaryTag.builder()
|
||||
.put("root", tag).build();
|
||||
msg.writeNamelessCompoundTag(rootTag);
|
||||
|
||||
byte[] sectionData = new byte[]{0, 0, 0, 0, 0, 0, 1, 0};
|
||||
msg.writeVarInt(sectionData.length * 16);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
msg.writeBytes(sectionData);
|
||||
}
|
||||
|
||||
msg.writeVarInt(0);
|
||||
|
||||
byte[] lightData = new byte[]{1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, -1, -1, 0, 0};
|
||||
msg.ensureWritable(lightData.length);
|
||||
msg.writeBytes(lightData, 1, lightData.length - 1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package ua.nanit.limbo.protocol.packets.play;
|
||||
|
||||
import ua.nanit.limbo.protocol.ByteMessage;
|
||||
import ua.nanit.limbo.protocol.PacketOut;
|
||||
import ua.nanit.limbo.protocol.registry.Version;
|
||||
|
||||
public class PacketGameEvent implements PacketOut {
|
||||
|
||||
private byte type;
|
||||
private float value;
|
||||
|
||||
public void setType(byte type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setValue(float value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg, Version version) {
|
||||
msg.writeByte(type);
|
||||
msg.writeFloat(value);
|
||||
}
|
||||
}
|
@ -18,25 +18,26 @@
|
||||
package ua.nanit.limbo.protocol.packets.play;
|
||||
|
||||
import ua.nanit.limbo.protocol.ByteMessage;
|
||||
import ua.nanit.limbo.protocol.NbtMessage;
|
||||
import ua.nanit.limbo.protocol.PacketOut;
|
||||
import ua.nanit.limbo.protocol.registry.Version;
|
||||
|
||||
public class PacketPlayerListHeader implements PacketOut {
|
||||
|
||||
private String header;
|
||||
private String footer;
|
||||
private NbtMessage header;
|
||||
private NbtMessage footer;
|
||||
|
||||
public void setHeader(String header) {
|
||||
public void setHeader(NbtMessage header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public void setFooter(String footer) {
|
||||
public void setFooter(NbtMessage footer) {
|
||||
this.footer = footer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg, Version version) {
|
||||
msg.writeString(header);
|
||||
msg.writeString(footer);
|
||||
msg.writeNbtMessage(header, version);
|
||||
msg.writeNbtMessage(footer, version);
|
||||
}
|
||||
}
|
||||
|
@ -18,20 +18,21 @@
|
||||
package ua.nanit.limbo.protocol.packets.play;
|
||||
|
||||
import ua.nanit.limbo.protocol.ByteMessage;
|
||||
import ua.nanit.limbo.protocol.NbtMessage;
|
||||
import ua.nanit.limbo.protocol.PacketOut;
|
||||
import ua.nanit.limbo.protocol.registry.Version;
|
||||
|
||||
public class PacketTitleSetSubTitle implements PacketOut {
|
||||
|
||||
private String subtitle;
|
||||
private NbtMessage subtitle;
|
||||
|
||||
public void setSubtitle(String subtitle) {
|
||||
public void setSubtitle(NbtMessage subtitle) {
|
||||
this.subtitle = subtitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg, Version version) {
|
||||
msg.writeString(subtitle);
|
||||
msg.writeNbtMessage(subtitle, version);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,20 +18,21 @@
|
||||
package ua.nanit.limbo.protocol.packets.play;
|
||||
|
||||
import ua.nanit.limbo.protocol.ByteMessage;
|
||||
import ua.nanit.limbo.protocol.NbtMessage;
|
||||
import ua.nanit.limbo.protocol.PacketOut;
|
||||
import ua.nanit.limbo.protocol.registry.Version;
|
||||
|
||||
public class PacketTitleSetTitle implements PacketOut {
|
||||
|
||||
private String title;
|
||||
private NbtMessage title;
|
||||
|
||||
public void setTitle(String title) {
|
||||
public void setTitle(NbtMessage title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg, Version version) {
|
||||
msg.writeString(title);
|
||||
msg.writeNbtMessage(title, version);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public enum State {
|
||||
);
|
||||
serverBound.register(
|
||||
PacketLoginAcknowledged::new,
|
||||
map(0x03, V1_20_2, V1_20_2)
|
||||
map(0x03, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketDisconnect::new,
|
||||
map(0x00, Version.getMin(), Version.getMax())
|
||||
@ -83,36 +83,36 @@ public enum State {
|
||||
{
|
||||
clientBound.register(
|
||||
PacketPluginMessage::new,
|
||||
map(0x00, V1_20_2, V1_20_2)
|
||||
map(0x00, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(
|
||||
PacketDisconnect::new,
|
||||
map(0x01, V1_20_2, V1_20_2)
|
||||
map(0x01, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(
|
||||
PacketFinishConfiguration::new,
|
||||
map(0x02, V1_20_2, V1_20_2)
|
||||
map(0x02, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(
|
||||
PacketKeepAlive::new,
|
||||
map(0x03, V1_20_2, V1_20_2)
|
||||
map(0x03, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(
|
||||
PacketRegistryData::new,
|
||||
map(0x05, V1_20_2, V1_20_2)
|
||||
map(0x05, V1_20_2, V1_20_3)
|
||||
);
|
||||
|
||||
serverBound.register(
|
||||
PacketPluginMessage::new,
|
||||
map(0x01, V1_20_2, V1_20_2)
|
||||
map(0x01, V1_20_2, V1_20_3)
|
||||
);
|
||||
serverBound.register(
|
||||
PacketFinishConfiguration::new,
|
||||
map(0x02, V1_20_2, V1_20_2)
|
||||
map(0x02, V1_20_2, V1_20_3)
|
||||
);
|
||||
serverBound.register(
|
||||
PacketKeepAlive::new,
|
||||
map(0x03, V1_20_2, V1_20_2)
|
||||
map(0x03, V1_20_2, V1_20_3)
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -131,7 +131,8 @@ public enum State {
|
||||
map(0x12, V1_19_1, V1_19_1),
|
||||
map(0x11, V1_19_3, V1_19_3),
|
||||
map(0x12, V1_19_4, V1_20),
|
||||
map(0x14, V1_20_2, V1_20_2)
|
||||
map(0x14, V1_20_2, V1_20_2),
|
||||
map(0x15, V1_20_3, V1_20_3)
|
||||
);
|
||||
|
||||
clientBound.register(PacketDeclareCommands::new,
|
||||
@ -143,7 +144,7 @@ public enum State {
|
||||
map(0x0F, V1_19, V1_19_1),
|
||||
map(0x0E, V1_19_3, V1_19_3),
|
||||
map(0x10, V1_19_4, V1_20),
|
||||
map(0x11, V1_20_2, V1_20_2)
|
||||
map(0x11, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketJoinGame::new,
|
||||
map(0x01, V1_7_2, V1_8),
|
||||
@ -157,7 +158,7 @@ public enum State {
|
||||
map(0x25, V1_19_1, V1_19_1),
|
||||
map(0x24, V1_19_3, V1_19_3),
|
||||
map(0x28, V1_19_4, V1_20),
|
||||
map(0x29, V1_20_2, V1_20_2)
|
||||
map(0x29, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketPluginMessage::new,
|
||||
map(0x19, V1_13, V1_13_2),
|
||||
@ -170,7 +171,7 @@ public enum State {
|
||||
map(0x16, V1_19_1, V1_19_1),
|
||||
map(0x15, V1_19_3, V1_19_3),
|
||||
map(0x17, V1_19_4, V1_20),
|
||||
map(0x18, V1_20_2, V1_20_2)
|
||||
map(0x18, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketPlayerAbilities::new,
|
||||
map(0x39, V1_7_2, V1_8),
|
||||
@ -186,7 +187,7 @@ public enum State {
|
||||
map(0x31, V1_19_1, V1_19_1),
|
||||
map(0x30, V1_19_3, V1_19_3),
|
||||
map(0x34, V1_19_4, V1_20),
|
||||
map(0x36, V1_20_2, V1_20_2)
|
||||
map(0x36, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketPlayerPositionAndLook::new,
|
||||
map(0x08, V1_7_2, V1_8),
|
||||
@ -202,7 +203,7 @@ public enum State {
|
||||
map(0x39, V1_19_1, V1_19_1),
|
||||
map(0x38, V1_19_3, V1_19_3),
|
||||
map(0x3C, V1_19_4, V1_20),
|
||||
map(0x3E, V1_20_2, V1_20_2)
|
||||
map(0x3E, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketKeepAlive::new,
|
||||
map(0x00, V1_7_2, V1_8),
|
||||
@ -217,7 +218,7 @@ public enum State {
|
||||
map(0x20, V1_19_1, V1_19_1),
|
||||
map(0x1F, V1_19_3, V1_19_3),
|
||||
map(0x23, V1_19_4, V1_20),
|
||||
map(0x24, V1_20_2, V1_20_2)
|
||||
map(0x24, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketChatMessage::new,
|
||||
map(0x02, V1_7_2, V1_8),
|
||||
@ -230,7 +231,8 @@ public enum State {
|
||||
map(0x62, V1_19_1, V1_19_1),
|
||||
map(0x60, V1_19_3, V1_19_3),
|
||||
map(0x64, V1_19_4, V1_20),
|
||||
map(0x67, V1_20_2, V1_20_2)
|
||||
map(0x67, V1_20_2, V1_20_2),
|
||||
map(0x69, V1_20_3, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketBossBar::new,
|
||||
map(0x0C, V1_9, V1_14_4),
|
||||
@ -239,7 +241,7 @@ public enum State {
|
||||
map(0x0D, V1_17, V1_18_2),
|
||||
map(0x0A, V1_19, V1_19_3),
|
||||
map(0x0B, V1_19_4, V1_20),
|
||||
map(0x0A, V1_20_2, V1_20_2)
|
||||
map(0x0A, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketPlayerInfo::new,
|
||||
map(0x38, V1_7_2, V1_8),
|
||||
@ -255,7 +257,7 @@ public enum State {
|
||||
map(0x37, V1_19_1, V1_19_1),
|
||||
map(0x36, V1_19_3, V1_19_3),
|
||||
map(0x3A, V1_19_4, V1_20),
|
||||
map(0x3C, V1_20_2, V1_20_2)
|
||||
map(0x3C, V1_20_2, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketTitleLegacy::new,
|
||||
map(0x45, V1_8, V1_11_1),
|
||||
@ -272,7 +274,8 @@ public enum State {
|
||||
map(0x5D, V1_19_1, V1_19_1),
|
||||
map(0x5B, V1_19_3, V1_19_3),
|
||||
map(0x5F, V1_19_4, V1_20),
|
||||
map(0x61, V1_20_2, V1_20_2)
|
||||
map(0x61, V1_20_2, V1_20_2),
|
||||
map(0x63, V1_20_3, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketTitleSetSubTitle::new,
|
||||
map(0x57, V1_17, V1_17_1),
|
||||
@ -280,7 +283,8 @@ public enum State {
|
||||
map(0x5B, V1_19_1, V1_19_1),
|
||||
map(0x59, V1_19_3, V1_19_3),
|
||||
map(0x5D, V1_19_4, V1_20),
|
||||
map(0x5F, V1_20_2, V1_20_2)
|
||||
map(0x5F, V1_20_2, V1_20_2),
|
||||
map(0x61, V1_20_3, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketTitleTimes::new,
|
||||
map(0x5A, V1_17, V1_17_1),
|
||||
@ -288,7 +292,8 @@ public enum State {
|
||||
map(0x5E, V1_19_1, V1_19_1),
|
||||
map(0x5C, V1_19_3, V1_19_3),
|
||||
map(0x60, V1_19_4, V1_20),
|
||||
map(0x62, V1_20_2, V1_20_2)
|
||||
map(0x62, V1_20_2, V1_20_2),
|
||||
map(0x64, V1_20_3, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketPlayerListHeader::new,
|
||||
map(0x47, V1_8, V1_8),
|
||||
@ -306,12 +311,20 @@ public enum State {
|
||||
map(0x63, V1_19_1, V1_19_1),
|
||||
map(0x61, V1_19_3, V1_19_3),
|
||||
map(0x65, V1_19_4, V1_20),
|
||||
map(0x68, V1_20_2, V1_20_2)
|
||||
map(0x68, V1_20_2, V1_20_2),
|
||||
map(0x6A, V1_20_3, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketSpawnPosition::new,
|
||||
map(0x4C, V1_19_3, V1_19_3),
|
||||
map(0x50, V1_19_4, V1_20),
|
||||
map(0x52, V1_20_2, V1_20_2)
|
||||
map(0x52, V1_20_2, V1_20_2),
|
||||
map(0x54, V1_20_3, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketGameEvent::new,
|
||||
map(0x20, V1_20_3, V1_20_3)
|
||||
);
|
||||
clientBound.register(PacketEmptyChunk::new,
|
||||
map(0x25, V1_20_3, V1_20_3)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -70,7 +70,8 @@ public enum Version {
|
||||
V1_19_4(762),
|
||||
V1_20(763),
|
||||
// 1.20.1 has same protocol number
|
||||
V1_20_2(764);
|
||||
V1_20_2(764),
|
||||
V1_20_3(765);
|
||||
|
||||
private static final Map<Integer, Version> VERSION_MAP;
|
||||
private static final Version MAX;
|
||||
|
@ -21,18 +21,20 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
import ua.nanit.limbo.protocol.NbtMessage;
|
||||
import ua.nanit.limbo.util.Colors;
|
||||
import ua.nanit.limbo.util.NbtMessageUtil;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class BossBar {
|
||||
|
||||
private String text;
|
||||
private NbtMessage text;
|
||||
private float health;
|
||||
private Color color;
|
||||
private Division division;
|
||||
|
||||
public String getText() {
|
||||
public NbtMessage getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
@ -48,7 +50,7 @@ public class BossBar {
|
||||
return division;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
public void setText(NbtMessage text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@ -110,7 +112,7 @@ public class BossBar {
|
||||
public BossBar deserialize(Type type, ConfigurationNode node) throws SerializationException {
|
||||
BossBar bossBar = new BossBar();
|
||||
|
||||
bossBar.setText(Colors.of(node.node("text").getString("")));
|
||||
bossBar.setText(NbtMessageUtil.create(Colors.of(node.node("text").getString(""))));
|
||||
bossBar.setHealth(node.node("health").getFloat());
|
||||
|
||||
if (bossBar.getHealth() < 0 || bossBar.getHealth() > 1)
|
||||
|
@ -20,23 +20,25 @@ package ua.nanit.limbo.server.data;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
import ua.nanit.limbo.protocol.NbtMessage;
|
||||
import ua.nanit.limbo.util.Colors;
|
||||
import ua.nanit.limbo.util.NbtMessageUtil;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class Title {
|
||||
|
||||
private String title;
|
||||
private String subtitle;
|
||||
private NbtMessage title;
|
||||
private NbtMessage subtitle;
|
||||
private int fadeIn;
|
||||
private int stay;
|
||||
private int fadeOut;
|
||||
|
||||
public String getTitle() {
|
||||
public NbtMessage getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getSubtitle() {
|
||||
public NbtMessage getSubtitle() {
|
||||
return subtitle;
|
||||
}
|
||||
|
||||
@ -52,11 +54,11 @@ public class Title {
|
||||
return fadeOut;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
public void setTitle(NbtMessage title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public void setSubtitle(String subtitle) {
|
||||
public void setSubtitle(NbtMessage subtitle) {
|
||||
this.subtitle = subtitle;
|
||||
}
|
||||
|
||||
@ -77,8 +79,8 @@ public class Title {
|
||||
@Override
|
||||
public Title deserialize(Type type, ConfigurationNode node) {
|
||||
Title title = new Title();
|
||||
title.setTitle(Colors.of(node.node("title").getString("")));
|
||||
title.setSubtitle(Colors.of(node.node("subtitle").getString("")));
|
||||
title.setTitle(NbtMessageUtil.create(Colors.of(node.node("title").getString(""))));
|
||||
title.setSubtitle(NbtMessageUtil.create(Colors.of(node.node("subtitle").getString(""))));
|
||||
title.setFadeIn(node.node("fadeIn").getInt(10));
|
||||
title.setStay(node.node("stay").getInt(100));
|
||||
title.setFadeOut(node.node("fadeOut").getInt(10));
|
||||
|
110
src/main/java/ua/nanit/limbo/util/NbtMessageUtil.java
Normal file
110
src/main/java/ua/nanit/limbo/util/NbtMessageUtil.java
Normal file
@ -0,0 +1,110 @@
|
||||
package ua.nanit.limbo.util;
|
||||
|
||||
import com.google.gson.*;
|
||||
import net.kyori.adventure.nbt.*;
|
||||
import ua.nanit.limbo.protocol.NbtMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class NbtMessageUtil {
|
||||
|
||||
public static NbtMessage create(String json) {
|
||||
BinaryTag compoundBinaryTag = fromJson(JsonParser.parseString(json));
|
||||
|
||||
return new NbtMessage(json, compoundBinaryTag);
|
||||
}
|
||||
|
||||
public static BinaryTag fromJson(JsonElement json) {
|
||||
if (json instanceof JsonPrimitive) {
|
||||
JsonPrimitive jsonPrimitive = (JsonPrimitive) json;
|
||||
if (jsonPrimitive.isNumber()) {
|
||||
Number number = json.getAsNumber();
|
||||
|
||||
if (number instanceof Byte) {
|
||||
return ByteBinaryTag.byteBinaryTag((Byte) number);
|
||||
} else if (number instanceof Short) {
|
||||
return ShortBinaryTag.shortBinaryTag((Short) number);
|
||||
} else if (number instanceof Integer) {
|
||||
return IntBinaryTag.intBinaryTag((Integer) number);
|
||||
} else if (number instanceof Long) {
|
||||
return LongBinaryTag.longBinaryTag((Long) number);
|
||||
} else if (number instanceof Float) {
|
||||
return FloatBinaryTag.floatBinaryTag((Float) number);
|
||||
} else if (number instanceof Double) {
|
||||
return DoubleBinaryTag.doubleBinaryTag((Double) number);
|
||||
}
|
||||
} else if (jsonPrimitive.isString()) {
|
||||
return StringBinaryTag.stringBinaryTag(jsonPrimitive.getAsString());
|
||||
} else if (jsonPrimitive.isBoolean()) {
|
||||
return ByteBinaryTag.byteBinaryTag(jsonPrimitive.getAsBoolean() ? (byte) 1 : (byte) 0);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown JSON primitive: " + jsonPrimitive);
|
||||
}
|
||||
} else if (json instanceof JsonObject) {
|
||||
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder();
|
||||
for (Map.Entry<String, JsonElement> property : ((JsonObject) json).entrySet()) {
|
||||
builder.put(property.getKey(), fromJson(property.getValue()));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
} else if (json instanceof JsonArray) {
|
||||
List<JsonElement> jsonArray = ((JsonArray) json).asList();
|
||||
|
||||
if (jsonArray.isEmpty()) {
|
||||
return ListBinaryTag.listBinaryTag(EndBinaryTag.endBinaryTag().type(), Collections.emptyList());
|
||||
}
|
||||
|
||||
BinaryTagType tagByteType = ByteBinaryTag.ZERO.type();
|
||||
BinaryTagType tagIntType = IntBinaryTag.intBinaryTag(0).type();
|
||||
BinaryTagType tagLongType = LongBinaryTag.longBinaryTag(0).type();
|
||||
|
||||
BinaryTag listTag;
|
||||
BinaryTagType listType = fromJson(jsonArray.get(0)).type();
|
||||
if (listType.equals(tagByteType)) {
|
||||
byte[] bytes = new byte[jsonArray.size()];
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
bytes[i] = (Byte) ((JsonPrimitive) jsonArray.get(i)).getAsNumber();
|
||||
}
|
||||
|
||||
listTag = ByteArrayBinaryTag.byteArrayBinaryTag(bytes);
|
||||
} else if (listType.equals(tagIntType)) {
|
||||
int[] ints = new int[jsonArray.size()];
|
||||
for (int i = 0; i < ints.length; i++) {
|
||||
ints[i] = (Integer) ((JsonPrimitive) jsonArray.get(i)).getAsNumber();
|
||||
}
|
||||
|
||||
listTag = IntArrayBinaryTag.intArrayBinaryTag(ints);
|
||||
} else if (listType.equals(tagLongType)) {
|
||||
long[] longs = new long[jsonArray.size()];
|
||||
for (int i = 0; i < longs.length; i++) {
|
||||
longs[i] = (Long) ((JsonPrimitive) jsonArray.get(i)).getAsNumber();
|
||||
}
|
||||
|
||||
listTag = LongArrayBinaryTag.longArrayBinaryTag(longs);
|
||||
} else {
|
||||
List<BinaryTag> tagItems = new ArrayList<>(jsonArray.size());
|
||||
|
||||
for (JsonElement jsonEl : jsonArray) {
|
||||
BinaryTag subTag = fromJson(jsonEl);
|
||||
if (subTag.type() != listType) {
|
||||
throw new IllegalArgumentException("Cannot convert mixed JsonArray to Tag");
|
||||
}
|
||||
|
||||
tagItems.add(subTag);
|
||||
}
|
||||
|
||||
listTag = ListBinaryTag.listBinaryTag(listType, tagItems);
|
||||
}
|
||||
|
||||
return listTag;
|
||||
} else if (json instanceof JsonNull) {
|
||||
return EndBinaryTag.endBinaryTag();
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unknown JSON element: " + json);
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user