Reimplement ItemStack Obfuscation (#11817)

Reimplementation of the itemstack obfuscation config that
leverages the component patch map codec to drop
unwanted components on items or replaces them with
sanitized versions.

Co-authored-by: Bjarne Koll <git@lynxplay.dev>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
This commit is contained in:
Owen
2025-01-09 12:58:18 -05:00
committed by GitHub
parent efdcaa25ee
commit 55f3f280cb
17 changed files with 524 additions and 80 deletions

View File

@@ -80,7 +80,7 @@ public abstract class Configurations<G, W> {
}
@MustBeInvokedByOverriders
protected YamlConfigurationLoader.Builder createGlobalLoaderBuilder() {
protected YamlConfigurationLoader.Builder createGlobalLoaderBuilder(RegistryAccess registryAccess) {
return this.createLoaderBuilder();
}
@@ -104,7 +104,7 @@ public abstract class Configurations<G, W> {
}
public G initializeGlobalConfiguration(final RegistryAccess registryAccess) throws ConfigurateException {
return this.initializeGlobalConfiguration(creator(this.globalConfigClass, true));
return this.initializeGlobalConfiguration(registryAccess, creator(this.globalConfigClass, true));
}
private void trySaveFileNode(YamlConfigurationLoader loader, ConfigurationNode node, String filename) throws ConfigurateException {
@@ -117,9 +117,9 @@ public abstract class Configurations<G, W> {
}
}
protected G initializeGlobalConfiguration(final CheckedFunction<ConfigurationNode, G, SerializationException> creator) throws ConfigurateException {
protected G initializeGlobalConfiguration(final RegistryAccess registryAccess, final CheckedFunction<ConfigurationNode, G, SerializationException> creator) throws ConfigurateException {
final Path configFile = this.globalFolder.resolve(this.globalConfigFileName);
final YamlConfigurationLoader loader = this.createGlobalLoaderBuilder()
final YamlConfigurationLoader loader = this.createGlobalLoaderBuilder(registryAccess)
.defaultOptions(this.applyObjectMapperFactory(this.createGlobalObjectMapperFactoryBuilder().build()))
.path(configFile)
.build();

View File

@@ -5,10 +5,14 @@ import io.papermc.paper.FeatureHooks;
import io.papermc.paper.configuration.constraint.Constraints;
import io.papermc.paper.configuration.type.number.DoubleOr;
import io.papermc.paper.configuration.type.number.IntOr;
import io.papermc.paper.util.ItemObfuscationBinding;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ServerboundPlaceRecipePacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Items;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
@@ -20,6 +24,7 @@ import org.spongepowered.configurate.objectmapping.meta.Setting;
import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt;
import java.util.Set;
@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal", "FieldMayBeFinal", "NotNullFieldNotInitialized", "InnerClassMayBeStatic"})
public class GlobalConfiguration extends ConfigurationPart {
@@ -69,7 +74,7 @@ public class GlobalConfiguration extends ConfigurationPart {
)
public int playerMaxConcurrentChunkGenerates = 0;
}
static void set(GlobalConfiguration instance) {
static void set(final GlobalConfiguration instance) {
GlobalConfiguration.instance = instance;
}
@@ -354,4 +359,41 @@ public class GlobalConfiguration extends ConfigurationPart {
public boolean disableChorusPlantUpdates = false;
public boolean disableMushroomBlockUpdates = false;
}
public Anticheat anticheat;
public class Anticheat extends ConfigurationPart {
public Obfuscation obfuscation;
public class Obfuscation extends ConfigurationPart {
public Items items;
public class Items extends ConfigurationPart {
public boolean enableItemObfuscation = false;
public ItemObfuscationBinding.AssetObfuscationConfiguration allModels = new ItemObfuscationBinding.AssetObfuscationConfiguration(
true,
Set.of(DataComponents.LODESTONE_TRACKER),
Set.of()
);
public Map<ResourceLocation, ItemObfuscationBinding.AssetObfuscationConfiguration> modelOverrides = Map.of(
Objects.requireNonNull(net.minecraft.world.item.Items.ELYTRA.components().get(DataComponents.ITEM_MODEL)),
new ItemObfuscationBinding.AssetObfuscationConfiguration(
true,
Set.of(DataComponents.DAMAGE),
Set.of()
)
);
public transient ItemObfuscationBinding binding;
@PostProcess
public void bindDataSanitizer() {
this.binding = new ItemObfuscationBinding(this);
}
}
}
}
}

View File

@@ -10,6 +10,7 @@ import io.papermc.paper.configuration.serializer.ComponentSerializer;
import io.papermc.paper.configuration.serializer.EnumValueSerializer;
import io.papermc.paper.configuration.serializer.NbtPathSerializer;
import io.papermc.paper.configuration.serializer.PacketClassSerializer;
import io.papermc.paper.configuration.serializer.ResourceLocationSerializer;
import io.papermc.paper.configuration.serializer.StringRepresentableSerializer;
import io.papermc.paper.configuration.serializer.collections.FastutilMapSerializer;
import io.papermc.paper.configuration.serializer.collections.MapSerializer;
@@ -48,6 +49,7 @@ import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
@@ -180,6 +182,7 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
.register(Duration.SERIALIZER)
.register(DurationOrDisabled.SERIALIZER)
.register(NbtPathSerializer.SERIALIZER)
.register(ResourceLocationSerializer.INSTANCE)
);
}
@@ -193,16 +196,17 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
}
@Override
protected YamlConfigurationLoader.Builder createGlobalLoaderBuilder() {
return super.createGlobalLoaderBuilder()
.defaultOptions(PaperConfigurations::defaultGlobalOptions);
protected YamlConfigurationLoader.Builder createGlobalLoaderBuilder(RegistryAccess registryAccess) {
return super.createGlobalLoaderBuilder(registryAccess)
.defaultOptions((options) -> defaultGlobalOptions(registryAccess, options));
}
private static ConfigurationOptions defaultGlobalOptions(ConfigurationOptions options) {
private static ConfigurationOptions defaultGlobalOptions(RegistryAccess registryAccess, ConfigurationOptions options) {
return options
.header(GLOBAL_HEADER)
.serializers(builder -> builder
.register(new PacketClassSerializer())
.register(new RegistryValueSerializer<>(new TypeToken<DataComponentType<?>>() {}, registryAccess, Registries.DATA_COMPONENT_TYPE, false))
);
}
@@ -316,7 +320,7 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
public void reloadConfigs(MinecraftServer server) {
try {
this.initializeGlobalConfiguration(reloader(this.globalConfigClass, GlobalConfiguration.get()));
this.initializeGlobalConfiguration(server.registryAccess(), reloader(this.globalConfigClass, GlobalConfiguration.get()));
this.initializeWorldDefaultsConfiguration(server.registryAccess());
for (ServerLevel level : server.getAllLevels()) {
this.createWorldConfig(createWorldContextMap(level), reloader(this.worldConfigClass, level.paperConfig()));
@@ -454,9 +458,9 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
}
@VisibleForTesting
static ConfigurationNode createForTesting() {
static ConfigurationNode createForTesting(RegistryAccess registryAccess) {
ObjectMapper.Factory factory = defaultGlobalFactoryBuilder(ObjectMapper.factoryBuilder()).build();
ConfigurationOptions options = defaultGlobalOptions(defaultOptions(ConfigurationOptions.defaults()))
ConfigurationOptions options = defaultGlobalOptions(registryAccess, defaultOptions(ConfigurationOptions.defaults()))
.serializers(builder -> builder.register(type -> ConfigurationPart.class.isAssignableFrom(erase(type)), factory.asTypeSerializer()));
return BasicConfigurationNode.root(options);
}

View File

@@ -88,17 +88,6 @@ public class WorldConfiguration extends ConfigurationPart {
public class Anticheat extends ConfigurationPart {
public Obfuscation obfuscation;
public class Obfuscation extends ConfigurationPart {
public Items items = new Items();
public class Items extends ConfigurationPart {
public boolean hideItemmeta = false;
public boolean hideDurability = false;
public boolean hideItemmetaWithVisualEffects = false;
}
}
public AntiXray antiXray;
public class AntiXray extends ConfigurationPart {

View File

@@ -0,0 +1,26 @@
package io.papermc.paper.configuration.serializer;
import java.lang.reflect.Type;
import java.util.function.Predicate;
import net.minecraft.resources.ResourceLocation;
import org.spongepowered.configurate.serialize.ScalarSerializer;
import org.spongepowered.configurate.serialize.SerializationException;
public class ResourceLocationSerializer extends ScalarSerializer<ResourceLocation> {
public static final ScalarSerializer<ResourceLocation> INSTANCE = new ResourceLocationSerializer();
private ResourceLocationSerializer() {
super(ResourceLocation.class);
}
@Override
public ResourceLocation deserialize(final Type type, final Object obj) throws SerializationException {
return ResourceLocation.read(obj.toString()).getOrThrow(s -> new SerializationException(ResourceLocation.class, s));
}
@Override
protected Object serialize(final ResourceLocation item, final Predicate<Class<?>> typeSupported) {
return item.toString();
}
}