From b5d3f80d85b2dfeb1e54b3e8807f8da45e858570 Mon Sep 17 00:00:00 2001 From: Omer Uddin Date: Tue, 15 Jun 2021 01:44:37 -0400 Subject: [PATCH] port some patches (#5837) --- patches/api/PreSpawnerSpawnEvent.patch | 47 ++++++++++ ...e-Biome-Mob-Lookups-for-Mob-Spawning.patch | 57 ++++++++++++ patches/server/PreSpawnerSpawnEvent.patch | 29 ++++++ ...tedContainer-instead-of-ReentrantLoc.patch | 92 +++++++++++++++++++ 4 files changed, 225 insertions(+) create mode 100644 patches/api/PreSpawnerSpawnEvent.patch create mode 100644 patches/server/Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch create mode 100644 patches/server/PreSpawnerSpawnEvent.patch create mode 100644 patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch diff --git a/patches/api/PreSpawnerSpawnEvent.patch b/patches/api/PreSpawnerSpawnEvent.patch new file mode 100644 index 0000000000..391d4675fa --- /dev/null +++ b/patches/api/PreSpawnerSpawnEvent.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 18 Sep 2018 23:50:10 +0100 +Subject: [PATCH] PreSpawnerSpawnEvent + +This adds a separate event before an entity is spawned by a spawner +which contains the location of the spawner too similarly to how the +SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for +spawners. + +Dropped as it does not apply due to the earlier PreCreatureSpawnEvent patch not being applied + +diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java +@@ -0,0 +0,0 @@ ++package com.destroystokyo.paper.event.entity; ++ ++ ++import com.google.common.base.Preconditions; ++import org.bukkit.Location; ++import org.bukkit.entity.EntityType; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called before an entity is spawned into a world by a spawner. ++ * ++ * This only includes the spawner's location and not the full BlockState snapshot for performance reasons. ++ * If you really need it you have to get the spawner yourself. ++ */ ++ ++public class PreSpawnerSpawnEvent extends PreCreatureSpawnEvent { ++ @NotNull private final Location spawnerLocation; ++ ++ public PreSpawnerSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull Location spawnerLocation) { ++ super(location, type, CreatureSpawnEvent.SpawnReason.SPAWNER); ++ this.spawnerLocation = Preconditions.checkNotNull(spawnerLocation, "Spawner location may not be null"); ++ } ++ ++ @NotNull ++ public Location getSpawnerLocation() { ++ return spawnerLocation; ++ } ++} diff --git a/patches/server/Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server/Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch new file mode 100644 index 0000000000..ebf886f2c3 --- /dev/null +++ b/patches/server/Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 12 Sep 2018 21:47:01 -0400 +Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning + +Uses an EnumMap as well as a Set paired List for O(1) contains calls. + +diff --git a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java ++++ b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java +@@ -0,0 +0,0 @@ public class MobSpawnSettings { + } + + public static class Builder { +- private final Map> spawners = Stream.of(MobCategory.values()).collect(ImmutableMap.toImmutableMap((mobCategory) -> { ++ // Paper start - keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it ++ public static class MobList extends java.util.ArrayList { ++ java.util.Set biomes = new java.util.HashSet<>(); ++ ++ @Override ++ public boolean contains(Object o) { ++ return biomes.contains(o); ++ } ++ ++ @Override ++ public boolean add(MobSpawnSettings.SpawnerData BiomeSettingsMobs) { ++ biomes.add(BiomeSettingsMobs); ++ return super.add(BiomeSettingsMobs); ++ } ++ ++ @Override ++ public MobSpawnSettings.SpawnerData remove(int index) { ++ MobSpawnSettings.SpawnerData removed = super.remove(index); ++ if (removed != null) { ++ biomes.remove(removed); ++ } ++ return removed; ++ } ++ ++ @Override ++ public void clear() { ++ biomes.clear(); ++ super.clear(); ++ } ++ } ++ // use toImmutableEnumMap collector ++ private final Map> spawners = (Map) Stream.of(MobCategory.values()).collect(Maps.toImmutableEnumMap((mobCategory) -> { + return mobCategory; + }, (mobCategory) -> { +- return Lists.newArrayList(); ++ return new MobList(); // Use MobList instead of ArrayList + })); ++ // Paper end + private final Map, MobSpawnSettings.MobSpawnCost> mobSpawnCosts = Maps.newLinkedHashMap(); + private float creatureGenerationProbability = 0.1F; + private boolean playerCanSpawn; diff --git a/patches/server/PreSpawnerSpawnEvent.patch b/patches/server/PreSpawnerSpawnEvent.patch new file mode 100644 index 0000000000..a31a073edb --- /dev/null +++ b/patches/server/PreSpawnerSpawnEvent.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Phoenix616 +Date: Tue, 18 Sep 2018 23:53:23 +0100 +Subject: [PATCH] PreSpawnerSpawnEvent + +This adds a separate event before an entity is spawned by a spawner +which contains the location of the spawner too similarly to how the +SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for +spawners. + +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + + org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); + if (type != null) { +- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; +- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( + net.minecraft.server.MCUtil.toLocation(world, d0, d1, d2), + type, +- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ net.minecraft.server.MCUtil.toLocation(world, pos) + ); + if (!event.callEvent()) { + flag = true; diff --git a/patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch b/patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch new file mode 100644 index 0000000000..43b02bbc14 --- /dev/null +++ b/patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLoc.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 May 2020 20:29:02 -0400 +Subject: [PATCH] Synchronize PalettedContainer instead of ReentrantLock + +Mojang has flaws in their logic about chunks being concurrently +wrote to. So we constantly see crashes around multiple threads writing. + +Additionally, java has optimized synchronization so well that its +in many times faster than trying to manage read wrote locks for low +contention situations. + +And this is extremely a low contention situation. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + private final DebugBuffer> traces = null; + + public void acquire() { ++ /* // Paper start - disable this - use proper synchronization + if (this.traces != null) { + Thread thread = Thread.currentThread(); + this.traces.push(Pair.of(thread, thread.getStackTrace())); + } + + ThreadingDetector.checkAndLock(this.lock, this.traces, "PalettedContainer"); ++ */ // Paper end + } + + public void release() { +- this.lock.release(); ++ //this.lock.release(); // Paper - disable this + } + + public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + return this.palette.idFor(objectAdded); + } + +- public T getAndSet(int x, int y, int z, T value) { ++ public synchronized T getAndSet(int x, int y, int z, T value) { // Paper - synchronize + Object var6; + try { + this.acquire(); +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + return (T)(object == null ? this.defaultValue : object); + } + +- public void set(int i, int j, int k, T object) { ++ public synchronized void set(int i, int j, int k, T object) { // Paper - synchronize + try { + this.acquire(); + this.set(getIndex(i, j, k), object); +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + return (T)(object == null ? this.defaultValue : object); + } + +- public void read(FriendlyByteBuf buf) { ++ public synchronized void read(FriendlyByteBuf buf) { // Paper - synchronize + try { + this.acquire(); + int i = buf.readByte(); +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + } + + public void writeDataPaletteBlock(FriendlyByteBuf packetDataSerializer) { this.write(packetDataSerializer); } // Paper - OBFHELPER +- public void write(FriendlyByteBuf buf) { ++ public synchronized void write(FriendlyByteBuf buf) { // Paper - synchronize + try { + this.acquire(); + buf.writeByte(this.bits); +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + + } + +- public void read(ListTag paletteNbt, long[] data) { ++ public synchronized void read(ListTag paletteNbt, long[] data) { // Paper - synchronize + try { + this.acquire(); + int i = Math.max(4, Mth.ceillog2(paletteNbt.size())); +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + + } + +- public void write(CompoundTag nbt, String paletteKey, String dataKey) { ++ public synchronized void write(CompoundTag nbt, String paletteKey, String dataKey) { // Paper - synchronize + try { + this.acquire(); + HashMapPalette hashMapPalette = new HashMapPalette<>(this.registry, this.bits, this.dummyPaletteResize, this.reader, this.writer);