diff --git a/patches/server/Add-configurable-entity-despawn-distances.patch b/patches/server/Add-configurable-entity-despawn-distances.patch index 15311ad1e8..36c1d816cf 100644 --- a/patches/server/Add-configurable-entity-despawn-distances.patch +++ b/patches/server/Add-configurable-entity-despawn-distances.patch @@ -9,19 +9,42 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java @@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + Player entityhuman = this.level().getNearestPlayer(this, -1.0D); if (entityhuman != null) { - double d0 = entityhuman.distanceToSqr((Entity) this); +- double d0 = entityhuman.distanceToSqr((Entity) this); - int i = this.getType().getCategory().getDespawnDistance(); -+ int i = this.level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory()).hard(); // Paper - Configurable despawn distances - int j = i * i; - - if (d0 > (double) j && this.removeWhenFarAway(d0)) { +- int j = i * i; +- +- if (d0 > (double) j && this.removeWhenFarAway(d0)) { ++ // Paper start - Configurable despawn distances ++ // Read configration data and square it for later comparison ++ final MobCategory category = this.getType().getCategory(); ++ final io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DespawnRangePair despawnRangePair = this.level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory()); ++ final int hardHorizontalLimitSquared = (int) Math.pow(despawnRangePair.hard().horizontalLimit().or(category.getDespawnDistance()), 2); ++ final int softHorizontalLimitSquared = (int) Math.pow(despawnRangePair.soft().horizontalLimit().or(category.getNoDespawnDistance()), 2); ++ final int hardVerticalLimit = despawnRangePair.hard().verticalLimit().or(category.getDespawnDistance()); ++ final int softVerticalLimit = despawnRangePair.soft().verticalLimit().or(category.getNoDespawnDistance()); ++ // Compute vertical/horizontal distances ++ final double horizontalDistanceSquared = entityhuman.distanceToSqr(this.getX(), entityhuman.getY(), this.getZ()); ++ final double verticalDistance = Math.abs(entityhuman.getY() - this.getY()); ++ // Despawn if hard/soft limit is exceeded ++ if ((horizontalDistanceSquared > hardHorizontalLimitSquared || verticalDistance > hardVerticalLimit) && this.removeWhenFarAway(horizontalDistanceSquared)) { this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause } - +- - int k = this.getType().getCategory().getNoDespawnDistance(); -+ int k = this.level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory()).soft(); // Paper - Configurable despawn distances - int l = k * k; - - if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l && this.removeWhenFarAway(d0)) { +- int l = k * k; +- +- if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l && this.removeWhenFarAway(d0)) { +- this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause +- } else if (d0 < (double) l) { ++ if (horizontalDistanceSquared > softHorizontalLimitSquared || verticalDistance > softVerticalLimit) { ++ if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && this.removeWhenFarAway(horizontalDistanceSquared)) { ++ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause ++ } ++ } else { ++ // Paper end - Configurable despawn distances + this.noActionTime = 0; + } + } diff --git a/patches/server/Paper-config-files.patch b/patches/server/Paper-config-files.patch index 5aa0d8ff70..8947af73b5 100644 --- a/patches/server/Paper-config-files.patch +++ b/patches/server/Paper-config-files.patch @@ -885,6 +885,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import io.papermc.paper.configuration.transformation.world.versioned.V30_RenameFilterNbtFromSpawnEgg; +import io.papermc.paper.configuration.transformation.world.versioned.V31_SpawnLoadedRangeToGameRule; +import io.papermc.paper.configuration.type.BooleanOrDefault; ++import io.papermc.paper.configuration.type.DespawnRange; +import io.papermc.paper.configuration.type.Duration; +import io.papermc.paper.configuration.type.DurationOrDisabled; +import io.papermc.paper.configuration.type.EngineMode; @@ -1095,6 +1096,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .register(new TypeToken>() {}, new FastutilMapSerializer.SomethingToPrimitive>(Reference2IntOpenHashMap::new, Integer.TYPE)) + .register(new TypeToken>() {}, new FastutilMapSerializer.SomethingToPrimitive>(Reference2LongOpenHashMap::new, Long.TYPE)) + .register(new TypeToken>() {}, new TableSerializer()) ++ .register(DespawnRange.class, DespawnRange.SERIALIZER) + .register(StringRepresentableSerializer::isValidFor, new StringRepresentableSerializer()) + .register(IntOr.Default.SERIALIZER) + .register(IntOr.Disabled.SERIALIZER) @@ -1429,6 +1431,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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.DespawnRange; +import io.papermc.paper.configuration.type.Duration; +import io.papermc.paper.configuration.type.DurationOrDisabled; +import io.papermc.paper.configuration.type.EngineMode; @@ -1603,12 +1606,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @MergeMap + public Reference2IntMap spawnLimits = Util.make(new Reference2IntOpenHashMap<>(NaturalSpawner.SPAWNING_CATEGORIES.length), map -> Arrays.stream(NaturalSpawner.SPAWNING_CATEGORIES).forEach(mobCategory -> map.put(mobCategory, -1))); + @MergeMap -+ public Map despawnRanges = Arrays.stream(MobCategory.values()).collect(Collectors.toMap(Function.identity(), category -> new DespawnRange(category.getNoDespawnDistance(), category.getDespawnDistance()))); ++ public Map despawnRanges = Arrays.stream(MobCategory.values()).collect(Collectors.toMap(Function.identity(), category -> DespawnRangePair.createDefault())); + @MergeMap + public Reference2IntMap ticksPerSpawn = Util.make(new Reference2IntOpenHashMap<>(NaturalSpawner.SPAWNING_CATEGORIES.length), map -> Arrays.stream(NaturalSpawner.SPAWNING_CATEGORIES).forEach(mobCategory -> map.put(mobCategory, -1))); + + @ConfigSerializable -+ public record DespawnRange(@Required int soft, @Required int hard) { ++ public record DespawnRangePair(@Required DespawnRange hard, @Required DespawnRange soft) { ++ public static DespawnRangePair createDefault() { ++ return new DespawnRangePair( ++ new DespawnRange(IntOr.Default.USE_DEFAULT), ++ new DespawnRange(IntOr.Default.USE_DEFAULT) ++ ); ++ } + } + + public WaterAnimalSpawnHeight wateranimalSpawnHeight; @@ -2933,7 +2942,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return serializer.deserialize(type, node); + } catch (SerializationException ex) { + ex.initPath(node::path); -+ LOGGER.error("Could not deserialize {} {} into {} at {}", mapPart, node.raw(), type, path); ++ LOGGER.error("Could not deserialize {} {} into {} at {}: {}", mapPart, node.raw(), type, path, ex.rawMessage()); + } + return null; + } @@ -2994,7 +3003,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return true; + } catch (SerializationException ex) { + ex.initPath(node::path); -+ LOGGER.error("Could not serialize {} {} from {} at {}", mapPart, object, type, path); ++ LOGGER.error("Could not serialize {} {} from {} at {}: {}", mapPart, object, type, path, ex.rawMessage()); + } + return false; + } @@ -4190,6 +4199,70 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } +} +diff --git a/src/main/java/io/papermc/paper/configuration/type/DespawnRange.java b/src/main/java/io/papermc/paper/configuration/type/DespawnRange.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/configuration/type/DespawnRange.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.configuration.type; ++ ++import io.papermc.paper.configuration.type.number.IntOr; ++import java.lang.reflect.Type; ++import org.checkerframework.checker.nullness.qual.Nullable; ++import org.spongepowered.configurate.ConfigurationNode; ++import org.spongepowered.configurate.objectmapping.meta.Required; ++import org.spongepowered.configurate.serialize.SerializationException; ++import org.spongepowered.configurate.serialize.TypeSerializer; ++ ++public record DespawnRange( ++ @Required IntOr.Default horizontalLimit, ++ @Required IntOr.Default verticalLimit, ++ @Required boolean wasDefinedViaLongSyntax ++) { ++ ++ public DespawnRange(final IntOr.Default generalLimit) { ++ this(generalLimit, generalLimit, false); ++ } ++ ++ public static final TypeSerializer SERIALIZER = new Serializer(); ++ ++ static final class Serializer implements TypeSerializer { ++ ++ public static final String HORIZONTAL = "horizontal"; ++ public static final String VERTICAL = "vertical"; ++ ++ @Override ++ public DespawnRange deserialize(final Type type, final ConfigurationNode node) throws SerializationException { ++ if (node.hasChild(HORIZONTAL) && node.hasChild(VERTICAL)) { ++ return new DespawnRange( ++ node.node(HORIZONTAL).require(IntOr.Default.class), ++ node.node(VERTICAL).require(IntOr.Default.class), ++ true ++ ); ++ } else if (node.hasChild(HORIZONTAL) || node.hasChild(VERTICAL)) { ++ throw new SerializationException(node, DespawnRange.class, "Expected both horizontal and vertical despawn ranges to be defined"); ++ } else { ++ return new DespawnRange(node.require(IntOr.Default.class)); ++ } ++ } ++ ++ @Override ++ public void serialize(final Type type, final @Nullable DespawnRange despawnRange, final ConfigurationNode node) throws SerializationException { ++ if (despawnRange == null) { ++ node.raw(null); ++ return; ++ } ++ ++ if (despawnRange.wasDefinedViaLongSyntax()) { ++ node.node(HORIZONTAL).set(despawnRange.horizontalLimit()); ++ node.node(VERTICAL).set(despawnRange.verticalLimit()); ++ } else { ++ node.set(despawnRange.verticalLimit()); ++ } ++ } ++ } ++} diff --git a/src/main/java/io/papermc/paper/configuration/type/Duration.java b/src/main/java/io/papermc/paper/configuration/type/Duration.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 diff --git a/patches/server/Player-affects-spawning-API.patch b/patches/server/Player-affects-spawning-API.patch index 7f70948768..aeb0c6b613 100644 --- a/patches/server/Player-affects-spawning-API.patch +++ b/patches/server/Player-affects-spawning-API.patch @@ -32,7 +32,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + Player entityhuman = this.level().findNearbyPlayer(this, -1.0D, EntitySelector.PLAYER_AFFECTS_SPAWNING); // Paper - Affects Spawning API if (entityhuman != null) { - double d0 = entityhuman.distanceToSqr((Entity) this); + // Paper start - Configurable despawn distances diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java