Merge pull request #82 from BoomEaro/feature/1.20.5

Support 1.20.6
This commit is contained in:
Max 2024-05-02 13:03:01 +03:00 committed by GitHub
commit cd42e91cd1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 179 additions and 42 deletions

View File

@ -35,7 +35,7 @@ Symbol `X` means all minor versions.
- [x] 1.17.X
- [x] 1.18.X
- [x] 1.19.X
- [x] 1.20-1.20.4
- [x] 1.20-1.20.6
The server **doesn't** support snapshots.

View File

@ -115,7 +115,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
public void handlePacket(Object packet) {
if (packet instanceof Packet) {
((Packet)packet).handle(this, server);
((Packet) packet).handle(this, server);
}
}
@ -199,7 +199,14 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
if (PacketSnapshots.PACKET_PLUGIN_MESSAGE != null)
writePacket(PacketSnapshots.PACKET_PLUGIN_MESSAGE);
if (clientVersion.moreOrEqual(Version.V1_20_5)) {
for (PacketSnapshot packet : PacketSnapshots.PACKETS_REGISTRY_DATA) {
writePacket(packet);
}
} else {
writePacket(PacketSnapshots.PACKET_REGISTRY_DATA);
}
sendPacket(PacketSnapshots.PACKET_FINISH_CONFIGURATION);
}
@ -272,7 +279,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
}
public void setAddress(String host) {
this.address = new InetSocketAddress(host, ((InetSocketAddress)this.address).getPort());
this.address = new InetSocketAddress(host, ((InetSocketAddress) this.address).getPort());
}
boolean checkBungeeGuardHandshake(String handshake) {
@ -333,7 +340,7 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
byte[] mySignature = mac.doFinal(data);
if (!MessageDigest.isEqual(signature, mySignature))
return false;
} catch (InvalidKeyException |java.security.NoSuchAlgorithmException e) {
} catch (InvalidKeyException | java.security.NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
int version = buf.readVarInt();

View File

@ -17,6 +17,9 @@
package ua.nanit.limbo.connection;
import net.kyori.adventure.nbt.BinaryTag;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.nbt.ListBinaryTag;
import ua.nanit.limbo.LimboConstants;
import ua.nanit.limbo.protocol.PacketSnapshot;
import ua.nanit.limbo.protocol.packets.configuration.PacketFinishConfiguration;
@ -27,6 +30,7 @@ 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 ua.nanit.limbo.world.Dimension;
import java.util.ArrayList;
import java.util.Collections;
@ -60,6 +64,7 @@ public final class PacketSnapshots {
public static PacketSnapshot PACKET_TITLE_LEGACY_TIMES;
public static PacketSnapshot PACKET_REGISTRY_DATA;
public static List<PacketSnapshot> PACKETS_REGISTRY_DATA;
public static PacketSnapshot PACKET_FINISH_CONFIGURATION;
public static List<PacketSnapshot> PACKETS_EMPTY_CHUNKS;
@ -193,6 +198,38 @@ public final class PacketSnapshots {
packetRegistryData.setDimensionRegistry(server.getDimensionRegistry());
PACKET_REGISTRY_DATA = PacketSnapshot.of(packetRegistryData);
Dimension dimension1_20_5 = server.getDimensionRegistry().getDimension_1_20_5();
List<PacketSnapshot> packetRegistries = new ArrayList<>();
CompoundBinaryTag dimensionTag = dimension1_20_5.getData();
for (String registryType : dimensionTag.keySet()) {
CompoundBinaryTag compundRegistryType = dimensionTag.getCompound(registryType);
PacketRegistryData registryData = new PacketRegistryData();
registryData.setDimensionRegistry(server.getDimensionRegistry());
ListBinaryTag values = compundRegistryType.getList("value");
registryData.setMetadataWriter((message, version) -> {
message.writeString(registryType);
message.writeVarInt(values.size());
for (BinaryTag entry : values) {
CompoundBinaryTag entryTag = (CompoundBinaryTag) entry;
String name = entryTag.getString("name");
CompoundBinaryTag element = entryTag.getCompound("element");
message.writeString(name);
message.writeBoolean(true);
message.writeNamelessCompoundTag(element);
}
});
packetRegistries.add(PacketSnapshot.of(registryData));
}
PACKETS_REGISTRY_DATA = packetRegistries;
PACKET_FINISH_CONFIGURATION = PacketSnapshot.of(new PacketFinishConfiguration());
PacketGameEvent packetGameEvent = new PacketGameEvent();

View File

@ -0,0 +1,10 @@
package ua.nanit.limbo.protocol;
import ua.nanit.limbo.protocol.registry.Version;
@FunctionalInterface
public interface MetadataWriter {
void writeData(ByteMessage message, Version version);
}

View File

@ -1,6 +1,7 @@
package ua.nanit.limbo.protocol.packets.configuration;
import ua.nanit.limbo.protocol.ByteMessage;
import ua.nanit.limbo.protocol.MetadataWriter;
import ua.nanit.limbo.protocol.PacketOut;
import ua.nanit.limbo.protocol.registry.Version;
import ua.nanit.limbo.world.DimensionRegistry;
@ -8,13 +9,24 @@ import ua.nanit.limbo.world.DimensionRegistry;
public class PacketRegistryData implements PacketOut {
private DimensionRegistry dimensionRegistry;
private MetadataWriter metadataWriter;
public void setDimensionRegistry(DimensionRegistry dimensionRegistry) {
this.dimensionRegistry = dimensionRegistry;
}
public void setMetadataWriter(MetadataWriter metadataWriter) {
this.metadataWriter = metadataWriter;
}
@Override
public void encode(ByteMessage msg, Version version) {
if (metadataWriter != null) {
if (version.moreOrEqual(Version.V1_20_5)) {
metadataWriter.writeData(msg, version);
return;
}
}
msg.writeNamelessCompoundTag(dimensionRegistry.getCodec_1_20());
}
}

View File

@ -49,6 +49,9 @@ public class PacketLoginSuccess implements PacketOut {
if (version.moreOrEqual(Version.V1_19)) {
msg.writeVarInt(0);
}
if (version.moreOrEqual(Version.V1_20_5)) {
msg.writeBoolean(true);
}
}
@Override

View File

@ -39,6 +39,7 @@ public class PacketJoinGame implements PacketOut {
private boolean isDebug;
private boolean isFlat;
private boolean limitedCrafting;
private boolean secureProfile;
public void setEntityId(int entityId) {
this.entityId = entityId;
@ -100,6 +101,10 @@ public class PacketJoinGame implements PacketOut {
this.limitedCrafting = limitedCrafting;
}
public void setSecureProfile(boolean secureProfile) {
this.secureProfile = secureProfile;
}
@Override
public void encode(ByteMessage msg, Version version) {
msg.writeInt(entityId);
@ -255,7 +260,7 @@ public class PacketJoinGame implements PacketOut {
msg.writeVarInt(0);
}
if (version.moreOrEqual(Version.V1_20_2)) {
if (version.fromTo(Version.V1_20_2, Version.V1_20_3)) {
msg.writeBoolean(isHardcore);
msg.writeStringsArray(worldNames);
msg.writeVarInt(maxPlayers);
@ -274,6 +279,27 @@ public class PacketJoinGame implements PacketOut {
msg.writeBoolean(false);
msg.writeVarInt(0);
}
if (version.moreOrEqual(Version.V1_20_5)) {
msg.writeBoolean(isHardcore);
msg.writeStringsArray(worldNames);
msg.writeVarInt(maxPlayers);
msg.writeVarInt(viewDistance);
msg.writeVarInt(viewDistance); // Simulation Distance
msg.writeBoolean(reducedDebugInfo);
msg.writeBoolean(enableRespawnScreen);
msg.writeBoolean(limitedCrafting);
msg.writeVarInt(dimensionRegistry.getDimension_1_20_5().getId());
msg.writeString(worldName);
msg.writeLong(hashedSeed);
msg.writeByte(gameMode);
msg.writeByte(previousGameMode);
msg.writeBoolean(isDebug);
msg.writeBoolean(isFlat);
msg.writeBoolean(false);
msg.writeVarInt(0);
msg.writeBoolean(secureProfile);
}
}
}

View File

@ -66,7 +66,7 @@ public enum State {
);
serverBound.register(
PacketLoginAcknowledged::new,
map(0x03, V1_20_2, V1_20_3)
map(0x03, V1_20_2, V1_20_5)
);
clientBound.register(PacketDisconnect::new,
map(0x00, Version.getMin(), Version.getMax())
@ -83,36 +83,44 @@ public enum State {
{
clientBound.register(
PacketPluginMessage::new,
map(0x00, V1_20_2, V1_20_3)
map(0x00, V1_20_2, V1_20_3),
map(0x01, V1_20_5, V1_20_5)
);
clientBound.register(
PacketDisconnect::new,
map(0x01, V1_20_2, V1_20_3)
map(0x01, V1_20_2, V1_20_3),
map(0x02, V1_20_5, V1_20_5)
);
clientBound.register(
PacketFinishConfiguration::new,
map(0x02, V1_20_2, V1_20_3)
map(0x02, V1_20_2, V1_20_3),
map(0x03, V1_20_5, V1_20_5)
);
clientBound.register(
PacketKeepAlive::new,
map(0x03, V1_20_2, V1_20_3)
map(0x03, V1_20_2, V1_20_3),
map(0x04, V1_20_5, V1_20_5)
);
clientBound.register(
PacketRegistryData::new,
map(0x05, V1_20_2, V1_20_3)
map(0x05, V1_20_2, V1_20_3),
map(0x07, V1_20_5, V1_20_5)
);
serverBound.register(
PacketPluginMessage::new,
map(0x01, V1_20_2, V1_20_3)
map(0x01, V1_20_2, V1_20_3),
map(0x02, V1_20_2, V1_20_5)
);
serverBound.register(
PacketFinishConfiguration::new,
map(0x02, V1_20_2, V1_20_3)
map(0x02, V1_20_2, V1_20_3),
map(0x03, V1_20_5, V1_20_5)
);
serverBound.register(
PacketKeepAlive::new,
map(0x03, V1_20_2, V1_20_3)
map(0x03, V1_20_2, V1_20_3),
map(0x04, V1_20_5, V1_20_5)
);
}
},
@ -132,7 +140,8 @@ public enum State {
map(0x11, V1_19_3, V1_19_3),
map(0x12, V1_19_4, V1_20),
map(0x14, V1_20_2, V1_20_2),
map(0x15, V1_20_3, V1_20_3)
map(0x15, V1_20_3, V1_20_3),
map(0x18, V1_20_5, V1_20_5)
);
clientBound.register(PacketDeclareCommands::new,
@ -144,7 +153,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_3)
map(0x11, V1_20_2, V1_20_5)
);
clientBound.register(PacketJoinGame::new,
map(0x01, V1_7_2, V1_8),
@ -158,7 +167,8 @@ 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_3)
map(0x29, V1_20_2, V1_20_3),
map(0x2B, V1_20_5, V1_20_5)
);
clientBound.register(PacketPluginMessage::new,
map(0x19, V1_13, V1_13_2),
@ -171,7 +181,8 @@ 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_3)
map(0x18, V1_20_2, V1_20_3),
map(0x19, V1_20_5, V1_20_5)
);
clientBound.register(PacketPlayerAbilities::new,
map(0x39, V1_7_2, V1_8),
@ -187,7 +198,8 @@ 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_3)
map(0x36, V1_20_2, V1_20_3),
map(0x38, V1_20_5, V1_20_5)
);
clientBound.register(PacketPlayerPositionAndLook::new,
map(0x08, V1_7_2, V1_8),
@ -203,7 +215,8 @@ 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_3)
map(0x3E, V1_20_2, V1_20_3),
map(0x40, V1_20_5, V1_20_5)
);
clientBound.register(PacketKeepAlive::new,
map(0x00, V1_7_2, V1_8),
@ -218,7 +231,8 @@ 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_3)
map(0x24, V1_20_2, V1_20_3),
map(0x26, V1_20_5, V1_20_5)
);
clientBound.register(PacketChatMessage::new,
map(0x02, V1_7_2, V1_8),
@ -232,7 +246,8 @@ public enum State {
map(0x60, V1_19_3, V1_19_3),
map(0x64, V1_19_4, V1_20),
map(0x67, V1_20_2, V1_20_2),
map(0x69, V1_20_3, V1_20_3)
map(0x69, V1_20_3, V1_20_3),
map(0x6C, V1_20_5, V1_20_5)
);
clientBound.register(PacketBossBar::new,
map(0x0C, V1_9, V1_14_4),
@ -241,7 +256,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_3)
map(0x0A, V1_20_2, V1_20_5)
);
clientBound.register(PacketPlayerInfo::new,
map(0x38, V1_7_2, V1_8),
@ -257,7 +272,8 @@ 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_3)
map(0x3C, V1_20_2, V1_20_3),
map(0x3E, V1_20_5, V1_20_5)
);
clientBound.register(PacketTitleLegacy::new,
map(0x45, V1_8, V1_11_1),
@ -275,7 +291,8 @@ public enum State {
map(0x5B, V1_19_3, V1_19_3),
map(0x5F, V1_19_4, V1_20),
map(0x61, V1_20_2, V1_20_2),
map(0x63, V1_20_3, V1_20_3)
map(0x63, V1_20_3, V1_20_3),
map(0x65, V1_20_5, V1_20_5)
);
clientBound.register(PacketTitleSetSubTitle::new,
map(0x57, V1_17, V1_17_1),
@ -284,7 +301,8 @@ public enum State {
map(0x59, V1_19_3, V1_19_3),
map(0x5D, V1_19_4, V1_20),
map(0x5F, V1_20_2, V1_20_2),
map(0x61, V1_20_3, V1_20_3)
map(0x61, V1_20_3, V1_20_3),
map(0x63, V1_20_5, V1_20_5)
);
clientBound.register(PacketTitleTimes::new,
map(0x5A, V1_17, V1_17_1),
@ -293,7 +311,8 @@ public enum State {
map(0x5C, V1_19_3, V1_19_3),
map(0x60, V1_19_4, V1_20),
map(0x62, V1_20_2, V1_20_2),
map(0x64, V1_20_3, V1_20_3)
map(0x64, V1_20_3, V1_20_3),
map(0x66, V1_20_5, V1_20_5)
);
clientBound.register(PacketPlayerListHeader::new,
map(0x47, V1_8, V1_8),
@ -312,19 +331,23 @@ public enum State {
map(0x61, V1_19_3, V1_19_3),
map(0x65, V1_19_4, V1_20),
map(0x68, V1_20_2, V1_20_2),
map(0x6A, V1_20_3, V1_20_3)
map(0x6A, V1_20_3, V1_20_3),
map(0x6D, V1_20_5, V1_20_5)
);
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(0x54, V1_20_3, V1_20_3)
map(0x54, V1_20_3, V1_20_3),
map(0x56, V1_20_5, V1_20_5)
);
clientBound.register(PacketGameEvent::new,
map(0x20, V1_20_3, V1_20_3)
map(0x20, V1_20_3, V1_20_3),
map(0x22, V1_20_5, V1_20_5)
);
clientBound.register(PacketEmptyChunk::new,
map(0x25, V1_20_3, V1_20_3)
map(0x25, V1_20_3, V1_20_3),
map(0x27, V1_20_5, V1_20_5)
);
}
};

View File

@ -71,7 +71,8 @@ public enum Version {
V1_20(763),
// 1.20.1 has same protocol number
V1_20_2(764),
V1_20_3(765);
V1_20_3(765),
V1_20_5(766);
private static final Map<Integer, Version> VERSION_MAP;
private static final Version MAX;

View File

@ -33,6 +33,7 @@ public final class DimensionRegistry {
private Dimension defaultDimension_1_16;
private Dimension defaultDimension_1_18_2;
private Dimension dimension_1_20_5;
private CompoundBinaryTag codec_1_16;
private CompoundBinaryTag codec_1_18_2;
@ -82,6 +83,10 @@ public final class DimensionRegistry {
return defaultDimension_1_18_2;
}
public Dimension getDimension_1_20_5() {
return dimension_1_20_5;
}
public void load(String def) throws IOException {
codec_1_16 = readCodecFile("/dimension/codec_1_16.snbt");
codec_1_18_2 = readCodecFile("/dimension/codec_1_18_2.snbt");
@ -94,6 +99,8 @@ public final class DimensionRegistry {
defaultDimension_1_16 = getDefaultDimension(def, codec_1_16);
defaultDimension_1_18_2 = getDefaultDimension(def, codec_1_18_2);
dimension_1_20_5 = getModernDimension(def, codec_1_20);
}
private Dimension getDefaultDimension(String def, CompoundBinaryTag tag) {
@ -116,24 +123,35 @@ public final class DimensionRegistry {
}
}
private Dimension getModernDimension(String def, CompoundBinaryTag tag) {
switch (def.toLowerCase()) {
case "overworld":
return new Dimension(0, "minecraft:overworld", tag);
case "the_nether":
return new Dimension(2, "minecraft:nether", tag);
case "the_end":
return new Dimension(3, "minecraft:the_end", tag);
default:
Logger.warning("Undefined dimension type: '%s'. Using THE_END as default", def);
return new Dimension(3, "minecraft:the_end", tag);
}
}
private CompoundBinaryTag readCodecFile(String resPath) throws IOException {
InputStream in = server.getClass().getResourceAsStream(resPath);
if(in == null)
if (in == null)
throw new FileNotFoundException("Cannot find dimension registry file");
return TagStringIO.get().asCompound(streamToString(in));
}
private String streamToString(InputStream in) throws IOException {
InputStreamReader isReader = new InputStreamReader(in, StandardCharsets.UTF_8);
BufferedReader bufReader = new BufferedReader(isReader);
try (BufferedReader bufReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
String content = bufReader.lines()
.collect(Collectors.joining("\n"));
isReader.close();
bufReader.close();
return content;
}
}
}