forked from BLOCKFANTASY/LOOHP-Limbo
Minecraft 1.20.4
This commit is contained in:
parent
f4ed5d0f53
commit
0a919303b6
22
pom.xml
22
pom.xml
|
|
@ -24,7 +24,7 @@
|
||||||
<groupId>com.loohp</groupId>
|
<groupId>com.loohp</groupId>
|
||||||
<artifactId>Limbo</artifactId>
|
<artifactId>Limbo</artifactId>
|
||||||
<name>Limbo</name>
|
<name>Limbo</name>
|
||||||
<version>0.7.6-ALPHA</version>
|
<version>0.7.7-ALPHA</version>
|
||||||
|
|
||||||
<description>Standalone Limbo Minecraft Server.</description>
|
<description>Standalone Limbo Minecraft Server.</description>
|
||||||
<url>https://github.com/LOOHP/Limbo</url>
|
<url>https://github.com/LOOHP/Limbo</url>
|
||||||
|
|
@ -136,7 +136,7 @@
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
<finalName>${project.artifactId}-${project.version}-1.20.2</finalName>
|
<finalName>${project.artifactId}-${project.version}-1.20.4</finalName>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|
@ -210,6 +210,10 @@
|
||||||
<id>jitpack.io</id>
|
<id>jitpack.io</id>
|
||||||
<url>https://jitpack.io</url>
|
<url>https://jitpack.io</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>sonatype-oss-snapshots1</id>
|
||||||
|
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
|
||||||
|
</repository>
|
||||||
<repository>
|
<repository>
|
||||||
<id>bungeecord-repo</id>
|
<id>bungeecord-repo</id>
|
||||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
|
@ -220,7 +224,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>3.11</version>
|
<version>3.12.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.Querz</groupId>
|
<groupId>com.github.Querz</groupId>
|
||||||
|
|
@ -231,7 +235,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.8.5</version>
|
<version>2.10.1</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
@ -256,31 +260,31 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-text-serializer-gson</artifactId>
|
<artifactId>adventure-text-serializer-gson</artifactId>
|
||||||
<version>4.14.0</version>
|
<version>4.15.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-text-serializer-legacy</artifactId>
|
<artifactId>adventure-text-serializer-legacy</artifactId>
|
||||||
<version>4.14.0</version>
|
<version>4.15.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-text-serializer-plain</artifactId>
|
<artifactId>adventure-text-serializer-plain</artifactId>
|
||||||
<version>4.14.0</version>
|
<version>4.15.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-api</artifactId>
|
<artifactId>adventure-api</artifactId>
|
||||||
<version>4.14.0</version>
|
<version>4.15.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-nbt</artifactId>
|
<artifactId>adventure-nbt</artifactId>
|
||||||
<version>4.14.0</version>
|
<version>4.15.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
||||||
|
|
@ -139,8 +139,8 @@ public final class Limbo {
|
||||||
|
|
||||||
//===========================
|
//===========================
|
||||||
|
|
||||||
public final String SERVER_IMPLEMENTATION_VERSION = "1.20.2";
|
public final String SERVER_IMPLEMENTATION_VERSION = "1.20.4";
|
||||||
public final int SERVER_IMPLEMENTATION_PROTOCOL = 764;
|
public final int SERVER_IMPLEMENTATION_PROTOCOL = 765;
|
||||||
public final String LIMBO_IMPLEMENTATION_VERSION;
|
public final String LIMBO_IMPLEMENTATION_VERSION;
|
||||||
|
|
||||||
private final AtomicBoolean isRunning;
|
private final AtomicBoolean isRunning;
|
||||||
|
|
@ -555,7 +555,7 @@ public final class Limbo {
|
||||||
json.put("modinfo", modInfoJson);
|
json.put("modinfo", modInfoJson);
|
||||||
|
|
||||||
|
|
||||||
TreeMap<String, Object> treeMap = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER);
|
TreeMap<String, Object> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
treeMap.putAll(json);
|
treeMap.putAll(json);
|
||||||
|
|
||||||
Gson g = new GsonBuilder().create();
|
Gson g = new GsonBuilder().create();
|
||||||
|
|
|
||||||
|
|
@ -19,19 +19,19 @@
|
||||||
|
|
||||||
package com.loohp.limbo.events.player;
|
package com.loohp.limbo.events.player;
|
||||||
|
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInResourcePackStatus.EnumResourcePackStatus;
|
import com.loohp.limbo.network.protocol.packets.ServerboundResourcePackPacket.Action;
|
||||||
import com.loohp.limbo.player.Player;
|
import com.loohp.limbo.player.Player;
|
||||||
|
|
||||||
public class PlayerResourcePackStatusEvent extends PlayerEvent {
|
public class PlayerResourcePackStatusEvent extends PlayerEvent {
|
||||||
|
|
||||||
private EnumResourcePackStatus status;
|
private Action status;
|
||||||
|
|
||||||
public PlayerResourcePackStatusEvent(Player player, EnumResourcePackStatus status) {
|
public PlayerResourcePackStatusEvent(Player player, Action status) {
|
||||||
super(player);
|
super(player);
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EnumResourcePackStatus getStatus() {
|
public Action getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,8 @@ import com.loohp.limbo.network.protocol.packets.PacketPlayInPickItem;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPluginMessaging;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPluginMessaging;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPosition;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPosition;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInPositionAndLook;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInPositionAndLook;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInResourcePackStatus;
|
import com.loohp.limbo.network.protocol.packets.ServerboundResourcePackPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInResourcePackStatus.EnumResourcePackStatus;
|
import com.loohp.limbo.network.protocol.packets.ServerboundResourcePackPacket.Action;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInRotation;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInRotation;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInSetCreativeSlot;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInSetCreativeSlot;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayInTabComplete;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayInTabComplete;
|
||||||
|
|
@ -765,11 +765,11 @@ public class ClientConnection extends Thread {
|
||||||
Limbo.getInstance().getUnsafe().a(player, event.getSlot());
|
Limbo.getInstance().getUnsafe().a(player, event.getSlot());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (packetIn instanceof PacketPlayInResourcePackStatus) {
|
} else if (packetIn instanceof ServerboundResourcePackPacket) {
|
||||||
PacketPlayInResourcePackStatus rpcheck = (PacketPlayInResourcePackStatus) packetIn;
|
ServerboundResourcePackPacket rpcheck = (ServerboundResourcePackPacket) packetIn;
|
||||||
// Pass on result to the events
|
// Pass on result to the events
|
||||||
Limbo.getInstance().getEventsManager().callEvent(new PlayerResourcePackStatusEvent(player, rpcheck.getLoadedValue()));
|
Limbo.getInstance().getEventsManager().callEvent(new PlayerResourcePackStatusEvent(player, rpcheck.getAction()));
|
||||||
if (rpcheck.getLoadedValue().equals(EnumResourcePackStatus.DECLINED) && properties.getResourcePackRequired()) {
|
if (rpcheck.getAction().equals(Action.DECLINED) && properties.getResourcePackRequired()) {
|
||||||
player.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect"));
|
player.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect"));
|
||||||
}
|
}
|
||||||
} else if (packetIn instanceof PacketPlayInPluginMessaging) {
|
} else if (packetIn instanceof PacketPlayInPluginMessaging) {
|
||||||
|
|
|
||||||
|
|
@ -27,32 +27,34 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class PacketPlayOutResourcePackSend extends PacketOut {
|
public class ClientboundResourcePackPushPacket extends PacketOut {
|
||||||
|
|
||||||
public static final int MAX_HASH_LENGTH = 40;
|
public static final int MAX_HASH_LENGTH = 40;
|
||||||
|
|
||||||
private String url;
|
private final UUID id;
|
||||||
private String hash;
|
private final String url;
|
||||||
private boolean isForced;
|
private final String hash;
|
||||||
private boolean hasPromptMessage;
|
private final boolean required;
|
||||||
private Component promptMessage;
|
private final Component prompt;
|
||||||
|
|
||||||
public PacketPlayOutResourcePackSend(String url, String hash, boolean isForced, boolean hasPromptMessage, Component promptMessage) {
|
public ClientboundResourcePackPushPacket(UUID id, String url, String hash, boolean required, Component promptMessage) {
|
||||||
if (hash.length() > MAX_HASH_LENGTH) {
|
if (hash.length() > MAX_HASH_LENGTH) {
|
||||||
throw new IllegalArgumentException("Hash is too long (max " + MAX_HASH_LENGTH + ", was " + hash.length() + ")");
|
throw new IllegalArgumentException("Hash is too long (max " + MAX_HASH_LENGTH + ", was " + hash.length() + ")");
|
||||||
}
|
}
|
||||||
|
this.id = id;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.hash = hash;
|
this.hash = hash;
|
||||||
this.isForced = isForced;
|
this.required = required;
|
||||||
this.hasPromptMessage = hasPromptMessage;
|
this.prompt = promptMessage;
|
||||||
if (hasPromptMessage && promptMessage == null) {
|
|
||||||
throw new IllegalArgumentException("promptMessage cannot be null when hasPromptMessage is true");
|
|
||||||
}
|
|
||||||
this.promptMessage = promptMessage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getURL() {
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,16 +62,12 @@ public class PacketPlayOutResourcePackSend extends PacketOut {
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isForced() {
|
public boolean isRequired() {
|
||||||
return isForced;
|
return required;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPromptMessage() {
|
public Component getPrompt() {
|
||||||
return hasPromptMessage;
|
return prompt;
|
||||||
}
|
|
||||||
|
|
||||||
public Component getPromptMessage() {
|
|
||||||
return promptMessage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -78,13 +76,17 @@ public class PacketPlayOutResourcePackSend extends PacketOut {
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
|
DataTypeIO.writeUUID(output, id);
|
||||||
DataTypeIO.writeString(output, url, StandardCharsets.UTF_8);
|
DataTypeIO.writeString(output, url, StandardCharsets.UTF_8);
|
||||||
DataTypeIO.writeString(output, hash, StandardCharsets.UTF_8);
|
DataTypeIO.writeString(output, hash, StandardCharsets.UTF_8);
|
||||||
output.writeBoolean(isForced);
|
output.writeBoolean(required);
|
||||||
output.writeBoolean(hasPromptMessage);
|
if (prompt == null) {
|
||||||
if (hasPromptMessage) {
|
output.writeBoolean(false);
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(promptMessage), StandardCharsets.UTF_8);
|
} else {
|
||||||
|
output.writeBoolean(true);
|
||||||
|
DataTypeIO.writeComponent(output, prompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -21,12 +21,10 @@ package com.loohp.limbo.network.protocol.packets;
|
||||||
|
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class ClientboundSetActionBarTextPacket extends PacketOut {
|
public class ClientboundSetActionBarTextPacket extends PacketOut {
|
||||||
|
|
||||||
|
|
@ -46,7 +44,7 @@ public class ClientboundSetActionBarTextPacket extends PacketOut {
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(actionBar), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, actionBar);
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,10 @@ package com.loohp.limbo.network.protocol.packets;
|
||||||
|
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class ClientboundSetSubtitleTextPacket extends PacketOut {
|
public class ClientboundSetSubtitleTextPacket extends PacketOut {
|
||||||
|
|
||||||
|
|
@ -46,7 +44,7 @@ public class ClientboundSetSubtitleTextPacket extends PacketOut {
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(subTitle), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, subTitle);
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,10 @@ package com.loohp.limbo.network.protocol.packets;
|
||||||
|
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class ClientboundSetTitleTextPacket extends PacketOut {
|
public class ClientboundSetTitleTextPacket extends PacketOut {
|
||||||
|
|
||||||
|
|
@ -46,7 +44,7 @@ public class ClientboundSetTitleTextPacket extends PacketOut {
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(titleText), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, titleText);
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,10 @@ package com.loohp.limbo.network.protocol.packets;
|
||||||
|
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class ClientboundSystemChatPacket extends PacketOut {
|
public class ClientboundSystemChatPacket extends PacketOut {
|
||||||
|
|
||||||
|
|
@ -52,7 +50,7 @@ public class ClientboundSystemChatPacket extends PacketOut {
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(message), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, message);
|
||||||
output.writeBoolean(overlay);
|
output.writeBoolean(overlay);
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,10 @@ package com.loohp.limbo.network.protocol.packets;
|
||||||
|
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class PacketLoginOutDisconnect extends PacketOut {
|
public class PacketLoginOutDisconnect extends PacketOut {
|
||||||
|
|
||||||
|
|
@ -46,7 +44,7 @@ public class PacketLoginOutDisconnect extends PacketOut {
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getLoginOut().get(getClass()));
|
output.writeByte(Packet.getLoginOut().get(getClass()));
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(reason), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, reason);
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,10 @@ package com.loohp.limbo.network.protocol.packets;
|
||||||
import com.loohp.limbo.bossbar.KeyedBossBar;
|
import com.loohp.limbo.bossbar.KeyedBossBar;
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import net.kyori.adventure.bossbar.BossBar;
|
import net.kyori.adventure.bossbar.BossBar;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class PacketPlayOutBoss extends PacketOut {
|
public class PacketPlayOutBoss extends PacketOut {
|
||||||
|
|
||||||
|
|
@ -83,7 +81,7 @@ public class PacketPlayOutBoss extends PacketOut {
|
||||||
BossBar properties = bossBar.getProperties();
|
BossBar properties = bossBar.getProperties();
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case ADD: {
|
case ADD: {
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(properties.name()), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, properties.name());
|
||||||
output.writeFloat(properties.progress());
|
output.writeFloat(properties.progress());
|
||||||
DataTypeIO.writeVarInt(output, properties.color().ordinal());
|
DataTypeIO.writeVarInt(output, properties.color().ordinal());
|
||||||
DataTypeIO.writeVarInt(output, properties.overlay().ordinal());
|
DataTypeIO.writeVarInt(output, properties.overlay().ordinal());
|
||||||
|
|
@ -98,7 +96,7 @@ public class PacketPlayOutBoss extends PacketOut {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case UPDATE_NAME: {
|
case UPDATE_NAME: {
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(properties.name()), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, properties.name());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case UPDATE_STYLE: {
|
case UPDATE_STYLE: {
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,10 @@ package com.loohp.limbo.network.protocol.packets;
|
||||||
|
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class PacketPlayOutDisconnect extends PacketOut {
|
public class PacketPlayOutDisconnect extends PacketOut {
|
||||||
|
|
||||||
|
|
@ -46,7 +44,7 @@ public class PacketPlayOutDisconnect extends PacketOut {
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(reason), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, reason);
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import com.loohp.limbo.utils.Rotation3f;
|
import com.loohp.limbo.utils.Rotation3f;
|
||||||
import com.loohp.limbo.world.BlockPosition;
|
import com.loohp.limbo.world.BlockPosition;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
|
|
@ -129,7 +128,7 @@ public class PacketPlayOutEntityMetadata extends PacketOut {
|
||||||
output.writeByte((byte) watch.getValue());
|
output.writeByte((byte) watch.getValue());
|
||||||
break;
|
break;
|
||||||
case CHAT:
|
case CHAT:
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize((Component) watch.getValue()), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, (Component) watch.getValue());
|
||||||
break;
|
break;
|
||||||
//case DIRECTION:
|
//case DIRECTION:
|
||||||
// break;
|
// break;
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ import java.io.IOException;
|
||||||
|
|
||||||
public class PacketPlayOutGameState extends PacketOut {
|
public class PacketPlayOutGameState extends PacketOut {
|
||||||
|
|
||||||
private int reason;
|
private final int reason;
|
||||||
private float value;
|
private final float value;
|
||||||
|
|
||||||
public PacketPlayOutGameState(int reason, float value) {
|
public PacketPlayOutGameState(int reason, float value) {
|
||||||
this.reason = reason;
|
this.reason = reason;
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,10 @@ import com.loohp.limbo.registry.Registry;
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class PacketPlayOutOpenWindow extends PacketOut {
|
public class PacketPlayOutOpenWindow extends PacketOut {
|
||||||
|
|
||||||
|
|
@ -63,7 +61,7 @@ public class PacketPlayOutOpenWindow extends PacketOut {
|
||||||
|
|
||||||
DataTypeIO.writeVarInt(output, containerId);
|
DataTypeIO.writeVarInt(output, containerId);
|
||||||
DataTypeIO.writeVarInt(output, Registry.MENU_REGISTRY.getId(type));
|
DataTypeIO.writeVarInt(output, Registry.MENU_REGISTRY.getId(type));
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(title), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, title);
|
||||||
|
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,10 @@ package com.loohp.limbo.network.protocol.packets;
|
||||||
|
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class PacketPlayOutPlayerListHeaderFooter extends PacketOut{
|
public class PacketPlayOutPlayerListHeaderFooter extends PacketOut{
|
||||||
|
|
||||||
|
|
@ -53,8 +51,8 @@ public class PacketPlayOutPlayerListHeaderFooter extends PacketOut{
|
||||||
|
|
||||||
DataOutputStream output = new DataOutputStream(buffer);
|
DataOutputStream output = new DataOutputStream(buffer);
|
||||||
output.writeByte(Packet.getPlayOut().get(getClass()));
|
output.writeByte(Packet.getPlayOut().get(getClass()));
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(header), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, header);
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(footer), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, footer);
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ package com.loohp.limbo.network.protocol.packets;
|
||||||
|
|
||||||
import com.loohp.limbo.utils.DataTypeIO;
|
import com.loohp.limbo.utils.DataTypeIO;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
|
|
@ -74,7 +73,7 @@ public class PacketPlayOutTabComplete extends PacketOut {
|
||||||
DataTypeIO.writeString(output, match.getMatch(), StandardCharsets.UTF_8);
|
DataTypeIO.writeString(output, match.getMatch(), StandardCharsets.UTF_8);
|
||||||
if (match.getTooltip().isPresent()) {
|
if (match.getTooltip().isPresent()) {
|
||||||
output.writeBoolean(true);
|
output.writeBoolean(true);
|
||||||
DataTypeIO.writeString(output, GsonComponentSerializer.gson().serialize(match.getTooltip().get()), StandardCharsets.UTF_8);
|
DataTypeIO.writeComponent(output, match.getTooltip().get());
|
||||||
} else {
|
} else {
|
||||||
output.writeBoolean(false);
|
output.writeBoolean(false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,43 +23,38 @@ import com.loohp.limbo.utils.DataTypeIO;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class PacketPlayInResourcePackStatus extends PacketIn {
|
public class ServerboundResourcePackPacket extends PacketIn {
|
||||||
|
|
||||||
public static enum EnumResourcePackStatus {
|
public enum Action {
|
||||||
SUCCESS,
|
|
||||||
DECLINED,
|
|
||||||
FAILED,
|
|
||||||
ACCEPTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
private EnumResourcePackStatus loaded;
|
SUCCESSFULLY_LOADED, DECLINED, FAILED_DOWNLOAD, ACCEPTED, DOWNLOADED, INVALID_URL, FAILED_RELOAD, DISCARDED;
|
||||||
|
|
||||||
public PacketPlayInResourcePackStatus(EnumResourcePackStatus loaded) {
|
public boolean isTerminal() {
|
||||||
this.loaded = loaded;
|
return this != ACCEPTED && this != DOWNLOADED;
|
||||||
}
|
|
||||||
|
|
||||||
public PacketPlayInResourcePackStatus(DataInputStream in) throws IOException {
|
|
||||||
this(toLoadedValue(DataTypeIO.readVarInt(in)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public EnumResourcePackStatus getLoadedValue() {
|
|
||||||
return loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static EnumResourcePackStatus toLoadedValue(int value) {
|
|
||||||
switch (value) {
|
|
||||||
case 0:
|
|
||||||
return EnumResourcePackStatus.SUCCESS;
|
|
||||||
case 1:
|
|
||||||
return EnumResourcePackStatus.DECLINED;
|
|
||||||
case 2:
|
|
||||||
return EnumResourcePackStatus.FAILED;
|
|
||||||
case 3:
|
|
||||||
return EnumResourcePackStatus.ACCEPTED;
|
|
||||||
default:
|
|
||||||
return EnumResourcePackStatus.FAILED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private final UUID id;
|
||||||
|
private final Action action;
|
||||||
|
|
||||||
|
public ServerboundResourcePackPacket(UUID id, Action action) {
|
||||||
|
this.id = id;
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerboundResourcePackPacket(DataInputStream in) throws IOException {
|
||||||
|
this(DataTypeIO.readUUID(in), Action.values()[DataTypeIO.readVarInt(in)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action getAction() {
|
||||||
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +51,7 @@ import com.loohp.limbo.network.protocol.packets.PacketPlayOutNamedSoundEffect;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutOpenWindow;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutOpenWindow;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerListHeaderFooter;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerListHeaderFooter;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPositionAndLook;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutPositionAndLook;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutResourcePackSend;
|
import com.loohp.limbo.network.protocol.packets.ClientboundResourcePackPushPacket;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutRespawn;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutRespawn;
|
||||||
import com.loohp.limbo.network.protocol.packets.PacketPlayOutStopSound;
|
import com.loohp.limbo.network.protocol.packets.PacketPlayOutStopSound;
|
||||||
import com.loohp.limbo.sounds.SoundEffect;
|
import com.loohp.limbo.sounds.SoundEffect;
|
||||||
|
|
@ -369,7 +369,7 @@ public class Player extends LivingEntity implements CommandSender, InventoryHold
|
||||||
|
|
||||||
public void setResourcePack(String url, String hash, boolean forced, Component promptmessage) {
|
public void setResourcePack(String url, String hash, boolean forced, Component promptmessage) {
|
||||||
try {
|
try {
|
||||||
PacketPlayOutResourcePackSend packsend = new PacketPlayOutResourcePackSend(url, hash, forced, promptmessage != null, promptmessage);
|
ClientboundResourcePackPushPacket packsend = new ClientboundResourcePackPushPacket(UUID.randomUUID(), url, hash, forced, promptmessage);
|
||||||
clientConnection.sendPacket(packsend);
|
clientConnection.sendPacket(packsend);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package com.loohp.limbo.utils;
|
package com.loohp.limbo.utils;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
import com.loohp.limbo.inventory.ItemStack;
|
import com.loohp.limbo.inventory.ItemStack;
|
||||||
import com.loohp.limbo.location.BlockFace;
|
import com.loohp.limbo.location.BlockFace;
|
||||||
import com.loohp.limbo.location.MovingObjectPositionBlock;
|
import com.loohp.limbo.location.MovingObjectPositionBlock;
|
||||||
|
|
@ -26,6 +27,8 @@ import com.loohp.limbo.location.Vector;
|
||||||
import com.loohp.limbo.registry.Registry;
|
import com.loohp.limbo.registry.Registry;
|
||||||
import com.loohp.limbo.world.BlockPosition;
|
import com.loohp.limbo.world.BlockPosition;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
import net.querz.nbt.io.NBTInputStream;
|
import net.querz.nbt.io.NBTInputStream;
|
||||||
import net.querz.nbt.io.NBTOutputStream;
|
import net.querz.nbt.io.NBTOutputStream;
|
||||||
import net.querz.nbt.tag.CompoundTag;
|
import net.querz.nbt.tag.CompoundTag;
|
||||||
|
|
@ -272,4 +275,20 @@ public class DataTypeIO {
|
||||||
} while (value != 0);
|
} while (value != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Component readComponent(DataInputStream in) throws IOException {
|
||||||
|
// Do not use CompoundTag, as Mojang serializes a plaintext component as just a single StringTag
|
||||||
|
Tag<?> tag = readTag(in, Tag.class);
|
||||||
|
if (tag == null || tag instanceof EndTag) {
|
||||||
|
throw new IllegalArgumentException("Got end-tag when trying to read Component");
|
||||||
|
}
|
||||||
|
JsonElement json = NbtComponentSerializer.tagComponentToJson(tag);
|
||||||
|
return GsonComponentSerializer.gson().deserializeFromTree(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeComponent(DataOutputStream out, Component component) throws IOException {
|
||||||
|
JsonElement json = GsonComponentSerializer.gson().serializeToTree(component);
|
||||||
|
Tag<?> tag = NbtComponentSerializer.jsonComponentToTag(json);
|
||||||
|
writeTag(out, tag);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,385 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Limbo.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||||
|
* Copyright (C) 2023. Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.loohp.limbo.utils;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
|
import com.google.gson.internal.LazilyParsedNumber;
|
||||||
|
import net.querz.nbt.tag.ByteArrayTag;
|
||||||
|
import net.querz.nbt.tag.ByteTag;
|
||||||
|
import net.querz.nbt.tag.CompoundTag;
|
||||||
|
import net.querz.nbt.tag.DoubleTag;
|
||||||
|
import net.querz.nbt.tag.EndTag;
|
||||||
|
import net.querz.nbt.tag.FloatTag;
|
||||||
|
import net.querz.nbt.tag.IntArrayTag;
|
||||||
|
import net.querz.nbt.tag.IntTag;
|
||||||
|
import net.querz.nbt.tag.ListTag;
|
||||||
|
import net.querz.nbt.tag.LongArrayTag;
|
||||||
|
import net.querz.nbt.tag.LongTag;
|
||||||
|
import net.querz.nbt.tag.NumberTag;
|
||||||
|
import net.querz.nbt.tag.ShortTag;
|
||||||
|
import net.querz.nbt.tag.StringTag;
|
||||||
|
import net.querz.nbt.tag.Tag;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Taken from <a href="https://github.com/GeyserMC/MCProtocolLib/blob/master/src/main/java/com/github/steveice10/mc/protocol/codec/NbtComponentSerializer.java">MCProtocolLib's NbtComponentSerializer</a>
|
||||||
|
*/
|
||||||
|
public class NbtComponentSerializer {
|
||||||
|
|
||||||
|
private static final Set<String> BOOLEAN_TYPES = new HashSet<>(Arrays.asList(
|
||||||
|
"interpret",
|
||||||
|
"bold",
|
||||||
|
"italic",
|
||||||
|
"underlined",
|
||||||
|
"strikethrough",
|
||||||
|
"obfuscated"
|
||||||
|
));
|
||||||
|
// Order is important
|
||||||
|
private static final List<Pair<String, String>> COMPONENT_TYPES = Arrays.asList(
|
||||||
|
new Pair<>("text", "text"),
|
||||||
|
new Pair<>("translatable", "translate"),
|
||||||
|
new Pair<>("score", "score"),
|
||||||
|
new Pair<>("selector", "selector"),
|
||||||
|
new Pair<>("keybind", "keybind"),
|
||||||
|
new Pair<>("nbt", "nbt")
|
||||||
|
);
|
||||||
|
|
||||||
|
private NbtComponentSerializer() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonElement tagComponentToJson(Tag<?> tag) {
|
||||||
|
return convertToJson(null, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Tag<?> jsonComponentToTag(JsonElement component) {
|
||||||
|
return convertToTag(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Tag<?> convertToTag(JsonElement element) {
|
||||||
|
if (element == null || element.isJsonNull()) {
|
||||||
|
return null;
|
||||||
|
} else if (element.isJsonObject()) {
|
||||||
|
final CompoundTag tag = new CompoundTag();
|
||||||
|
final JsonObject jsonObject = element.getAsJsonObject();
|
||||||
|
for (final Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
|
||||||
|
convertObjectEntry(entry.getKey(), entry.getValue(), tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
addComponentType(jsonObject, tag);
|
||||||
|
return tag;
|
||||||
|
} else if (element.isJsonArray()) {
|
||||||
|
return convertJsonArray(element.getAsJsonArray());
|
||||||
|
} else if (element.isJsonPrimitive()) {
|
||||||
|
final JsonPrimitive primitive = element.getAsJsonPrimitive();
|
||||||
|
if (primitive.isString()) {
|
||||||
|
return new StringTag(primitive.getAsString());
|
||||||
|
} else if (primitive.isBoolean()) {
|
||||||
|
return new ByteTag((byte) (primitive.getAsBoolean() ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
final Number number = primitive.getAsNumber();
|
||||||
|
if (number instanceof Integer) {
|
||||||
|
return new IntTag(number.intValue());
|
||||||
|
} else if (number instanceof Byte) {
|
||||||
|
return new ByteTag(number.byteValue());
|
||||||
|
} else if (number instanceof Short) {
|
||||||
|
return new ShortTag(number.shortValue());
|
||||||
|
} else if (number instanceof Long) {
|
||||||
|
return new LongTag(number.longValue());
|
||||||
|
} else if (number instanceof Double) {
|
||||||
|
return new DoubleTag(number.doubleValue());
|
||||||
|
} else if (number instanceof Float) {
|
||||||
|
return new FloatTag(number.floatValue());
|
||||||
|
} else if (number instanceof LazilyParsedNumber) {
|
||||||
|
// TODO: This might need better handling
|
||||||
|
return new IntTag(number.intValue());
|
||||||
|
}
|
||||||
|
return new IntTag(number.intValue()); // ???
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unhandled json type " + element.getClass().getSimpleName() + " with value " + element.getAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
private static ListTag<?> convertJsonArray(JsonArray array) {
|
||||||
|
// TODO Number arrays?
|
||||||
|
final ListTag listTag = ListTag.createUnchecked(EndTag.class);
|
||||||
|
boolean singleType = true;
|
||||||
|
for (final JsonElement entry : array) {
|
||||||
|
final Tag<?> convertedEntryTag = convertToTag(entry);
|
||||||
|
if (listTag.getTypeClass() != null && listTag.getTypeClass() != convertedEntryTag.getClass()) {
|
||||||
|
singleType = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
listTag.add(convertedEntryTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (singleType) {
|
||||||
|
return listTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generally, vanilla-esque serializers should not produce this format, so it should be rare
|
||||||
|
// Lists are only used for lists of components ("extra" and "with")
|
||||||
|
final ListTag processedListTag = ListTag.createUnchecked(EndTag.class);
|
||||||
|
for (final JsonElement entry : array) {
|
||||||
|
final Tag<?> convertedTag = convertToTag(entry);
|
||||||
|
if (convertedTag instanceof CompoundTag) {
|
||||||
|
processedListTag.add(convertedTag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap all entries in compound tags, as lists can only consist of one type of tag
|
||||||
|
final CompoundTag compoundTag = new CompoundTag();
|
||||||
|
compoundTag.put("type", new StringTag("text"));
|
||||||
|
if (convertedTag instanceof ListTag) {
|
||||||
|
compoundTag.put("text", new StringTag());
|
||||||
|
compoundTag.put("extra", convertedTag.clone());
|
||||||
|
} else {
|
||||||
|
compoundTag.put("text", new StringTag(stringValue(convertedTag)));
|
||||||
|
}
|
||||||
|
processedListTag.add(compoundTag);
|
||||||
|
}
|
||||||
|
return processedListTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a json object entry to a tag entry.
|
||||||
|
*
|
||||||
|
* @param key key of the entry
|
||||||
|
* @param value value of the entry
|
||||||
|
* @param tag the resulting compound tag
|
||||||
|
*/
|
||||||
|
private static void convertObjectEntry(final String key, final JsonElement value, final CompoundTag tag) {
|
||||||
|
if ((key.equals("contents")) && value.isJsonObject()) {
|
||||||
|
// Store show_entity id as int array instead of uuid string
|
||||||
|
// Not really required, but we might as well make it more compact
|
||||||
|
final JsonObject hoverEvent = value.getAsJsonObject();
|
||||||
|
final JsonElement id = hoverEvent.get("id");
|
||||||
|
final UUID uuid;
|
||||||
|
if (id != null && id.isJsonPrimitive() && (uuid = parseUUID(id.getAsString())) != null) {
|
||||||
|
hoverEvent.remove("id");
|
||||||
|
|
||||||
|
final CompoundTag convertedTag = (CompoundTag) convertToTag(value);
|
||||||
|
convertedTag.put("id", new IntArrayTag(toIntArray(uuid)));
|
||||||
|
tag.put(key, convertedTag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag.put(key, convertToTag(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addComponentType(final JsonObject object, final CompoundTag tag) {
|
||||||
|
if (object.has("type")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the type to speed up deserialization and make DFU errors slightly more useful
|
||||||
|
for (final Pair<String, String> pair : COMPONENT_TYPES) {
|
||||||
|
if (object.has(pair.value)) {
|
||||||
|
tag.put("type", new StringTag(pair.key));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JsonElement convertToJson(final String key, final Tag<?> tag) {
|
||||||
|
if (tag == null) {
|
||||||
|
return null;
|
||||||
|
} else if (tag instanceof CompoundTag) {
|
||||||
|
final JsonObject object = new JsonObject();
|
||||||
|
if (!"value".equals(key)) {
|
||||||
|
removeComponentType(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Map.Entry<String, Tag<?>> entry : ((CompoundTag) tag).entrySet()) {
|
||||||
|
convertCompoundTagEntry(entry.getKey(), entry.getValue(), object);
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
} else if (tag instanceof ListTag<?>) {
|
||||||
|
final ListTag<?> list = (ListTag<?>) tag;
|
||||||
|
final JsonArray array = new JsonArray();
|
||||||
|
for (final Tag<?> listEntry : list) {
|
||||||
|
array.add(convertToJson(null, listEntry));
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
} else if (tag instanceof NumberTag<?>) {
|
||||||
|
if (key != null && BOOLEAN_TYPES.contains(key)) {
|
||||||
|
// Booleans don't have a direct representation in nbt
|
||||||
|
return new JsonPrimitive(((NumberTag<?>) tag).asByte() != 0);
|
||||||
|
}
|
||||||
|
if (tag instanceof ByteTag) {
|
||||||
|
return new JsonPrimitive(((ByteTag) tag).asByte());
|
||||||
|
} else if (tag instanceof ShortTag) {
|
||||||
|
return new JsonPrimitive(((ShortTag) tag).asShort());
|
||||||
|
} else if (tag instanceof IntTag) {
|
||||||
|
return new JsonPrimitive(((IntTag) tag).asInt());
|
||||||
|
} else if (tag instanceof LongTag) {
|
||||||
|
return new JsonPrimitive(((LongTag) tag).asLong());
|
||||||
|
} else if (tag instanceof FloatTag) {
|
||||||
|
return new JsonPrimitive(((FloatTag) tag).asFloat());
|
||||||
|
} else if (tag instanceof DoubleTag) {
|
||||||
|
return new JsonPrimitive(((DoubleTag) tag).asDouble());
|
||||||
|
}
|
||||||
|
return new JsonPrimitive(((NumberTag<?>) tag).asDouble());
|
||||||
|
} else if (tag instanceof StringTag) {
|
||||||
|
return new JsonPrimitive(((StringTag) tag).getValue());
|
||||||
|
} else if (tag instanceof ByteArrayTag) {
|
||||||
|
final ByteArrayTag arrayTag = (ByteArrayTag) tag;
|
||||||
|
final JsonArray array = new JsonArray();
|
||||||
|
for (final byte num : arrayTag.getValue()) {
|
||||||
|
array.add(num);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
} else if (tag instanceof IntArrayTag) {
|
||||||
|
final IntArrayTag arrayTag = (IntArrayTag) tag;
|
||||||
|
final JsonArray array = new JsonArray();
|
||||||
|
for (final int num : arrayTag.getValue()) {
|
||||||
|
array.add(num);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
} else if (tag instanceof LongArrayTag) {
|
||||||
|
final LongArrayTag arrayTag = (LongArrayTag) tag;
|
||||||
|
final JsonArray array = new JsonArray();
|
||||||
|
for (final long num : arrayTag.getValue()) {
|
||||||
|
array.add(num);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unhandled tag type " + tag.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void convertCompoundTagEntry(final String key, final Tag<?> tag, final JsonObject object) {
|
||||||
|
if ((key.equals("contents")) && tag instanceof CompoundTag) {
|
||||||
|
// Back to a UUID string
|
||||||
|
final CompoundTag showEntity = (CompoundTag) tag;
|
||||||
|
final Tag<?> idTag = showEntity.get("id");
|
||||||
|
if (idTag instanceof IntArrayTag) {
|
||||||
|
showEntity.remove("id");
|
||||||
|
|
||||||
|
final JsonObject convertedElement = (JsonObject) convertToJson(key, tag);
|
||||||
|
final UUID uuid = fromIntArray(((IntArrayTag) idTag).getValue());
|
||||||
|
convertedElement.addProperty("id", uuid.toString());
|
||||||
|
object.add(key, convertedElement);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "":1 is a valid tag, but not a valid json component
|
||||||
|
object.add(key.isEmpty() ? "text" : key, convertToJson(key, tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void removeComponentType(final JsonObject object) {
|
||||||
|
final JsonElement type = object.remove("type");
|
||||||
|
if (type == null || !type.isJsonPrimitive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the other fields
|
||||||
|
final String typeString = type.getAsString();
|
||||||
|
for (final Pair<String, String> pair : COMPONENT_TYPES) {
|
||||||
|
if (!pair.key.equals(typeString)) {
|
||||||
|
object.remove(pair.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last adopted from https://github.com/ViaVersion/ViaVersion/blob/8e38e25cbad1798abb628b4994f4047eaf64640d/common/src/main/java/com/viaversion/viaversion/util/UUIDUtil.java
|
||||||
|
public static UUID fromIntArray(final int[] parts) {
|
||||||
|
if (parts.length != 4) {
|
||||||
|
return new UUID(0, 0);
|
||||||
|
}
|
||||||
|
return new UUID((long) parts[0] << 32 | (parts[1] & 0xFFFFFFFFL), (long) parts[2] << 32 | (parts[3] & 0xFFFFFFFFL));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] toIntArray(final UUID uuid) {
|
||||||
|
return toIntArray(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] toIntArray(final long msb, final long lsb) {
|
||||||
|
return new int[]{(int) (msb >> 32), (int) msb, (int) (lsb >> 32), (int) lsb};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUID parseUUID(final String uuidString) {
|
||||||
|
try {
|
||||||
|
return UUID.fromString(uuidString);
|
||||||
|
} catch (final IllegalArgumentException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last adopted from https://github.com/ViaVersion/ViaNBT/commit/ad8ac024c48c2fc25e18dc689b3ca62602420ab9
|
||||||
|
private static String stringValue(Tag<?> tag) {
|
||||||
|
if (tag instanceof ByteArrayTag) {
|
||||||
|
return Arrays.toString(((ByteArrayTag) tag).getValue());
|
||||||
|
} else if (tag instanceof ByteTag) {
|
||||||
|
return Byte.toString(((ByteTag) tag).asByte());
|
||||||
|
} else if (tag instanceof DoubleTag) {
|
||||||
|
return Double.toString(((DoubleTag) tag).asDouble());
|
||||||
|
} else if (tag instanceof FloatTag) {
|
||||||
|
return Float.toString(((FloatTag) tag).asFloat());
|
||||||
|
} else if (tag instanceof IntArrayTag) {
|
||||||
|
return Arrays.toString(((IntArrayTag) tag).getValue());
|
||||||
|
} else if (tag instanceof IntTag) {
|
||||||
|
return Integer.toString(((IntTag) tag).asInt());
|
||||||
|
} else if (tag instanceof LongArrayTag) {
|
||||||
|
return Arrays.toString(((LongArrayTag) tag).getValue());
|
||||||
|
} else if (tag instanceof LongTag) {
|
||||||
|
return Long.toString(((LongTag) tag).asLong());
|
||||||
|
} else if (tag instanceof ShortTag) {
|
||||||
|
return Short.toString(((ShortTag) tag).asShort());
|
||||||
|
} else if (tag instanceof StringTag) {
|
||||||
|
return ((StringTag) tag).getValue();
|
||||||
|
} else {
|
||||||
|
return tag.valueToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Pair<K, V> {
|
||||||
|
|
||||||
|
private final K key;
|
||||||
|
private final V value;
|
||||||
|
|
||||||
|
private Pair(K key, V value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public K getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public V getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -20,56 +20,56 @@
|
||||||
"ClientboundFinishConfigurationPacket": "0x02"
|
"ClientboundFinishConfigurationPacket": "0x02"
|
||||||
},
|
},
|
||||||
"PlayIn": {
|
"PlayIn": {
|
||||||
"0x14": "PacketPlayInKeepAlive",
|
"0x15": "PacketPlayInKeepAlive",
|
||||||
"0x04": "ServerboundChatCommandPacket",
|
"0x04": "ServerboundChatCommandPacket",
|
||||||
"0x05": "PacketPlayInChat",
|
"0x05": "PacketPlayInChat",
|
||||||
"0x16": "PacketPlayInPosition",
|
"0x17": "PacketPlayInPosition",
|
||||||
"0x17": "PacketPlayInPositionAndLook",
|
"0x18": "PacketPlayInPositionAndLook",
|
||||||
"0x18": "PacketPlayInRotation",
|
"0x19": "PacketPlayInRotation",
|
||||||
"0x0F": "PacketPlayInPluginMessaging",
|
"0x10": "PacketPlayInPluginMessaging",
|
||||||
"0x0A": "PacketPlayInTabComplete",
|
"0x0A": "PacketPlayInTabComplete",
|
||||||
"0x2B": "PacketPlayInHeldItemChange",
|
"0x2C": "PacketPlayInHeldItemChange",
|
||||||
"0x27": "PacketPlayInResourcePackStatus",
|
"0x28": "ServerboundResourcePackPacket",
|
||||||
"0x34": "PacketPlayInUseItem",
|
"0x35": "PacketPlayInUseItem",
|
||||||
"0x35": "PacketPlayInBlockPlace",
|
"0x36": "PacketPlayInBlockPlace",
|
||||||
"0x2E": "PacketPlayInSetCreativeSlot",
|
"0x2F": "PacketPlayInSetCreativeSlot",
|
||||||
"0x0D": "PacketPlayInWindowClick",
|
"0x0D": "PacketPlayInWindowClick",
|
||||||
"0x0E": "PacketPlayInCloseWindow",
|
"0x0E": "PacketPlayInCloseWindow",
|
||||||
"0x1C": "PacketPlayInPickItem",
|
"0x1D": "PacketPlayInPickItem",
|
||||||
"0x20": "PacketPlayInBlockDig",
|
"0x21": "PacketPlayInBlockDig",
|
||||||
"0x26": "PacketPlayInItemName"
|
"0x27": "PacketPlayInItemName"
|
||||||
},
|
},
|
||||||
"PlayOut": {
|
"PlayOut": {
|
||||||
"PacketPlayOutLogin": "0x29",
|
"PacketPlayOutLogin": "0x29",
|
||||||
"PacketPlayOutPositionAndLook": "0x3E",
|
"PacketPlayOutPositionAndLook": "0x3E",
|
||||||
"PacketPlayOutSpawnPosition": "0x52",
|
"PacketPlayOutSpawnPosition": "0x54",
|
||||||
"ClientboundSystemChatPacket": "0x67",
|
"ClientboundSystemChatPacket": "0x69",
|
||||||
"PacketPlayOutPlayerAbilities": "0x36",
|
"PacketPlayOutPlayerAbilities": "0x36",
|
||||||
"ClientboundLevelChunkWithLightPacket": "0x25",
|
"ClientboundLevelChunkWithLightPacket": "0x25",
|
||||||
"PacketPlayOutUnloadChunk": "0x1F",
|
"PacketPlayOutUnloadChunk": "0x1F",
|
||||||
"PacketPlayOutKeepAlive": "0x24",
|
"PacketPlayOutKeepAlive": "0x15",
|
||||||
"PacketPlayOutPlayerInfo": "0x3C",
|
"PacketPlayOutPlayerInfo": "0x3C",
|
||||||
"PacketPlayOutUpdateViewPosition": "0x50",
|
"PacketPlayOutUpdateViewPosition": "0x52",
|
||||||
"PacketPlayOutDisconnect": "0x1B",
|
"PacketPlayOutDisconnect": "0x1B",
|
||||||
"PacketPlayOutPluginMessaging": "0x18",
|
"PacketPlayOutPluginMessaging": "0x18",
|
||||||
"PacketPlayOutTabComplete": "0x10",
|
"PacketPlayOutTabComplete": "0x10",
|
||||||
"PacketPlayOutDeclareCommands": "0x11",
|
"PacketPlayOutDeclareCommands": "0x11",
|
||||||
"PacketPlayOutRespawn": "0x43",
|
"PacketPlayOutRespawn": "0x45",
|
||||||
"PacketPlayOutGameState": "0x20",
|
"PacketPlayOutGameState": "0x20",
|
||||||
"PacketPlayOutEntityDestroy": "0x40",
|
"PacketPlayOutEntityDestroy": "0x40",
|
||||||
"PacketPlayOutEntityMetadata": "0x54",
|
"PacketPlayOutEntityMetadata": "0x56",
|
||||||
"PacketPlayOutSpawnEntity": "0x01",
|
"PacketPlayOutSpawnEntity": "0x01",
|
||||||
"PacketPlayOutHeldItemChange": "0x4F",
|
"PacketPlayOutHeldItemChange": "0x51",
|
||||||
"PacketPlayOutPlayerListHeaderFooter": "0x68",
|
"PacketPlayOutPlayerListHeaderFooter": "0x6A",
|
||||||
"PacketPlayOutResourcePackSend": "0x42",
|
"ClientboundResourcePackPushPacket": "0x44",
|
||||||
"ClientboundSetTitlesAnimationPacket": "0x62",
|
"ClientboundSetTitlesAnimationPacket": "0x64",
|
||||||
"ClientboundSetTitleTextPacket": "0x61",
|
"ClientboundSetTitleTextPacket": "0x63",
|
||||||
"ClientboundSetSubtitleTextPacket": "0x5F",
|
"ClientboundSetSubtitleTextPacket": "0x61",
|
||||||
"ClientboundSetActionBarTextPacket": "0x48",
|
"ClientboundSetActionBarTextPacket": "0x4A",
|
||||||
"ClientboundClearTitlesPacket": "0x0F",
|
"ClientboundClearTitlesPacket": "0x0F",
|
||||||
"PacketPlayOutBoss": "0x0A",
|
"PacketPlayOutBoss": "0x0A",
|
||||||
"PacketPlayOutNamedSoundEffect": "0x64",
|
"PacketPlayOutNamedSoundEffect": "0x66",
|
||||||
"PacketPlayOutStopSound": "0x66",
|
"PacketPlayOutStopSound": "0x68",
|
||||||
"PacketPlayOutWindowItems": "0x13",
|
"PacketPlayOutWindowItems": "0x13",
|
||||||
"PacketPlayOutSetSlot": "0x15",
|
"PacketPlayOutSetSlot": "0x15",
|
||||||
"PacketPlayOutOpenWindow": "0x31",
|
"PacketPlayOutOpenWindow": "0x31",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue