Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Network synced registries #866

Merged
merged 67 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
172cfce
WIP starting network synchronized registries
booky10 Jun 25, 2024
92564a3
More WIP changes to networked registries
booky10 Jun 27, 2024
dfd490a
Merge branch '2.0' into feat/network-synced-registries
booky10 Jun 30, 2024
7b209c9
Revert changes to Dimension
booky10 Jun 30, 2024
3f0cb7e
Start working on dimension type registry
booky10 Jun 30, 2024
4fdc9c6
Finish encode of DimensionType
booky10 Jul 1, 2024
b01db5c
Work on creating registries of sent registries
booky10 Jul 1, 2024
699fd9a
Finish migrating Dimension to DimensionType
booky10 Jul 1, 2024
0690c45
Add quality methods to StaticDimensionType
booky10 Jul 1, 2024
f4fc20a
Revert formatting changes in ChunkReader_v1_7
booky10 Jul 1, 2024
902c99a
Revert some now useless changes to MappedEntity#getId
booky10 Jul 1, 2024
8315b8d
Implement chat_type as a synchronized registry
booky10 Jul 1, 2024
3f309bc
Migrate usages of chat types to new registry
booky10 Jul 1, 2024
33f50a0
Implement trim_pattern as a synchronized registry
booky10 Jul 1, 2024
c3b8c21
Implement trim_material as a synchronized registry
booky10 Jul 1, 2024
6e87103
Move everything related to registries from InternalPacketListener to …
booky10 Jul 1, 2024
884ab80
Start working on enchantment registry
booky10 Jul 1, 2024
31447cb
Fix test errors
booky10 Jul 1, 2024
8908cce
Implement enchantment effect component types
booky10 Jul 1, 2024
afcdfae
Fix version being ignored in User#getMinWorldHeight
booky10 Jul 1, 2024
ba08959
Add wolf_variant registry and start with biome registry
booky10 Jul 1, 2024
8c02988
Save dimension type as reference while decoding
booky10 Jul 2, 2024
dd057ca
Finish biome effects implementation
booky10 Jul 3, 2024
3822609
Implement most particle data codecs
booky10 Jul 3, 2024
11d2d97
Fix biome mapping not being compressed and shadowed
booky10 Jul 3, 2024
08120db
Add small biome mapping test
booky10 Jul 3, 2024
e056f1c
Implement synchronized painting variant registries
booky10 Jul 8, 2024
4961ad6
Add biome registry handling to SynchronizedRegistriesHandler
booky10 Jul 8, 2024
0e5a443
Fix various issues encountered on login
booky10 Jul 8, 2024
adef187
Fix MappedEntitySet codec
booky10 Jul 8, 2024
4ab220f
Make TrimMaterial override armor materials optional
booky10 Jul 8, 2024
9fdd161
Merge branch '2.0' into feat/network-synced-registries
booky10 Jul 8, 2024
4ed6443
Allow enchantment definition slots to be defined directly
booky10 Jul 8, 2024
87fa35d
Fix enchantment registry not being able to be replaced
booky10 Jul 8, 2024
a08f898
Allow chat type decoration parameters to be defined directly
booky10 Jul 8, 2024
1f7a09a
Current WIP, adds damage types and jukebox
libraryaddict Jul 30, 2024
b27f64c
Missing license disclaimer thingy
libraryaddict Jul 30, 2024
acc2207
Rename JukeboxSong and StaticJukeboxSong
libraryaddict Jul 30, 2024
4549d07
IJukeboxSong
libraryaddict Jul 31, 2024
3c55703
feature: damage event wrapper using new damage types
retrooper Aug 4, 2024
1f85797
Merge pull request #1 from packetevents/2.0
libraryaddict Aug 4, 2024
7da389d
feature: 1.21 enchantment mappings (ordered alphabetically)
retrooper Aug 4, 2024
0039ab8
Resolve small backwards compatibility issues
booky10 Aug 4, 2024
12e0869
Fix JukeboxSongs#values javadoc
booky10 Aug 4, 2024
9b22739
Remove setters from jukebox song interface
booky10 Aug 4, 2024
7a5b425
Merge pull request #1 from libraryaddict/feat/network-synced-registries
booky10 Aug 4, 2024
c057f18
Merge branch '2.0' into feat/network-synced-registries
booky10 Aug 4, 2024
b5320f2
Fix data reading for biomes and enchantment types
booky10 Aug 4, 2024
f0d499a
Add more biome mappings
booky10 Aug 4, 2024
679aea8
Add even more biome mappings
booky10 Aug 4, 2024
b247807
Fix biome mapping test
booky10 Aug 4, 2024
16733e5
Add full legacy data support for biomes
booky10 Aug 4, 2024
ea56cfd
Add backwards compatibility support for chat types
booky10 Aug 4, 2024
e2283d6
Fix backwards compatibility for encoding trim patterns
booky10 Aug 4, 2024
d988d0c
Fix backwards compatibility for dimension type codec
booky10 Aug 4, 2024
c152040
deletion: remove hard-coded 1.21 enchantment type mappings (as tempor…
retrooper Aug 5, 2024
a3063f0
feature: cache registries globally on non-proxy servers
retrooper Aug 5, 2024
676cb6c
feature: cache legacy registries
retrooper Aug 5, 2024
3fa6a0f
fix: wrong tag name used in ParticleDustData
retrooper Aug 5, 2024
22060a9
Actually make caching work by not decoding registries when not needed
booky10 Aug 6, 2024
c2cdafb
Add system property to force disable caching
booky10 Aug 6, 2024
26c30f4
Implement key-based registry caching and velocity proxy per-server ca…
booky10 Aug 6, 2024
963ec4e
Revert some debug changes which weren't meant to be pushed
booky10 Aug 6, 2024
55c1093
Fix biome and enchantment type definitions on bungee
booky10 Aug 6, 2024
e9eb441
Implement caching on bungee platform
booky10 Aug 6, 2024
7b152ff
Don't store exact copies of vanilla registry elements
booky10 Aug 6, 2024
2f45e9e
Add equality methods for all dynamic registry value classes
booky10 Aug 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ mappingCompression {
compress("block/legacy_block_mappings.json")
compress("block/modern_block_mappings.json")

compress("enchantment/enchantment_type_data.json")

compress("stats/statistics.json")

compress("world/biome_data.json")
}

with<JsonArrayCompressionStrategy> {
Expand All @@ -61,13 +65,19 @@ mappingCompression {

compress("command/argument_parser_mappings.json")

compress("damage/damagetype_mappings.json")

compress("enchantment/effect_component_type.json")

compress("entity/entity_data_type_mappings.json")
compress("entity/painting_mappings.json")
compress("entity/wolf_variant_mappings.json")

compress("item/item_armor_material_mappings.json")
compress("item/item_banner_pattern_mappings.json")
compress("item/item_component_mappings.json")
compress("item/item_instrument_mappings.json")
compress("item/item_jukebox_song_mappings.json")
compress("item/item_map_decoration_type_mappings.json")
compress("item/item_potion_mappings.json")
compress("item/item_trim_material_mappings.json")
Expand All @@ -78,6 +88,7 @@ mappingCompression {

compress("sound/sound_mappings.json")

compress("world/biome_mappings.json")
compress("world/world_position_source_mappings.json")
}

Expand All @@ -89,6 +100,8 @@ mappingCompression {
compress("entity/legacy_entity_type_mappings.json")

compress("item/item_type_mappings.json")

compress("world/dimension_type_mappings.json")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,21 @@
import com.github.retrooper.packetevents.manager.protocol.ProtocolManager;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.ConnectionState;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.mappings.SynchronizedRegistriesHandler;
import com.github.retrooper.packetevents.wrapper.configuration.server.WrapperConfigServerRegistryData;
import com.github.retrooper.packetevents.wrapper.configuration.server.WrapperConfigServerRegistryData.RegistryElement;
import com.github.retrooper.packetevents.wrapper.handshaking.client.WrapperHandshakingClientHandshake;
import com.github.retrooper.packetevents.wrapper.login.server.WrapperLoginServerLoginSuccess;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerJoinGame;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerRespawn;

import java.net.InetSocketAddress;
import java.util.List;

public class InternalPacketListener extends PacketListenerAbstract {

private static final ResourceLocation DIMENSION_TYPE_REGISTRY_KEY =
ResourceLocation.minecraft("dimension_type");

public InternalPacketListener() {
this(PacketListenerPriority.LOWEST);
}
Expand Down Expand Up @@ -92,94 +82,37 @@ public void onPacketSend(PacketSendEvent event) {
}
}

// The server sends dimension information in configuration phase >= 1.20.2
// The server sends dimension information in configuration phase, since 1.20.2
else if (event.getPacketType() == PacketType.Configuration.Server.REGISTRY_DATA) {
WrapperConfigServerRegistryData registryData = new WrapperConfigServerRegistryData(event);

// Store world data
NBTCompound registryDataTag = registryData.getRegistryData();
NBTList<NBTCompound> list = null;
if (registryDataTag != null) { // <1.20.5
//Handle dimension type
NBTCompound dimensionTypes = registryDataTag
.getCompoundTagOrNull(DIMENSION_TYPE_REGISTRY_KEY.toString());
if (dimensionTypes == null) {
dimensionTypes = registryDataTag
.getCompoundTagOrNull(DIMENSION_TYPE_REGISTRY_KEY.getKey());
}
if (dimensionTypes != null) {
list = dimensionTypes.getCompoundListTagOrNull("value");
}
if (list == null) {
list = new NBTList<>(NBTType.COMPOUND);
PacketEvents.getAPI().getLogger().warning("Can't find dimension type registry in registry data, "
+ "this may cause issues; available registries: " + registryDataTag.getTags().keySet());
}
} else if (DIMENSION_TYPE_REGISTRY_KEY.equals(registryData.getRegistryKey())) { // >=1.20.5
// remap to legacy format
list = new NBTList<>(NBTType.COMPOUND);
List<RegistryElement> elements = registryData.getElements();
if (elements != null) {
int i = 0;
for (RegistryElement element : elements) {
NBTCompound tag = new NBTCompound();
tag.setTag("name", new NBTString(element.getId().toString()));
tag.setTag("id", new NBTInt(i++));
if (element.getData() != null) { // may be null because of known packs not being sent
tag.setTag("element", element.getData());
}
list.addTag(tag);
}
}
WrapperConfigServerRegistryData packet = new WrapperConfigServerRegistryData(event);

if (packet.getElements() != null) { // 1.20.2 to 1.20.5
SynchronizedRegistriesHandler.handleRegistry(user, packet.getServerVersion().toClientVersion(),
packet.getRegistryKey(), packet.getElements());
}
if (list != null) {
user.setWorldNBT(list);
if (packet.getRegistryData() != null) { // since 1.20.5
SynchronizedRegistriesHandler.handleLegacyRegistries(user, packet.getServerVersion()
.toClientVersion(), packet.getRegistryData());
}
}

// The server sends dimension information in login packet for >= 1.17 and < 1.20.2
// The server sends registry info in login packet for 1.16 to 1.20.1
else if (event.getPacketType() == PacketType.Play.Server.JOIN_GAME) {
WrapperPlayServerJoinGame joinGame = new WrapperPlayServerJoinGame(event);
user.setEntityId(joinGame.getEntityId());
user.setDimension(joinGame.getDimension());
if (event.getServerVersion().isOlderThanOrEquals(ServerVersion.V_1_16_5)) {
return; // Fixed world height, no tags are sent to the client
}

// Store world data
NBTCompound dimensionCodec = joinGame.getDimensionCodec();
if (dimensionCodec != null) {
NBTList<NBTCompound> types = null;
NBTCompound dimensionTypes = dimensionCodec
.getCompoundTagOrNull(DIMENSION_TYPE_REGISTRY_KEY.toString());
if (dimensionTypes == null) {
dimensionTypes = dimensionCodec
.getCompoundTagOrNull(DIMENSION_TYPE_REGISTRY_KEY.getKey());
}
if (dimensionTypes != null) { // account for dimension type registry somehow going missing
types = dimensionTypes.getCompoundListTagOrNull("value");
}
if (types == null) {
types = new NBTList<>(NBTType.COMPOUND);
PacketEvents.getAPI().getLogger().warning("Can't find dimension type registry in join packet, "
+ "this may cause issues; available registries: " + dimensionCodec.getTags().keySet());
}
user.setWorldNBT(types);
if (joinGame.getDimensionCodec() != null) { // 1.16 to 1.20.1
SynchronizedRegistriesHandler.handleLegacyRegistries(user, joinGame.getServerVersion().toClientVersion(),
joinGame.getDimensionCodec());
}

// Update world height
user.switchDimensionType(joinGame.getServerVersion(), joinGame.getDimension());
user.setDimensionType(joinGame.getDimensionType());
}

// Respawn is used to switch dimensions
else if (event.getPacketType() == PacketType.Play.Server.RESPAWN) {
WrapperPlayServerRespawn respawn = new WrapperPlayServerRespawn(event);
user.setDimension(respawn.getDimension());
if (event.getServerVersion().isOlderThanOrEquals(ServerVersion.V_1_16_5)) {
return; // Fixed world height, no tags are sent to the client
}

user.switchDimensionType(respawn.getServerVersion(), respawn.getDimension());
WrapperPlayServerRespawn packet = new WrapperPlayServerRespawn(event);
user.setDimensionType(packet.getDimensionType());
} else if (event.getPacketType() == PacketType.Play.Server.CONFIGURATION_START) {
user.setEncoderState(ConnectionState.CONFIGURATION);
} else if (event.getPacketType() == PacketType.Configuration.Server.CONFIGURATION_END) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@

package com.github.retrooper.packetevents.manager.server;

import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.User;
import org.jetbrains.annotations.Nullable;

public interface ServerManager {
/**
* Get the server version.
Expand All @@ -34,4 +38,20 @@ public interface ServerManager {
default SystemOS getOS() {
return SystemOS.getOS();
}

/**
* Gets a platform-specific network-synchronized-registries cache key.
* <p>
* This tells packetevents, if a registry should be cached or read again. On
* backend servers with global registries, this may be a constant value. On
* proxy servers with per-server registries, this may be a value which depends
* on the current server the {@link User} is on.
*
* @param user the {@link User} for which the registry gets read
* @param version the version the packet is for
* @return some value or null for no caching at all
*/
default @Nullable Object getRegistryCacheKey(User user, ClientVersion version) {
return null; // no caching
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,31 @@
package com.github.retrooper.packetevents.protocol.chat;

import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_19_1;
import com.github.retrooper.packetevents.protocol.mapper.CopyableEntity;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.protocol.nbt.NBT;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.util.mappings.TypesBuilderData;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.util.Index;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

public interface ChatType extends MappedEntity {
public interface ChatType extends MappedEntity, CopyableEntity<ChatType> {

ChatTypeDecoration getChatDecoration();

@ApiStatus.Obsolete(since = "1.19.1")
ChatTypeDecoration getOverlayDecoration();

ChatTypeDecoration getNarrationDecoration();

@ApiStatus.Obsolete(since = "1.19.1")
NarrationPriority getNarrationPriority();

static ChatType readDirect(PacketWrapper<?> wrapper) {
ChatTypeDecoration chatDecoration = ChatTypeDecoration.read(wrapper);
ChatTypeDecoration narrationDecoration = ChatTypeDecoration.read(wrapper);
Expand All @@ -41,9 +55,75 @@ static void writeDirect(PacketWrapper<?> wrapper, ChatType chatType) {
ChatTypeDecoration.write(wrapper, chatType.getNarrationDecoration());
}

static ChatType decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data) {
NBTCompound compound = (NBTCompound) nbt;
NBTCompound chatTag = compound.getCompoundTagOrThrow("chat");
NBTCompound narrationTag = compound.getCompoundTagOrThrow("narration");

ChatTypeDecoration overlay = null;
NarrationPriority narrationPriority = null;
if (version.isOlderThan(ClientVersion.V_1_19_1)) {
overlay = ChatTypeDecoration.decode(compound.getCompoundTagOrThrow("overlay"), version);
narrationPriority = NarrationPriority.ID_INDEX.valueOrThrow(
narrationTag.getStringTagValueOrThrow("priority"));
chatTag = chatTag.getCompoundTagOrThrow("description");
narrationTag = narrationTag.getCompoundTagOrThrow("description");
}

ChatTypeDecoration chat = ChatTypeDecoration.decode(chatTag, version);
ChatTypeDecoration narration = ChatTypeDecoration.decode(narrationTag, version);
return new StaticChatType(data, chat, overlay, narration, narrationPriority);
}

static NBT encode(ChatType chatType, ClientVersion version) {
NBTCompound compound = new NBTCompound();
NBT chatTag = ChatTypeDecoration.encode(chatType.getChatDecoration(), version);
NBT narrationTag = ChatTypeDecoration.encode(chatType.getNarrationDecoration(), version);

if (version.isOlderThan(ClientVersion.V_1_19_1)) {
if (chatType.getOverlayDecoration() != null) {
compound.setTag("overlay",
ChatTypeDecoration.encode(chatType.getOverlayDecoration(), version));
}
NBTCompound narrationCompound = new NBTCompound();
narrationCompound.setTag("description", narrationTag);
if (chatType.getNarrationPriority() != null) {
narrationCompound.setTag("priority", new NBTString(chatType.getNarrationPriority().getId()));
}
narrationTag = narrationCompound;
NBTCompound chatCompound = new NBTCompound();
chatCompound.setTag("description", chatTag);
chatTag = chatCompound;
}

compound.setTag("chat", chatTag);
compound.setTag("narration", narrationTag);
return compound;
}

class Bound extends ChatMessage_v1_19_1.ChatTypeBoundNetwork {
public Bound(ChatType type, Component name, @Nullable Component targetName) {
super(type, name, targetName);
}
}

@ApiStatus.Obsolete(since = "1.19.1")
enum NarrationPriority {

CHAT("chat"),
SYSTEM("system");

public static final Index<String, NarrationPriority> ID_INDEX = Index.create(
NarrationPriority.class, NarrationPriority::getId);

private final String id;

NarrationPriority(String id) {
this.id = id;
}

public String getId() {
return this.id;
}
}
}
Loading