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:
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user