Rework filtering spawn egg and tile entity nbt config (#6613)

This commit is contained in:
Jake Potrebic 2022-12-27 18:59:15 -08:00 committed by GitHub
parent fa42c68b73
commit 90750a6591
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 289 additions and 176 deletions

View File

@ -934,10 +934,10 @@ index 0000000000000000000000000000000000000000..69add4a7f1147015806bc9b63a8340d1
+}
diff --git a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b6d68350f608bb64a701d0e390283d50f12094e
index 0000000000000000000000000000000000000000..9fde9ccb5d069ddce8dd837ef1bc68b93ce66434
--- /dev/null
+++ b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java
@@ -0,0 +1,435 @@
@@ -0,0 +1,439 @@
+package io.papermc.paper.configuration;
+
+import com.google.common.base.Suppliers;
@ -947,10 +947,11 @@ index 0000000000000000000000000000000000000000..0b6d68350f608bb64a701d0e390283d5
+import io.papermc.paper.configuration.legacy.RequiresSpigotInitialization;
+import io.papermc.paper.configuration.serializer.ComponentSerializer;
+import io.papermc.paper.configuration.serializer.EnumValueSerializer;
+import io.papermc.paper.configuration.serializer.FastutilMapSerializer;
+import io.papermc.paper.configuration.serializer.collections.FastutilMapSerializer;
+import io.papermc.paper.configuration.serializer.NbtPathSerializer;
+import io.papermc.paper.configuration.serializer.PacketClassSerializer;
+import io.papermc.paper.configuration.serializer.StringRepresentableSerializer;
+import io.papermc.paper.configuration.serializer.TableSerializer;
+import io.papermc.paper.configuration.serializer.collections.TableSerializer;
+import io.papermc.paper.configuration.serializer.collections.MapSerializer;
+import io.papermc.paper.configuration.serializer.registry.RegistryHolderSerializer;
+import io.papermc.paper.configuration.serializer.registry.RegistryValueSerializer;
@ -958,7 +959,8 @@ index 0000000000000000000000000000000000000000..0b6d68350f608bb64a701d0e390283d5
+import io.papermc.paper.configuration.transformation.global.LegacyPaperConfig;
+import io.papermc.paper.configuration.transformation.world.FeatureSeedsGeneration;
+import io.papermc.paper.configuration.transformation.world.LegacyPaperWorldConfig;
+import io.papermc.paper.configuration.transformation.world.ZeroWorldHeight;
+import io.papermc.paper.configuration.transformation.world.versioned.V29_ZeroWorldHeight;
+import io.papermc.paper.configuration.transformation.world.versioned.V30_RenameFilterNbtFromSpawnEgg;
+import io.papermc.paper.configuration.type.BooleanOrDefault;
+import io.papermc.paper.configuration.type.DoubleOrDefault;
+import io.papermc.paper.configuration.type.Duration;
@ -1150,6 +1152,7 @@ index 0000000000000000000000000000000000000000..0b6d68350f608bb64a701d0e390283d5
+ .register(BooleanOrDefault.SERIALIZER)
+ .register(Duration.SERIALIZER)
+ .register(EngineMode.SERIALIZER)
+ .register(NbtPathSerializer.SERIALIZER)
+ .register(FallbackValueSerializer.create(contextMap.require(SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get(), MinecraftServer::getServer))
+ .register(new RegistryValueSerializer<>(new TypeToken<EntityType<?>>() {}, Registries.ENTITY_TYPE, true))
+ .register(new RegistryValueSerializer<>(Item.class, Registries.ITEM, true))
@ -1174,7 +1177,8 @@ index 0000000000000000000000000000000000000000..0b6d68350f608bb64a701d0e390283d5
+ builder.build().apply(node);
+
+ final ConfigurationTransformation.VersionedBuilder versionedBuilder = Transformations.versionedBuilder();
+ ZeroWorldHeight.apply(versionedBuilder);
+ V29_ZeroWorldHeight.apply(versionedBuilder);
+ V30_RenameFilterNbtFromSpawnEgg.apply(versionedBuilder);
+ // ADD FUTURE VERSIONED TRANSFORMS TO versionedBuilder HERE
+ versionedBuilder.build().apply(node);
+ }
@ -1447,7 +1451,7 @@ new file mode 100644
index 0000000000000000000000000000000000000000..2e9590c73d867c3ebb42f695df4c796a0f477452
--- /dev/null
+++ b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
@@ -0,0 +1,472 @@
@@ -0,0 +1,475 @@
+package io.papermc.paper.configuration;
+
+import com.google.common.collect.HashBasedTable;
@ -1458,6 +1462,7 @@ index 0000000000000000000000000000000000000000..2e9590c73d867c3ebb42f695df4c796a
+import io.papermc.paper.configuration.legacy.MaxEntityCollisionsInitializer;
+import io.papermc.paper.configuration.legacy.RequiresSpigotInitialization;
+import io.papermc.paper.configuration.legacy.SpawnLoadedRangeInitializer;
+import io.papermc.paper.configuration.serializer.NbtPathSerializer;
+import io.papermc.paper.configuration.transformation.world.FeatureSeedsGeneration;
+import io.papermc.paper.configuration.type.BooleanOrDefault;
+import io.papermc.paper.configuration.type.DoubleOrDefault;
@ -1476,6 +1481,7 @@ index 0000000000000000000000000000000000000000..2e9590c73d867c3ebb42f695df4c796a
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import net.minecraft.Util;
+import net.minecraft.commands.arguments.NbtPathArgument;
+import net.minecraft.core.Holder;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.resources.ResourceLocation;
@ -1497,7 +1503,7 @@ index 0000000000000000000000000000000000000000..2e9590c73d867c3ebb42f695df4c796a
+@SuppressWarnings({"FieldCanBeLocal", "FieldMayBeFinal", "NotNullFieldNotInitialized", "InnerClassMayBeStatic"})
+public class WorldConfiguration extends ConfigurationPart {
+ private static final Logger LOGGER = LogUtils.getLogger();
+ static final int CURRENT_VERSION = 29; // (when you change the version, change the comment, so it conflicts on rebases): zero height fixes
+ static final int CURRENT_VERSION = 30; // (when you change the version, change the comment, so it conflicts on rebases): rename filter bad nbt from spawn eggs
+
+ private transient final SpigotWorldConfig spigotConfig;
+ private transient final ResourceLocation worldKey;
@ -1573,7 +1579,8 @@ index 0000000000000000000000000000000000000000..2e9590c73d867c3ebb42f695df4c796a
+ public class Spawning extends ConfigurationPart {
+ public ArrowDespawnRate nonPlayerArrowDespawnRate = ArrowDespawnRate.def(WorldConfiguration.this.spigotConfig);
+ public ArrowDespawnRate creativeArrowDespawnRate = ArrowDespawnRate.def(WorldConfiguration.this.spigotConfig);
+ public boolean filterNbtDataFromSpawnEggsAndRelated = true;
+ public boolean filterBadTileEntityNbtFromFallingBlocks = true;
+ public List<NbtPathArgument.NbtPath> filteredEntityTagNbtPaths = NbtPathSerializer.fromString(List.of("Pos", "Motion", "SleepingX", "SleepingY", "SleepingZ"));
+ public boolean disableMobSpawnerSpawnEggTransformation = false;
+ public boolean perPlayerMobSpawns = true;
+ public boolean scanForLegacyEnderDragon = true;
@ -2300,78 +2307,61 @@ index 0000000000000000000000000000000000000000..2afb9268447792e3cdb46172b2050dbc
+ return item.name();
+ }
+}
diff --git a/src/main/java/io/papermc/paper/configuration/serializer/FastutilMapSerializer.java b/src/main/java/io/papermc/paper/configuration/serializer/FastutilMapSerializer.java
diff --git a/src/main/java/io/papermc/paper/configuration/serializer/NbtPathSerializer.java b/src/main/java/io/papermc/paper/configuration/serializer/NbtPathSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2f362883d1825084c277608c791f82165828ebe
index 0000000000000000000000000000000000000000..b44b2dc28f619594e302417848e95c0087acbcea
--- /dev/null
+++ b/src/main/java/io/papermc/paper/configuration/serializer/FastutilMapSerializer.java
@@ -0,0 +1,69 @@
+++ b/src/main/java/io/papermc/paper/configuration/serializer/NbtPathSerializer.java
@@ -0,0 +1,52 @@
+package io.papermc.paper.configuration.serializer;
+
+import io.leangen.geantyref.GenericTypeReflector;
+import io.leangen.geantyref.TypeFactory;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.spongepowered.configurate.ConfigurationNode;
+import org.spongepowered.configurate.serialize.SerializationException;
+import org.spongepowered.configurate.serialize.TypeSerializer;
+
+import java.lang.reflect.ParameterizedType;
+import com.destroystokyo.paper.util.SneakyThrow;
+import com.mojang.brigadier.StringReader;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+import net.minecraft.commands.arguments.NbtPathArgument;
+import org.spongepowered.configurate.serialize.ScalarSerializer;
+import org.spongepowered.configurate.serialize.SerializationException;
+
+@SuppressWarnings("rawtypes")
+public abstract class FastutilMapSerializer<M extends Map<?, ?>> implements TypeSerializer<M> {
+ private final Function<Map, ? extends M> factory;
+public class NbtPathSerializer extends ScalarSerializer<NbtPathArgument.NbtPath> {
+
+ protected FastutilMapSerializer(final Function<Map, ? extends M> factory) {
+ this.factory = factory;
+ public static final NbtPathSerializer SERIALIZER = new NbtPathSerializer();
+ private static final NbtPathArgument DUMMY_ARGUMENT = new NbtPathArgument();
+
+ private NbtPathSerializer() {
+ super(NbtPathArgument.NbtPath.class);
+ }
+
+ @Override
+ public M deserialize(final Type type, final ConfigurationNode node) throws SerializationException {
+ @Nullable final Map map = (Map) node.get(this.createBaseMapType((ParameterizedType) type));
+ return this.factory.apply(map == null ? Collections.emptyMap() : map);
+ public NbtPathArgument.NbtPath deserialize(final Type type, final Object obj) throws SerializationException {
+ return fromString(obj.toString());
+ }
+
+ @Override
+ public void serialize(final Type type, @Nullable final M obj, final ConfigurationNode node) throws SerializationException {
+ if (obj == null || obj.isEmpty()) {
+ node.raw(null);
+ } else {
+ final Type baseMapType = this.createBaseMapType((ParameterizedType) type);
+ node.set(baseMapType, obj);
+ }
+ protected Object serialize(final NbtPathArgument.NbtPath item, final Predicate<Class<?>> typeSupported) {
+ return item.toString();
+ }
+
+ protected abstract Type createBaseMapType(final ParameterizedType type);
+
+ public static final class SomethingToPrimitive<M extends Map<?, ?>> extends FastutilMapSerializer<M> {
+ private final Type primitiveType;
+
+ public SomethingToPrimitive(final Function<Map, ? extends M> factory, final Type primitiveType) {
+ super(factory);
+ this.primitiveType = primitiveType;
+ public static List<NbtPathArgument.NbtPath> fromString(final List<String> tags) {
+ List<NbtPathArgument.NbtPath> paths = new ArrayList<>();
+ try {
+ for (final String tag : tags) {
+ paths.add(fromString(tag));
+ }
+ } catch (SerializationException ex) {
+ SneakyThrow.sneaky(ex);
+ }
+ return List.copyOf(paths);
+ }
+
+ @Override
+ protected Type createBaseMapType(final ParameterizedType type) {
+ return TypeFactory.parameterizedClass(Map.class, type.getActualTypeArguments()[0], GenericTypeReflector.box(this.primitiveType));
+ }
+ }
+
+ public static final class PrimitiveToSomething<M extends Map<?, ?>> extends FastutilMapSerializer<M> {
+ private final Type primitiveType;
+
+ public PrimitiveToSomething(final Function<Map, ? extends M> factory, final Type primitiveType) {
+ super(factory);
+ this.primitiveType = primitiveType;
+ }
+
+ @Override
+ protected Type createBaseMapType(final ParameterizedType type) {
+ return TypeFactory.parameterizedClass(Map.class, GenericTypeReflector.box(this.primitiveType), type.getActualTypeArguments()[0]);
+ private static NbtPathArgument.NbtPath fromString(final String tag) throws SerializationException {
+ try {
+ return DUMMY_ARGUMENT.parse(new StringReader(tag));
+ } catch (CommandSyntaxException e) {
+ throw new SerializationException(NbtPathArgument.NbtPath.class, e);
+ }
+ }
+}
@ -2525,99 +2515,79 @@ index 0000000000000000000000000000000000000000..7fc0905fc6b8f5df762b4cea573f935d
+ return item.getSerializedName();
+ }
+}
diff --git a/src/main/java/io/papermc/paper/configuration/serializer/TableSerializer.java b/src/main/java/io/papermc/paper/configuration/serializer/TableSerializer.java
diff --git a/src/main/java/io/papermc/paper/configuration/serializer/collections/FastutilMapSerializer.java b/src/main/java/io/papermc/paper/configuration/serializer/collections/FastutilMapSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..346422c5eb791961061cc73b9b827d63bbd67daf
index 0000000000000000000000000000000000000000..4af710e144b70933d750c22edfe484c18e4a3540
--- /dev/null
+++ b/src/main/java/io/papermc/paper/configuration/serializer/TableSerializer.java
@@ -0,0 +1,89 @@
+package io.papermc.paper.configuration.serializer;
+++ b/src/main/java/io/papermc/paper/configuration/serializer/collections/FastutilMapSerializer.java
@@ -0,0 +1,69 @@
+package io.papermc.paper.configuration.serializer.collections;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.ImmutableTable;
+import com.google.common.collect.Table;
+import io.leangen.geantyref.GenericTypeReflector;
+import io.leangen.geantyref.TypeFactory;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.spongepowered.configurate.BasicConfigurationNode;
+import org.spongepowered.configurate.ConfigurationNode;
+import org.spongepowered.configurate.ConfigurationOptions;
+import org.spongepowered.configurate.serialize.SerializationException;
+import org.spongepowered.configurate.serialize.TypeSerializer;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+
+public class TableSerializer implements TypeSerializer<Table<?, ?, ?>> {
+ private static final int ROW_TYPE_ARGUMENT_INDEX = 0;
+ private static final int COLUMN_TYPE_ARGUMENT_INDEX = 1;
+ private static final int VALUE_TYPE_ARGUMENT_INDEX = 2;
+@SuppressWarnings("rawtypes")
+public abstract class FastutilMapSerializer<M extends Map<?, ?>> implements TypeSerializer<M> {
+ private final Function<Map, ? extends M> factory;
+
+ @Override
+ public Table<?, ?, ?> deserialize(final Type type, final ConfigurationNode node) throws SerializationException {
+ final Table<?, ?, ?> table = HashBasedTable.create();
+ if (!node.empty() && node.isMap()) {
+ this.deserialize0(table, (ParameterizedType) type, node);
+ }
+ return table;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <R, C, V> void deserialize0(final Table<R, C, V> table, final ParameterizedType type, final ConfigurationNode node) throws SerializationException {
+ final Type rowType = type.getActualTypeArguments()[ROW_TYPE_ARGUMENT_INDEX];
+ final Type columnType = type.getActualTypeArguments()[COLUMN_TYPE_ARGUMENT_INDEX];
+ final Type valueType = type.getActualTypeArguments()[VALUE_TYPE_ARGUMENT_INDEX];
+
+ final @Nullable TypeSerializer<R> rowKeySerializer = (TypeSerializer<R>) node.options().serializers().get(rowType);
+ if (rowKeySerializer == null) {
+ throw new SerializationException("Could not find serializer for table row type " + rowType);
+ }
+
+ final Type mapType = TypeFactory.parameterizedClass(Map.class, columnType, valueType);
+ final @Nullable TypeSerializer<Map<C, V>> columnValueSerializer = (TypeSerializer<Map<C, V>>) node.options().serializers().get(mapType);
+ if (columnValueSerializer == null) {
+ throw new SerializationException("Could not find serializer for table column-value map " + type);
+ }
+
+ final BasicConfigurationNode rowKeyNode = BasicConfigurationNode.root(node.options());
+
+ for (final Object key : node.childrenMap().keySet()) {
+ final R rowKey = rowKeySerializer.deserialize(rowType, rowKeyNode.set(key));
+ final Map<C, V> map = columnValueSerializer.deserialize(mapType, node.node(rowKeyNode.raw()));
+ map.forEach((column, value) -> table.put(rowKey, column, value));
+ }
+ protected FastutilMapSerializer(final Function<Map, ? extends M> factory) {
+ this.factory = factory;
+ }
+
+ @Override
+ public void serialize(final Type type, @Nullable final Table<?, ?, ?> table, final ConfigurationNode node) throws SerializationException {
+ if (table != null) {
+ this.serialize0(table, (ParameterizedType) type, node);
+ }
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private <R, C, V> void serialize0(final Table<R, C, V> table, final ParameterizedType type, final ConfigurationNode node) throws SerializationException {
+ final Type rowType = type.getActualTypeArguments()[ROW_TYPE_ARGUMENT_INDEX];
+ final Type columnType = type.getActualTypeArguments()[COLUMN_TYPE_ARGUMENT_INDEX];
+ final Type valueType = type.getActualTypeArguments()[VALUE_TYPE_ARGUMENT_INDEX];
+
+ final @Nullable TypeSerializer rowKeySerializer = node.options().serializers().get(rowType);
+ if (rowKeySerializer == null) {
+ throw new SerializationException("Could not find a serializer for table row type " + rowType);
+ }
+
+ final BasicConfigurationNode rowKeyNode = BasicConfigurationNode.root(node.options());
+ for (final R key : table.rowKeySet()) {
+ rowKeySerializer.serialize(rowType, key, rowKeyNode.set(key));
+ final Object keyObj = Objects.requireNonNull(rowKeyNode.raw());
+ node.node(keyObj).set(TypeFactory.parameterizedClass(Map.class, columnType, valueType), table.row(key));
+ }
+ public M deserialize(final Type type, final ConfigurationNode node) throws SerializationException {
+ @Nullable final Map map = (Map) node.get(this.createBaseMapType((ParameterizedType) type));
+ return this.factory.apply(map == null ? Collections.emptyMap() : map);
+ }
+
+ @Override
+ public @Nullable Table<?, ?, ?> emptyValue(Type specificType, ConfigurationOptions options) {
+ return ImmutableTable.of();
+ public void serialize(final Type type, @Nullable final M obj, final ConfigurationNode node) throws SerializationException {
+ if (obj == null || obj.isEmpty()) {
+ node.raw(null);
+ } else {
+ final Type baseMapType = this.createBaseMapType((ParameterizedType) type);
+ node.set(baseMapType, obj);
+ }
+ }
+
+ protected abstract Type createBaseMapType(final ParameterizedType type);
+
+ public static final class SomethingToPrimitive<M extends Map<?, ?>> extends FastutilMapSerializer<M> {
+ private final Type primitiveType;
+
+ public SomethingToPrimitive(final Function<Map, ? extends M> factory, final Type primitiveType) {
+ super(factory);
+ this.primitiveType = primitiveType;
+ }
+
+ @Override
+ protected Type createBaseMapType(final ParameterizedType type) {
+ return TypeFactory.parameterizedClass(Map.class, type.getActualTypeArguments()[0], GenericTypeReflector.box(this.primitiveType));
+ }
+ }
+
+ public static final class PrimitiveToSomething<M extends Map<?, ?>> extends FastutilMapSerializer<M> {
+ private final Type primitiveType;
+
+ public PrimitiveToSomething(final Function<Map, ? extends M> factory, final Type primitiveType) {
+ super(factory);
+ this.primitiveType = primitiveType;
+ }
+
+ @Override
+ protected Type createBaseMapType(final ParameterizedType type) {
+ return TypeFactory.parameterizedClass(Map.class, GenericTypeReflector.box(this.primitiveType), type.getActualTypeArguments()[0]);
+ }
+ }
+}
diff --git a/src/main/java/io/papermc/paper/configuration/serializer/collections/MapSerializer.java b/src/main/java/io/papermc/paper/configuration/serializer/collections/MapSerializer.java
@ -2788,9 +2758,104 @@ index 0000000000000000000000000000000000000000..f44d4cb05eab25d79a8ac09b9da98163
+ public interface WriteBack { // marker interface
+ }
+}
diff --git a/src/main/java/io/papermc/paper/configuration/serializer/collections/TableSerializer.java b/src/main/java/io/papermc/paper/configuration/serializer/collections/TableSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..36ca88b677e1b55b41c52750948d5b6de7ecd007
--- /dev/null
+++ b/src/main/java/io/papermc/paper/configuration/serializer/collections/TableSerializer.java
@@ -0,0 +1,89 @@
+package io.papermc.paper.configuration.serializer.collections;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.ImmutableTable;
+import com.google.common.collect.Table;
+import io.leangen.geantyref.TypeFactory;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.spongepowered.configurate.BasicConfigurationNode;
+import org.spongepowered.configurate.ConfigurationNode;
+import org.spongepowered.configurate.ConfigurationOptions;
+import org.spongepowered.configurate.serialize.SerializationException;
+import org.spongepowered.configurate.serialize.TypeSerializer;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.Objects;
+
+public class TableSerializer implements TypeSerializer<Table<?, ?, ?>> {
+ private static final int ROW_TYPE_ARGUMENT_INDEX = 0;
+ private static final int COLUMN_TYPE_ARGUMENT_INDEX = 1;
+ private static final int VALUE_TYPE_ARGUMENT_INDEX = 2;
+
+ @Override
+ public Table<?, ?, ?> deserialize(final Type type, final ConfigurationNode node) throws SerializationException {
+ final Table<?, ?, ?> table = HashBasedTable.create();
+ if (!node.empty() && node.isMap()) {
+ this.deserialize0(table, (ParameterizedType) type, node);
+ }
+ return table;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <R, C, V> void deserialize0(final Table<R, C, V> table, final ParameterizedType type, final ConfigurationNode node) throws SerializationException {
+ final Type rowType = type.getActualTypeArguments()[ROW_TYPE_ARGUMENT_INDEX];
+ final Type columnType = type.getActualTypeArguments()[COLUMN_TYPE_ARGUMENT_INDEX];
+ final Type valueType = type.getActualTypeArguments()[VALUE_TYPE_ARGUMENT_INDEX];
+
+ final @Nullable TypeSerializer<R> rowKeySerializer = (TypeSerializer<R>) node.options().serializers().get(rowType);
+ if (rowKeySerializer == null) {
+ throw new SerializationException("Could not find serializer for table row type " + rowType);
+ }
+
+ final Type mapType = TypeFactory.parameterizedClass(Map.class, columnType, valueType);
+ final @Nullable TypeSerializer<Map<C, V>> columnValueSerializer = (TypeSerializer<Map<C, V>>) node.options().serializers().get(mapType);
+ if (columnValueSerializer == null) {
+ throw new SerializationException("Could not find serializer for table column-value map " + type);
+ }
+
+ final BasicConfigurationNode rowKeyNode = BasicConfigurationNode.root(node.options());
+
+ for (final Object key : node.childrenMap().keySet()) {
+ final R rowKey = rowKeySerializer.deserialize(rowType, rowKeyNode.set(key));
+ final Map<C, V> map = columnValueSerializer.deserialize(mapType, node.node(rowKeyNode.raw()));
+ map.forEach((column, value) -> table.put(rowKey, column, value));
+ }
+ }
+
+ @Override
+ public void serialize(final Type type, @Nullable final Table<?, ?, ?> table, final ConfigurationNode node) throws SerializationException {
+ if (table != null) {
+ this.serialize0(table, (ParameterizedType) type, node);
+ }
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private <R, C, V> void serialize0(final Table<R, C, V> table, final ParameterizedType type, final ConfigurationNode node) throws SerializationException {
+ final Type rowType = type.getActualTypeArguments()[ROW_TYPE_ARGUMENT_INDEX];
+ final Type columnType = type.getActualTypeArguments()[COLUMN_TYPE_ARGUMENT_INDEX];
+ final Type valueType = type.getActualTypeArguments()[VALUE_TYPE_ARGUMENT_INDEX];
+
+ final @Nullable TypeSerializer rowKeySerializer = node.options().serializers().get(rowType);
+ if (rowKeySerializer == null) {
+ throw new SerializationException("Could not find a serializer for table row type " + rowType);
+ }
+
+ final BasicConfigurationNode rowKeyNode = BasicConfigurationNode.root(node.options());
+ for (final R key : table.rowKeySet()) {
+ rowKeySerializer.serialize(rowType, key, rowKeyNode.set(key));
+ final Object keyObj = Objects.requireNonNull(rowKeyNode.raw());
+ node.node(keyObj).set(TypeFactory.parameterizedClass(Map.class, columnType, valueType), table.row(key));
+ }
+ }
+
+ @Override
+ public @Nullable Table<?, ?, ?> emptyValue(Type specificType, ConfigurationOptions options) {
+ return ImmutableTable.of();
+ }
+}
diff --git a/src/main/java/io/papermc/paper/configuration/serializer/registry/RegistryEntrySerializer.java b/src/main/java/io/papermc/paper/configuration/serializer/registry/RegistryEntrySerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e4e0f1788cf67312cb52bd572784c2f27db71b6
index 0000000000000000000000000000000000000000..18da824fd003c110083a6c08d5db75578171433c
--- /dev/null
+++ b/src/main/java/io/papermc/paper/configuration/serializer/registry/RegistryEntrySerializer.java
@@ -0,0 +1,62 @@
@ -2826,7 +2891,7 @@ index 0000000000000000000000000000000000000000..0e4e0f1788cf67312cb52bd572784c2f
+ }
+
+ protected final Registry<R> registry() {
+ return MinecraftServer.getServer().registryAccess().registryOrThrow(this.registryKey);
+ return MinecraftServer.getServer().registryAccess().registryOrThrow(this.registryKey); // TODO don't depend on MinecraftServer#getServer
+ }
+
+ protected abstract T convertFromResourceKey(ResourceKey<R> key) throws SerializationException;
@ -3616,13 +3681,13 @@ index 0000000000000000000000000000000000000000..edaa6ef28c1f9a223943969870889700
+ moveFromRootAndRename(builder, path("game-mechanics", oldKey), newKey, parents);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/configuration/transformation/world/ZeroWorldHeight.java b/src/main/java/io/papermc/paper/configuration/transformation/world/ZeroWorldHeight.java
diff --git a/src/main/java/io/papermc/paper/configuration/transformation/world/versioned/V29_ZeroWorldHeight.java b/src/main/java/io/papermc/paper/configuration/transformation/world/versioned/V29_ZeroWorldHeight.java
new file mode 100644
index 0000000000000000000000000000000000000000..dcb1f3722de215800ddb0285538bc188d02af054
index 0000000000000000000000000000000000000000..f67e82fbeb97d68d5733bbd1c246183f5e91ab0a
--- /dev/null
+++ b/src/main/java/io/papermc/paper/configuration/transformation/world/ZeroWorldHeight.java
@@ -0,0 +1,46 @@
+package io.papermc.paper.configuration.transformation.world;
+++ b/src/main/java/io/papermc/paper/configuration/transformation/world/versioned/V29_ZeroWorldHeight.java
@@ -0,0 +1,49 @@
+package io.papermc.paper.configuration.transformation.world.versioned;
+
+import io.papermc.paper.configuration.type.IntOr;
+import org.checkerframework.checker.nullness.qual.Nullable;
@ -3638,7 +3703,7 @@ index 0000000000000000000000000000000000000000..dcb1f3722de215800ddb0285538bc188
+ * Several configurations that set a y-level used '0' as the "disabled" value.
+ * Since 0 is now a valid value, they need to be updated.
+ */
+public class ZeroWorldHeight implements TransformAction {
+public final class V29_ZeroWorldHeight implements TransformAction {
+
+ private static final int VERSION = 29;
+
@ -3649,7 +3714,10 @@ index 0000000000000000000000000000000000000000..dcb1f3722de215800ddb0285538bc188
+ private static final String ENVIRONMENT_KEY = "environment";
+ private static final String NETHER_CEILING_VOID_DAMAGE_HEIGHT_KEY = "nether-ceiling-void-damage-height";
+
+ private static final ZeroWorldHeight INSTANCE = new ZeroWorldHeight();
+ private static final V29_ZeroWorldHeight INSTANCE = new V29_ZeroWorldHeight();
+
+ private V29_ZeroWorldHeight() {
+ }
+
+ public static void apply(ConfigurationTransformation.VersionedBuilder builder) {
+ final ConfigurationTransformation transformation = ConfigurationTransformation.builder()
@ -3668,6 +3736,37 @@ index 0000000000000000000000000000000000000000..dcb1f3722de215800ddb0285538bc188
+ return null;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/configuration/transformation/world/versioned/V30_RenameFilterNbtFromSpawnEgg.java b/src/main/java/io/papermc/paper/configuration/transformation/world/versioned/V30_RenameFilterNbtFromSpawnEgg.java
new file mode 100644
index 0000000000000000000000000000000000000000..d08b65234192d5b639cead675114f64bf1f409c4
--- /dev/null
+++ b/src/main/java/io/papermc/paper/configuration/transformation/world/versioned/V30_RenameFilterNbtFromSpawnEgg.java
@@ -0,0 +1,25 @@
+package io.papermc.paper.configuration.transformation.world.versioned;
+
+import org.spongepowered.configurate.NodePath;
+import org.spongepowered.configurate.transformation.ConfigurationTransformation;
+
+import static org.spongepowered.configurate.NodePath.path;
+import static org.spongepowered.configurate.transformation.TransformAction.rename;
+
+/**
+ * The {@code filter-nbt-data-from-spawn-eggs-and-related} setting had nothing
+ * to do with spawn eggs, and was just filtering bad falling blocks.
+ */
+public final class V30_RenameFilterNbtFromSpawnEgg {
+
+ private static final int VERSION = 30;
+ private static final NodePath OLD_PATH = path("entities", "spawning", "filter-nbt-data-from-spawn-eggs-and-related");
+ private static final String NEW_PATH = "filter-bad-tile-entity-nbt-from-falling-blocks";
+
+ private V30_RenameFilterNbtFromSpawnEgg() {
+ }
+
+ public static void apply(ConfigurationTransformation.VersionedBuilder builder) {
+ builder.addVersion(VERSION, ConfigurationTransformation.builder().addAction(OLD_PATH, rename(NEW_PATH)).build());
+ }
+}
diff --git a/src/main/java/io/papermc/paper/configuration/type/BooleanOrDefault.java b/src/main/java/io/papermc/paper/configuration/type/BooleanOrDefault.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e422b74a377fa3edaf82dd960e7449c998c2912

View File

@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Sat, 12 Nov 2016 23:25:22 -0600
Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
index 561b8d6fcf4d511fb026bcc2c02054e56589d0b7..e7404619877099aa2223da349e15090d2c9be1d0 100644
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -318,6 +318,18 @@ public class FallingBlockEntity extends Entity {
@Override
protected void readAdditionalSaveData(CompoundTag nbt) {
this.blockState = NbtUtils.readBlockState(this.level.holderLookup(Registries.BLOCK), nbt.getCompound("BlockState"));
+ // Paper start - Block FallingBlocks with Command Blocks
+ final Block b = this.blockState.getBlock();
+ if (this.level.paperConfig().entities.spawning.filterNbtDataFromSpawnEggsAndRelated
+ && (b == Blocks.COMMAND_BLOCK
+ || b == Blocks.REPEATING_COMMAND_BLOCK
+ || b == Blocks.CHAIN_COMMAND_BLOCK
+ || b == Blocks.JIGSAW
+ || b == Blocks.STRUCTURE_BLOCK
+ || b instanceof net.minecraft.world.level.block.GameMasterBlock)) {
+ this.blockState = Blocks.STONE.defaultBlockState();
+ }
+ // Paper end
this.time = nbt.getInt("Time");
if (nbt.contains("HurtEntities", 99)) {
this.hurtEntities = nbt.getBoolean("HurtEntities");

View File

@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <zach.brown@destroystokyo.com>
Date: Sat, 12 Nov 2016 23:25:22 -0600
Subject: [PATCH] Filter bad tile entity nbt data from falling blocks
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
index 561b8d6fcf4d511fb026bcc2c02054e56589d0b7..97b2d12713d2245f1621d3ade5b5655b5897cbf4 100644
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -331,7 +331,7 @@ public class FallingBlockEntity extends Entity {
this.dropItem = nbt.getBoolean("DropItem");
}
- if (nbt.contains("TileEntityData", 10)) {
+ if (nbt.contains("TileEntityData", 10) && !(this.level.paperConfig().entities.spawning.filterBadTileEntityNbtFromFallingBlocks && this.blockState.getBlock() instanceof net.minecraft.world.level.block.GameMasterBlock)) {
this.blockData = nbt.getCompound("TileEntityData");
}

View File

@ -5,7 +5,7 @@ Subject: [PATCH] FallingBlock auto expire setting
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
index 23bd2a9af71b63bf463c7091ac261b033e9ce9af..72f1866226269396ba0f0c1be269e237925d9322 100644
index 06f6fe4d1be4b14c45d2576561201c9386988dc1..eacb8a407fe99af2c13f23c12b5544696bda8890 100644
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -63,6 +63,7 @@ public class FallingBlockEntity extends Entity {
@ -33,7 +33,7 @@ index 23bd2a9af71b63bf463c7091ac261b033e9ce9af..72f1866226269396ba0f0c1be269e237
}
@@ -369,6 +371,10 @@ public class FallingBlockEntity extends Entity {
@@ -357,6 +359,10 @@ public class FallingBlockEntity extends Entity {
int srcZ = nbt.getInt("SourceLoc_z");
this.setOrigin(new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ));
}

View File

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 15 Sep 2021 14:52:42 -0700
Subject: [PATCH] config for disabling entity tag tags
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
index e5cd4b7609243669c9d84ff8a4988c209e6101aa..4589f7db68f7a72065c85c0a50216c6d02658f1e 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
@@ -484,6 +484,13 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
if (world.isClientSide || !entity.onlyOpCanSetNbt() || player != null && minecraftserver.getPlayerList().isOp(player.getGameProfile())) {
CompoundTag nbttagcompound1 = entity.saveWithoutId(new CompoundTag());
UUID uuid = entity.getUUID();
+ // Paper start - filter out protected tags
+ if (player == null || !player.getBukkitEntity().hasPermission("minecraft.nbt.place")) {
+ for (net.minecraft.commands.arguments.NbtPathArgument.NbtPath tag : world.paperConfig().entities.spawning.filteredEntityTagNbtPaths) {
+ tag.remove(itemNbt.getCompound("EntityTag"));
+ }
+ }
+ // Paper end
nbttagcompound1.merge(itemNbt.getCompound("EntityTag"));
entity.setUUID(uuid);