Skip to content

Commit

Permalink
Merge pull request #972 from booky10/fix/workaround-spigot-item-conve…
Browse files Browse the repository at this point in the history
…rsion-issues

Use global synchronized registries as fallback
  • Loading branch information
booky10 committed Aug 29, 2024
2 parents e105770 + 9fd5b3b commit fd7bc84
Show file tree
Hide file tree
Showing 13 changed files with 186 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2022 retrooper and contributors
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -27,7 +27,6 @@
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage;
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessageLegacy;
import com.github.retrooper.packetevents.protocol.chat.message.ChatMessage_v1_16;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
import com.github.retrooper.packetevents.protocol.world.Dimension;
Expand All @@ -36,6 +35,7 @@
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import com.github.retrooper.packetevents.util.mappings.IRegistry;
import com.github.retrooper.packetevents.util.mappings.IRegistryHolder;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerChatMessage;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerCloseWindow;
Expand All @@ -53,7 +53,8 @@
import java.util.Map;
import java.util.UUID;

public class User {
public class User implements IRegistryHolder {

private final Object channel;
private ConnectionState decoderState;
private ConnectionState encoderState;
Expand All @@ -75,19 +76,13 @@ public User(Object channel,
}

@ApiStatus.Internal
@SuppressWarnings("unchecked") // should be fine
public <T extends MappedEntity> IRegistry<T> getUserRegistryOrFallback(IRegistry<T> fallbackRegistry) {
IRegistry<?> replacedRegistry = this.registries.get(fallbackRegistry.getRegistryKey());
return replacedRegistry != null ? (IRegistry<T>) replacedRegistry : fallbackRegistry;
}

@ApiStatus.Internal
public IRegistry<?> getUserRegistry(ResourceLocation registryKey) {
@Override
public @Nullable IRegistry<?> getRegistry(ResourceLocation registryKey, ClientVersion version) {
return this.registries.get(registryKey);
}

@ApiStatus.Internal
public void putUserRegistry(IRegistry<?> registry) {
public void putRegistry(IRegistry<?> registry) {
this.registries.put(registry.getRegistryKey(), registry);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public DimensionTypeRef asDimensionTypeRef() {
public com.github.retrooper.packetevents.protocol.world.dimension.DimensionType asDimensionType(
@Nullable User user, @Nullable ClientVersion version) {
IRegistry<com.github.retrooper.packetevents.protocol.world.dimension.DimensionType> registry = user != null
? user.getUserRegistryOrFallback(DimensionTypes.getRegistry()) : DimensionTypes.getRegistry();
? user.getRegistryOr(DimensionTypes.getRegistry()) : DimensionTypes.getRegistry();
String dimName = this.getDimensionName();
if (!dimName.isEmpty()) {
return registry.getByName(new ResourceLocation(dimName));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.github.retrooper.packetevents.util.mappings;

import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.mappings.SynchronizedRegistriesHandler.RegistryEntry;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

@ApiStatus.Internal
public final class GlobalRegistryHolder implements IRegistryHolder {

public static final IRegistryHolder INSTANCE = new GlobalRegistryHolder();

private GlobalRegistryHolder() {
}

public static Object getGlobalRegistryCacheKey(@Nullable User user, ClientVersion version) {
return version; // global registries, only depends on packet version
}

@Override
public @Nullable IRegistry<?> getRegistry(ResourceLocation registryKey, ClientVersion version) {
RegistryEntry<?> registryEntry = SynchronizedRegistriesHandler.getRegistryEntry(registryKey);
if (registryEntry == null) {
return null;
}
Object cacheKey = getGlobalRegistryCacheKey(null, version);
return registryEntry.getSyncedRegistry(cacheKey);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.function.BiFunction;

public interface IRegistry<T extends MappedEntity> {
public interface IRegistry<T extends MappedEntity> extends BiFunction<ClientVersion, Integer, T> {

default @Nullable T getByName(ResourceLocation name) {
return this.getByName(name.toString());
Expand All @@ -51,4 +52,9 @@ default int getId(String entityName, ClientVersion version) {
Collection<T> getEntries();

ResourceLocation getRegistryKey();

@Override
default T apply(ClientVersion version, Integer id) {
return this.getById(version, id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* This file is part of packetevents - https://github.com/retrooper/packetevents
* Copyright (C) 2024 retrooper and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.github.retrooper.packetevents.util.mappings;

import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

@ApiStatus.Internal
public interface IRegistryHolder {

default <T extends MappedEntity> IRegistry<T> getRegistryOr(IRegistry<T> fallbackRegistry) {
return this.getRegistryOr(fallbackRegistry, PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
}

@SuppressWarnings("unchecked") // should be fine
default <T extends MappedEntity> IRegistry<T> getRegistryOr(IRegistry<T> fallbackRegistry, ClientVersion version) {
IRegistry<?> replacedRegistry = this.getRegistry(fallbackRegistry.getRegistryKey(), version);
return replacedRegistry != null ? (IRegistry<T>) replacedRegistry : fallbackRegistry;
}

default @Nullable IRegistry<?> getRegistry(ResourceLocation registryKey) {
return this.getRegistry(registryKey, PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
}

@Nullable IRegistry<?> getRegistry(ResourceLocation registryKey, ClientVersion version);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,15 @@

package com.github.retrooper.packetevents.util.mappings;

import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.resources.ResourceLocation;
import com.github.retrooper.packetevents.wrapper.configuration.server.WrapperConfigServerRegistryData.RegistryElement;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class SimpleRegistry<T extends MappedEntity> implements IRegistry<T> {
Expand Down Expand Up @@ -93,4 +90,9 @@ public Collection<T> getEntries() {
public ResourceLocation getRegistryKey() {
return this.registryKey;
}

@Override
public String toString() {
return "SimpleRegistry[" + this.registryKey + ']';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ public final class SynchronizedRegistriesHandler {
private SynchronizedRegistriesHandler() {
}

public static @Nullable RegistryEntry<?> getRegistryEntry(ResourceLocation registryKey) {
return REGISTRY_KEYS.get(registryKey);
}

public static void handleRegistry(
User user, ClientVersion version,
ResourceLocation registryName,
Expand All @@ -108,7 +112,7 @@ public static void handleRegistry(
syncedRegistry = registryData.computeSyncedRegistry(cacheKey, () ->
registryData.createFromElements(elements, version));
}
user.putUserRegistry(syncedRegistry);
user.putRegistry(syncedRegistry);
}

public static void handleLegacyRegistries(
Expand All @@ -130,13 +134,15 @@ public static void handleLegacyRegistries(
}
}

@ApiStatus.Internal
@FunctionalInterface
private interface NbtEntryDecoder<T> {
public interface NbtEntryDecoder<T> {

T decode(NBT nbt, ClientVersion version, @Nullable TypesBuilderData data);
}

private static final class RegistryEntry<T extends MappedEntity & CopyableEntity<T>> {
@ApiStatus.Internal
public static final class RegistryEntry<T extends MappedEntity & CopyableEntity<T>> {

private final IRegistry<T> baseRegistry;
private final NbtEntryDecoder<T> decoder;
Expand All @@ -155,6 +161,10 @@ public RegistryEntry(
this.decoder = decoder;
}

public @Nullable SimpleRegistry<T> getSyncedRegistry(Object key) {
return this.syncedRegistries.get(key);
}

@SuppressWarnings("unchecked")
public SimpleRegistry<T> computeSyncedRegistry(Object key, Supplier<SimpleRegistry<?>> registry) {
return this.syncedRegistries.computeIfAbsent(key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,9 @@ public Collection<T> getEntries() {
public ResourceLocation getRegistryKey() {
return this.registryKey;
}

@Override
public String toString() {
return "VersionedRegistry[" + this.registryKey + ']';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,15 @@
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
import com.github.retrooper.packetevents.protocol.PacketSide;
import com.github.retrooper.packetevents.protocol.chat.*;
import com.github.retrooper.packetevents.protocol.chat.ChatType;
import com.github.retrooper.packetevents.protocol.chat.ChatTypes;
import com.github.retrooper.packetevents.protocol.chat.LastSeenMessages;
import com.github.retrooper.packetevents.protocol.chat.MessageSignature;
import com.github.retrooper.packetevents.protocol.chat.Node;
import com.github.retrooper.packetevents.protocol.chat.Parsers;
import com.github.retrooper.packetevents.protocol.chat.Parsers.Parser;
import com.github.retrooper.packetevents.protocol.chat.RemoteChatSession;
import com.github.retrooper.packetevents.protocol.chat.SignedCommandArgument;
import com.github.retrooper.packetevents.protocol.chat.filter.FilterMask;
import com.github.retrooper.packetevents.protocol.chat.filter.FilterMaskType;
import com.github.retrooper.packetevents.protocol.component.ComponentType;
Expand Down Expand Up @@ -88,7 +95,9 @@
import com.github.retrooper.packetevents.util.crypto.MinecraftEncryptionUtil;
import com.github.retrooper.packetevents.util.crypto.SaltSignature;
import com.github.retrooper.packetevents.util.crypto.SignatureData;
import com.github.retrooper.packetevents.util.mappings.GlobalRegistryHolder;
import com.github.retrooper.packetevents.util.mappings.IRegistry;
import com.github.retrooper.packetevents.util.mappings.IRegistryHolder;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.Style;
import org.jetbrains.annotations.ApiStatus;
Expand All @@ -100,7 +109,16 @@
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.time.Instant;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
Expand Down Expand Up @@ -1462,31 +1480,42 @@ public void writeEnum(Enum<?> value) {
}

public <Z extends MappedEntity> Z readMappedEntity(BiFunction<ClientVersion, Integer, Z> getter) {
return getter.apply(this.serverVersion.toClientVersion(), this.readVarInt());
int id = this.readVarInt();
Z entity = getter.apply(this.serverVersion.toClientVersion(), id);
if (entity == null) {
throw new IllegalStateException("Can't find mapped entity with id " + id + " using " + getter);
}
return entity;
}

public IRegistryHolder getRegistryHolder() {
// workaround to make packet wrappers work without user context on spigot/fabric servers
// this will not work for bungee or velocity, as we need to have some reference to get
// the actual cache key
return this.user != null ? this.user : GlobalRegistryHolder.INSTANCE;
}

public <Z extends MappedEntity> Z readMappedEntityOrDirect(
BiFunction<ClientVersion, Integer, Z> getter, Reader<Z> directReader) {
int id = this.readVarInt();
if (id != 0) { // registered in registry
return getter.apply(this.serverVersion.toClientVersion(), id - 1);
if (id == 0) { // not registered in registry
return directReader.apply(this);
}
return directReader.apply(this);
Z entity = getter.apply(this.serverVersion.toClientVersion(), id - 1);
if (entity == null) {
throw new IllegalStateException("Can't find mapped entity with id " + id + " using " + getter);
}
return entity;
}

public <Z extends MappedEntity> Z readMappedEntity(IRegistry<Z> registry) {
if (this.user != null) {
registry = this.user.getUserRegistryOrFallback(registry);
}
return this.readMappedEntity(registry::getById);
IRegistry<Z> replacedRegistry = this.getRegistryHolder().getRegistryOr(registry);
return this.readMappedEntity((BiFunction<ClientVersion, Integer, Z>) replacedRegistry);
}

public <Z extends MappedEntity> Z readMappedEntityOrDirect(
IRegistry<Z> registry, Reader<Z> directReader) {
if (this.user != null) {
registry = this.user.getUserRegistryOrFallback(registry);
}
return this.readMappedEntityOrDirect(registry::getById, directReader);
public <Z extends MappedEntity> Z readMappedEntityOrDirect(IRegistry<Z> registry, Reader<Z> directReader) {
IRegistry<Z> replacedRegistry = this.getRegistryHolder().getRegistryOr(registry);
return this.readMappedEntityOrDirect((BiFunction<ClientVersion, Integer, Z>) replacedRegistry, directReader);
}

public void writeMappedEntity(MappedEntity entity) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -504,8 +504,7 @@ public void setDimensionTypeRef(DimensionTypeRef dimensionTypeRef) {
}

public DimensionType getDimensionType() {
IRegistry<DimensionType> registry = this.user == null ? DimensionTypes.getRegistry() :
this.user.getUserRegistryOrFallback(DimensionTypes.getRegistry());
IRegistry<DimensionType> registry = this.getRegistryHolder().getRegistryOr(DimensionTypes.getRegistry());
return this.dimensionTypeRef.resolve(registry, this.serverVersion.toClientVersion());
}

Expand Down
Loading

0 comments on commit fd7bc84

Please sign in to comment.