diff --git a/patches/server/0010-Pufferfish-Entity-TTL.patch b/patches/removed/server/0010-Pufferfish-Entity-TTL.patch similarity index 98% rename from patches/server/0010-Pufferfish-Entity-TTL.patch rename to patches/removed/server/0010-Pufferfish-Entity-TTL.patch index bec695688..132dea013 100644 --- a/patches/server/0010-Pufferfish-Entity-TTL.patch +++ b/patches/removed/server/0010-Pufferfish-Entity-TTL.patch @@ -3,6 +3,8 @@ From: Kevin Raneri Date: Thu, 2 Jun 2022 19:54:09 -0500 Subject: [PATCH] Pufferfish: Entity TTL +Removed since Leaf 1.21.3, Paper 1.21.3 included it + Original license: GPL v3 Original project: https://github.com/pufferfish-gg/Pufferfish diff --git a/patches/server/0121-Paper-PR-Reduce-work-done-in-CraftMapCanvas.drawImag.patch b/patches/removed/server/0121-Paper-PR-Reduce-work-done-in-CraftMapCanvas.drawImag.patch similarity index 98% rename from patches/server/0121-Paper-PR-Reduce-work-done-in-CraftMapCanvas.drawImag.patch rename to patches/removed/server/0121-Paper-PR-Reduce-work-done-in-CraftMapCanvas.drawImag.patch index b6db79f35..e25e9a1ce 100644 --- a/patches/server/0121-Paper-PR-Reduce-work-done-in-CraftMapCanvas.drawImag.patch +++ b/patches/removed/server/0121-Paper-PR-Reduce-work-done-in-CraftMapCanvas.drawImag.patch @@ -5,6 +5,8 @@ Subject: [PATCH] Paper PR: Reduce work done in CraftMapCanvas.drawImage by limiting size of image and using System.arraycopy instead of for loops and use bitwise operations to do bounds checks. +Removed since Leaf 1.21.3, Paper 1.21.3 included it + Original license: GPLv3 Original project: https://github.com/PaperMC/Paper Paper pull request: https://github.com/PaperMC/Paper/pull/11000 diff --git a/patches/server/0125-Paper-Improve-performance-of-RecipeManager-removeRec.patch b/patches/removed/server/0125-Paper-Improve-performance-of-RecipeManager-removeRec.patch similarity index 97% rename from patches/server/0125-Paper-Improve-performance-of-RecipeManager-removeRec.patch rename to patches/removed/server/0125-Paper-Improve-performance-of-RecipeManager-removeRec.patch index 9f03a49bd..5672292c7 100644 --- a/patches/server/0125-Paper-Improve-performance-of-RecipeManager-removeRec.patch +++ b/patches/removed/server/0125-Paper-Improve-performance-of-RecipeManager-removeRec.patch @@ -3,6 +3,8 @@ From: Jake Potrebic Date: Thu, 31 Oct 2024 20:36:41 -0700 Subject: [PATCH] Paper: Improve performance of RecipeManager#removeRecipe +Removed since Leaf 1.21.3, Paper 1.21.3 included it + Original license: GPLv3 Original project: https://github.com/PaperMC/Paper Paper pull request: https://github.com/PaperMC/Paper/pull/11547 diff --git a/patches/server/0126-Paper-Fix-move-to-jline-terminal-ffm-on-java-22-and-.patch b/patches/removed/server/0126-Paper-Fix-move-to-jline-terminal-ffm-on-java-22-and-.patch similarity index 97% rename from patches/server/0126-Paper-Fix-move-to-jline-terminal-ffm-on-java-22-and-.patch rename to patches/removed/server/0126-Paper-Fix-move-to-jline-terminal-ffm-on-java-22-and-.patch index 558113871..b17e563cb 100644 --- a/patches/server/0126-Paper-Fix-move-to-jline-terminal-ffm-on-java-22-and-.patch +++ b/patches/removed/server/0126-Paper-Fix-move-to-jline-terminal-ffm-on-java-22-and-.patch @@ -4,6 +4,8 @@ Date: Sun, 17 Nov 2024 20:31:50 +0100 Subject: [PATCH] Paper: Fix: move to jline-terminal-ffm on java 22+ and fall back to jni on 21 +Removed since Leaf 1.21.3, Paper 1.21.3 included it + Original license: GPLv3 Original project: https://github.com/PaperMC/Paper Paper pull request: https://github.com/PaperMC/Paper/pull/11631 diff --git a/patches/server/0151-Better-inline-world-height.patch b/patches/removed/server/0151-Better-inline-world-height.patch similarity index 99% rename from patches/server/0151-Better-inline-world-height.patch rename to patches/removed/server/0151-Better-inline-world-height.patch index 6c85dcd37..f672daeba 100644 --- a/patches/server/0151-Better-inline-world-height.patch +++ b/patches/removed/server/0151-Better-inline-world-height.patch @@ -3,6 +3,7 @@ From: Taiyou06 Date: Fri, 8 Nov 2024 04:07:25 +0100 Subject: [PATCH] Better inline world height +Removed since Leaf 1.21.3, Paper 1.21.3 included it diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/WorldUtil.java b/src/main/java/ca/spottedleaf/moonrise/common/util/WorldUtil.java index af9623240ff2d389aa7090623f507720e7dbab7d..a286c8989f8c53fb896be7a3a8e15f850ece1df8 100644 diff --git a/patches/server/0001-Rebrand.patch b/patches/server/0001-Rebrand.patch index 10e5e8e3f..276a2524a 100644 --- a/patches/server/0001-Rebrand.patch +++ b/patches/server/0001-Rebrand.patch @@ -5,19 +5,19 @@ Subject: [PATCH] Rebrand diff --git a/build.gradle.kts b/build.gradle.kts -index 5ebc35cadc960d428e8a91642ddce0875078d790..4426855192b7dcc58b16d41b8a9d44bbbed3b55f 100644 +index 579877ba9bf17f40313c05ad5b1b219cf4b59ab3..a32417619cf253f25f060266a36e895c2e8b623e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -13,7 +13,7 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { - val alsoShade: Configuration by configurations.creating +@@ -25,7 +25,7 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider { + // Paper end - configure mockito agent that is needed in newer java versions dependencies { - implementation(project(":gale-api")) // Gale start - project setup - Depend on own API + implementation(project(":leaf-api")) // Gale start - project setup - Depend on own API // Leaf // Paper start - implementation("org.jline:jline-terminal-jansi:3.21.0") - implementation("net.minecrell:terminalconsoleappender:1.3.0") -@@ -95,14 +95,14 @@ tasks.jar { + implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+ + implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21 +@@ -109,14 +109,14 @@ tasks.jar { val gitBranch = git("rev-parse", "--abbrev-ref", "HEAD").getText().trim() // Paper attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", @@ -38,7 +38,7 @@ index 5ebc35cadc960d428e8a91642ddce0875078d790..4426855192b7dcc58b16d41b8a9d44bb "Build-Time" to Instant.now().toString(), "Git-Branch" to gitBranch, // Paper diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index ac23c85f17e0a5cd9702888a873cc470428b3e34..6c5c0cc59ff9901b22288f3cd62228c1e52794c5 100644 +index f21106b0897dd6e373970f32f5dd269418528977..6d8634caade010a31a8e1c59684e9bb0e5546380 100644 --- a/src/main/java/com/destroystokyo/paper/Metrics.java +++ b/src/main/java/com/destroystokyo/paper/Metrics.java @@ -593,7 +593,7 @@ public class Metrics { @@ -162,10 +162,10 @@ index 4d037e899e0b5548be406ad55acd2062603b7da1..379b36944ddb149e2f48221aa39ad090 DamageSource damageSource = this.cloneInstance(); damageSource.customEventDamager = entity; diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 11cf6a20550e252501a92be5bdffafcff007cbf9..54f7aa95cfbcf39bb86ad1b4eb0f9ff2f8526030 100644 +index cbeebb98622025d35557125e784cd8f0b4fbb751..79aca7e7cd2f860464657e77e935391642981fad 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -182,7 +182,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -294,7 +294,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise We do not want people to report thread issues to Paper, but we do want people to report thread issues to Gale. */ @@ -175,24 +175,24 @@ index 11cf6a20550e252501a92be5bdffafcff007cbf9..54f7aa95cfbcf39bb86ad1b4eb0f9ff2 } diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index bdfb969f88e68d89a5cad4b145bbc1441a110bac..fba0558f46516f65c678635359f305f865336d3a 100644 +index f6bc955c3496b52cda1a20aabd78769803ef471f..bbeb271fb19091897e99970198a8a110a4aa0858 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -492,7 +492,7 @@ public class CraftScheduler implements BukkitScheduler { +@@ -491,7 +491,7 @@ public class CraftScheduler implements BukkitScheduler { this.parsePending(); } else { - // this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper + // this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(this.currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper - task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Gale"); // Paper // Gale - branding changes + task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Leaf"); // Paper // Gale - branding changes // Leaf // We don't need to parse pending // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 4d0de69b730599d7a89903dd862b89d51ba79e1b..ebf68793373b128e63960e1c60a22d71a46a6b4e 100644 +index e57be8cbe35fdc2ae41b3a0278d244672a303059..6f9aecffd821e041f8edc8b8af419b2617c297fc 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -489,7 +489,7 @@ public final class CraftMagicNumbers implements UnsafeValues { - +@@ -505,7 +505,7 @@ public final class CraftMagicNumbers implements UnsafeValues { + // Paper start @Override public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { - return new org.galemc.gale.version.GaleVersionFetcher(); // Gale - branding changes - version fetcher diff --git a/patches/server/0003-Leaf-Config.patch b/patches/server/0003-Leaf-Config.patch index ddfbe50b1..3b96e29e0 100644 --- a/patches/server/0003-Leaf-Config.patch +++ b/patches/server/0003-Leaf-Config.patch @@ -11,10 +11,10 @@ Add per world config Add config reload diff --git a/build.gradle.kts b/build.gradle.kts -index c3790a8ebeeaaa395449e30ab69f1abfa9637034..a56ff254fb752030600fdf1d4ce62ff7ec14765d 100644 +index a32417619cf253f25f060266a36e895c2e8b623e..2fddb2f371b5b901be668fb60dbf871830ec571f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -14,6 +14,13 @@ val alsoShade: Configuration by configurations.creating +@@ -26,6 +26,13 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider { dependencies { implementation(project(":leaf-api")) // Gale start - project setup - Depend on own API // Leaf @@ -26,10 +26,10 @@ index c3790a8ebeeaaa395449e30ab69f1abfa9637034..a56ff254fb752030600fdf1d4ce62ff7 + // Leaf end - Leaf Config + // Paper start - implementation("org.jline:jline-terminal-jansi:3.21.0") - implementation("net.minecrell:terminalconsoleappender:1.3.0") + implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+ + implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21 diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 278adb48400ca9d4fd37bff040b37d4a8dd47282..759b22fc6f949829cef757232357368ef80d0d34 100644 +index d3219e3d36ef96bb43c2cb7d86f14ef7a702fcac..c7b5429910df7e3c4cfe1ac2f095845fd493c9b1 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java @@ -124,6 +124,7 @@ public class Main { @@ -41,10 +41,10 @@ index 278adb48400ca9d4fd37bff040b37d4a8dd47282..759b22fc6f949829cef757232357368e DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 4efbd656c57672b84c5d90f987bd57c67fc0c550..05f805c7e7a6ff6d40b9f86aaac5362ab516be3f 100644 +index 24b9711dca7223dd12b24c36cd76f50fbd96fc68..40c2dd482a8e10f1d5262d365841c968dda847cc 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1221,6 +1221,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop LeafBootstrap -> PaperBootstrap -> ... diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index c1e88c31910e96ef07cece05046c0b55e708b52d..c63dfc0b740ce2e544ad920188d7d7dfc2ae3e04 100644 +index be0d38544395a9b3befb898bb961f34e32fe9509..50a2b6e73ba4d8ad65582b2544fa409fd44f36d5 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -278,7 +278,8 @@ public class Main { - + System.setProperty("jdk.console", "java.base"); // Paper - revert default console provider back to java.base so we can have our own jline //System.out.println("Loading libraries, please wait..."); //net.minecraft.server.Main.main(options); - io.papermc.paper.PaperBootstrap.boot(options); diff --git a/patches/server/0007-Pufferfish-Optimize-mob-spawning.patch b/patches/server/0007-Pufferfish-Optimize-mob-spawning.patch index 1b597483a..890f9b739 100644 --- a/patches/server/0007-Pufferfish-Optimize-mob-spawning.patch +++ b/patches/server/0007-Pufferfish-Optimize-mob-spawning.patch @@ -71,12 +71,12 @@ index c21e00812f1aaa1279834a0562d360d6b89e146c..877d2095a066854939f260ca4b0b8c7b } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 05f805c7e7a6ff6d40b9f86aaac5362ab516be3f..654c381c210d9e353df8f7bca0cd7a434d997a8f 100644 +index 40c2dd482a8e10f1d5262d365841c968dda847cc..e084dd8f6e299e2ec71d7d5741c92b0e171f34f6 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -309,6 +309,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping + public gg.pufferfish.pufferfish.util.AsyncExecutor mobSpawnExecutor = new gg.pufferfish.pufferfish.util.AsyncExecutor("MobSpawning"); // Pufferfish - optimize mob spawning + @@ -84,10 +84,10 @@ index 05f805c7e7a6ff6d40b9f86aaac5362ab516be3f..654c381c210d9e353df8f7bca0cd7a43 AtomicReference atomicreference = new AtomicReference(); Thread thread = new ca.spottedleaf.moonrise.common.util.TickThread(() -> { // Paper - rewrite chunk system diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 2b289f84ffe49b46f1ca85893a6e3255f366bc5c..5ed84fbccf65aa91a4e8a19566207e1e7bb49620 100644 +index b4e2512366226d1132d87124b465071e000d2521..535dc6414c6b14ebd652695615e5a62d82f34171 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -371,6 +371,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -368,6 +368,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface DedicatedServer.LOGGER.info("JMX monitoring enabled"); } @@ -96,63 +96,21 @@ index 2b289f84ffe49b46f1ca85893a6e3255f366bc5c..5ed84fbccf65aa91a4e8a19566207e1e } } diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index c520d824630e8b5c569c3213d019b2548120a50f..e9d307dacea2f9b11cda5ecf5a06c7df09d1de90 100644 +index d6cfff8574567d0e3a77871c91be988ecfe31e25..4a2d941dab7df6158d7df507c18dfb63ec6e4afa 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -127,6 +127,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - // Paper end - rewrite chunk system - private ServerChunkCache.ChunkAndHolder[] iterationCopy; // Paper - chunk tick iteration optimisations +@@ -173,6 +173,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } + // Paper end - chunk tick iteration optimisations + public boolean firstRunSpawnCounts = true; // Pufferfish + public final java.util.concurrent.atomic.AtomicBoolean _pufferfish_spawnCountsReady = new java.util.concurrent.atomic.AtomicBoolean(false); // Pufferfish - optimize countmobs -+ + public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory) { this.level = world; - this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(world); -@@ -454,6 +457,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - // Paper start - Optional per player mob spawns - int naturalSpawnChunkCount = k; - if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled -+ if (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled) { // Pufferfish - moved down when async processing - // re-set mob counts - for (ServerPlayer player : this.level.players) { - // Paper start - per player mob spawning backoff -@@ -468,14 +472,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - } - // Paper end - per player mob spawning backoff - } -- spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); -+ lastSpawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); // Pufferfish - async mob spawning -+ } // Pufferfish - (endif) moved down when async processing - } else { -- spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); -+ // Pufferfish start - async mob spawning -+ lastSpawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); -+ _pufferfish_spawnCountsReady.set(true); -+ // Pufferfish end - } - // Paper end - Optional per player mob spawns - this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings - -- this.lastSpawnState = spawnercreature_d; -+ //this.lastSpawnState = spawnercreature_d; // Pufferfish - this is managed asynchronously - // Gale start - MultiPaper - skip unnecessary mob spawning computations - } else { - spawnercreature_d = null; -@@ -503,8 +511,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - - if (true && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) { // Paper - rewrite chunk system - chunk1.incrementInhabitedTime(j); -- if (flagAndHasNaturalSpawn && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot // Gale - MultiPaper - skip unnecessary mob spawning computations -- NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1); -+ if (flagAndHasNaturalSpawn && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get()) && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot // Gale - MultiPaper - skip unnecessary mob spawning computations // Pufferfish -+ NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1); // Pufferfish - } - - if (true) { // Paper - rewrite chunk system -@@ -544,6 +552,43 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing - // Paper end - chunk tick iteration optimisations +@@ -486,6 +488,43 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + + this.broadcastChangedChunks(); // Gale - Purpur - remove vanilla profiler } + + // Pufferfish start - optimize mob spawning @@ -193,7 +151,56 @@ index c520d824630e8b5c569c3213d019b2548120a50f..e9d307dacea2f9b11cda5ecf5a06c7df + // Pufferfish end } - // Gale start - MultiPaper - skip unnecessary mob spawning computations + private void broadcastChangedChunks() { // Gale - Purpur - remove vanilla profiler +@@ -537,6 +576,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + // Paper start - Optional per player mob spawns + final int naturalSpawnChunkCount = j; + if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled ++ if (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled) { // Pufferfish - moved down when async processing + // re-set mob counts + for (ServerPlayer player : this.level.players) { + // Paper start - per player mob spawning backoff +@@ -551,13 +591,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } + // Paper end - per player mob spawning backoff + } +- spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); ++ lastSpawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); // Pufferfish - async mob spawning ++ } // Pufferfish - (endif) moved down when async processing + } else { +- spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); ++ // Pufferfish start - async mob spawning ++ lastSpawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); ++ _pufferfish_spawnCountsReady.set(true); ++ // Pufferfish end + } + // Paper end - Optional per player mob spawns + +- this.lastSpawnState = spawnercreature_d; ++ //this.lastSpawnState = spawnercreature_d; // Pufferfish - this is managed asynchronously + // Gale start - MultiPaper - skip unnecessary mob spawning computations + } else { + spawnercreature_d = null; +@@ -577,7 +621,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + // Paper end - PlayerNaturallySpawnCreaturesEvent + boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit + +- list1 = NaturalSpawner.getFilteredSpawningCategories(spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1, this.level); // CraftBukkit ++ list1 = NaturalSpawner.getFilteredSpawningCategories(lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1, this.level); // CraftBukkit // Pufferfish + } else { + list1 = List.of(); + } +@@ -589,8 +633,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + ChunkPos chunkcoordintpair = chunk.getPos(); + + chunk.incrementInhabitedTime(timeDelta); +- if (!list1.isEmpty() && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot +- NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, list1); ++ if (!list1.isEmpty() && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get()) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot // Pufferfish ++ NaturalSpawner.spawnForChunk(this.level, chunk, lastSpawnState, list1); // Pufferfish + } + + if (true) { // Paper - rewrite chunk system diff --git a/src/main/java/net/minecraft/world/level/entity/EntityTickList.java b/src/main/java/net/minecraft/world/level/entity/EntityTickList.java index d8b4196adf955f8d414688dc451caac2d9c609d9..80a43def4912a3228cd95117d5c2aac68798b4ec 100644 --- a/src/main/java/net/minecraft/world/level/entity/EntityTickList.java diff --git a/patches/server/0008-Pufferfish-Dynamic-Activation-of-Brain.patch b/patches/server/0008-Pufferfish-Dynamic-Activation-of-Brain.patch index 69c0d0bf8..952d0ebf7 100644 --- a/patches/server/0008-Pufferfish-Dynamic-Activation-of-Brain.patch +++ b/patches/server/0008-Pufferfish-Dynamic-Activation-of-Brain.patch @@ -32,44 +32,44 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index d5652de3b6d71198a0153f087b43281fe579355d..9e4b4737ffcd777ad973e5c3c8f6c78c58995829 100644 +index c25da6e647401767def8cdbe505964865e8d7820..ea586b6c382ac49ffce0675442cc5dfb5c638628 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -701,6 +701,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -774,6 +774,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + org.spigotmc.ActivationRange.activateEntities(this); // Spigot - this.timings.entityTick.startTiming(); // Spigot this.entityTickList.forEach((entity) -> { + entity.activatedPriorityReset = false; // Pufferfish - DAB if (!entity.isRemoved()) { - if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed - entity.discard(); + if (!tickratemanager.isEntityFrozen(entity)) { + entity.checkDespawn(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 48c62f19459406ba393b4f5c277fdf9a393be5a3..22d3d963dc9806643608d077324b27832641ce57 100644 +index d9bd4116bd252e6df3b9c717c469cce0fb2e6fde..e9438f3b2acabcb9d3ecd6484704db1a94b21a0e 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -430,6 +430,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - private UUID originWorld; +@@ -388,6 +388,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public boolean freezeLocked = false; // Paper - Freeze Tick Lock API public boolean fixedPose = false; // Paper - Expand Pose API + private final int despawnTime; // Paper - entity despawn time limit + public boolean activatedPriorityReset = false; // Pufferfish - DAB + public int activatedPriority = org.dreeam.leaf.config.modules.opt.DynamicActivationofBrain.maximumActivationPrio; // Pufferfish - DAB (golf score) public void setOrigin(@javax.annotation.Nonnull Location location) { this.origin = location.toVector(); diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index cb61462d4691a055a4b25f7b953609d8a154fdfe..b2d8a858d8767bd6ca52e0b8db84757986c6ed61 100644 +index c8c2394558952d7ca57d29874485251b8f2b3400..24eaa9a2e6f0cf198a307058e655d5eb16a2c8c5 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -316,6 +316,7 @@ public class EntityType implements FeatureElement, EntityTypeT +@@ -384,6 +384,7 @@ public class EntityType implements FeatureElement, EntityTypeT private final boolean canSpawnFarFromPlayer; private final int clientTrackingRange; private final int updateInterval; + public boolean dabEnabled = false; // Pufferfish + private final String descriptionId; @Nullable - private String descriptionId; - @Nullable + private Component description; diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 06c57db4e6c76945cba514fc27828ff96fcd2c10..df932757d6a2f6812a1be16a3a71c4c4c75768b5 100644 +index ba1fc908290db310bec38c8eb1a3e464dd105bf6..fdeb3e58de44bba282cc5aa37f744a9e8c27ed46 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java @@ -237,10 +237,10 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab @@ -85,7 +85,7 @@ index 06c57db4e6c76945cba514fc27828ff96fcd2c10..df932757d6a2f6812a1be16a3a71c4c4 this.targetSelector.tick(); } } -@@ -920,10 +920,14 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -914,10 +914,14 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab int i = this.tickCount + this.getId(); if (i % 2 != 0 && this.tickCount > 1) { @@ -118,13 +118,13 @@ index 758f62416ca9c02351348ac0d41deeb4624abc0e..69130969c9a434ec2361e573c9a1ec9f } } diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -index 6fd5f65d8fb8830e000af6556c4009befa65b66f..6e01c7ba7720d6b08e4e98f59e0c086179e2ee0d 100644 +index 7ac88cb8704f84f1d932dff0fee927dfab8cad6a..38845c57d724dd08e224f2792caa874ad11268e1 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java -@@ -39,9 +39,13 @@ public class GoalSelector { +@@ -36,9 +36,13 @@ public class GoalSelector { } - // Paper start + // Paper start - EAR 2 - public boolean inactiveTick() { + public boolean inactiveTick(int tickRate, boolean inactive) { // Pufferfish start + if (inactive && !org.dreeam.leaf.config.modules.opt.DynamicActivationofBrain.enabled) tickRate = 4; // reset to Paper's @@ -138,7 +138,7 @@ index 6fd5f65d8fb8830e000af6556c4009befa65b66f..6e01c7ba7720d6b08e4e98f59e0c0861 public boolean hasTasks() { for (WrappedGoal task : this.availableGoals) { diff --git a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java -index a6b8c6540886af41ef1bccbd76784fe327e8277b..d908b7723d1810a91a7bc8783bb72c64231ac8c3 100644 +index 3a89c8bb4fbbe5a3a219e2fbc823c3abe529d1f2..5470b000760728b6703fccab5448a3f62d4335c8 100644 --- a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java +++ b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java @@ -217,8 +217,10 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS @@ -147,58 +147,58 @@ index a6b8c6540886af41ef1bccbd76784fe327e8277b..d908b7723d1810a91a7bc8783bb72c64 + private int behaviorTick = 0; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel) this.level(), this); + this.getBrain().tick(world, this); AllayAi.updateActivity(this); - super.customServerAiStep(); + super.customServerAiStep(world); diff --git a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java -index 1147bf32f6efe02e51c838eb371f11c6430a80a9..c75dccb977e0d620e3834ca0197e8fd51bf3bfd4 100644 +index 22dbc237498d765bc9a13f6c5924769122406c8a..dab55d73069018b17769b82a79acb5b8fe62772d 100644 --- a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java +++ b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java -@@ -269,8 +269,10 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder, B return true; } + private int behaviorTick = 0; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel) this.level(), this); + this.getBrain().tick(world, this); AxolotlAi.updateActivity(this); if (!this.isNoAi()) { diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java -index 22b84f4d84ca749a2094627b4dd4f4718f60cc74..29df5e116f8a7061081250622fd367e49e5e7171 100644 +index 1a71f1d094271b5ce798210562000f6d0160eaa6..e6e12142c24e7fff99423678bc47c2e1d38e8afd 100644 --- a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java +++ b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java -@@ -181,8 +181,10 @@ public class Frog extends Animal implements VariantHolder> { +@@ -182,8 +182,10 @@ public class Frog extends Animal implements VariantHolder> { .ifPresent(this::setVariant); } + private int behaviorTick = 0; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel)this.level(), this); + this.getBrain().tick(world, this); FrogAi.updateActivity(this); - super.customServerAiStep(); + super.customServerAiStep(world); diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java -index ab27bfb8b5a036eb13e77c8baeaa47e86a9ed2d6..d3cf26a3bdf40f6c827880bc394e7034a1adf4dc 100644 +index 76ecf98d91a368cd223f09bb0c56a50320999735..db617182d75f3418fef4b34cd8eddbfc90fc5a9e 100644 --- a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java +++ b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java -@@ -83,8 +83,10 @@ public class Tadpole extends AbstractFish { +@@ -81,8 +81,10 @@ public class Tadpole extends AbstractFish { return SoundEvents.TADPOLE_FLOP; } + private int behaviorTick = 0; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel) this.level(), this); + this.getBrain().tick(world, this); TadpoleAi.updateActivity(this); - super.customServerAiStep(); + super.customServerAiStep(world); diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java -index a6b6dd1715f7cb278b66381cbb0dd9d7069ce6ed..79ef4a1a4f4d404121087e2e6bcc3855556a88db 100644 +index f480ee1d0cde254d9621b85b4064771bdab2d3a3..509d1d1497c3f015686dbc485b82649a98356a02 100644 --- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java +++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java @@ -190,8 +190,10 @@ public class Goat extends Animal { @@ -207,63 +207,61 @@ index a6b6dd1715f7cb278b66381cbb0dd9d7069ce6ed..79ef4a1a4f4d404121087e2e6bcc3855 + private int behaviorTick = 0; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel) this.level(), this); + this.getBrain().tick(world, this); GoatAi.updateActivity(this); - super.customServerAiStep(); + super.customServerAiStep(world); diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java -index 8453c20a4b5f3a1205d0530b5c3b9f2c38a234a2..14878f825cc80296ffa09b5b2c0d8ed9a134491b 100644 +index 05a2d7a104161bde1dd913e14afb045264a54e87..9802aa9a1e4822684ba4406d2cafa4af69fe2ec5 100644 --- a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java -@@ -153,8 +153,10 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { - return (Brain)super.getBrain(); +@@ -136,8 +136,10 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { + return (Brain) super.getBrain(); // CraftBukkit - decompile error } + private int behaviorTick; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel)this.level(), this); + this.getBrain().tick(world, this); HoglinAi.updateActivity(this); if (this.isConverting()) { diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java -index 37452ff83fe07c9fa14a337cbf5018bfc7543f5a..6da1335186a6d31d8e78542f8b3bd11d214ef13c 100644 +index ad987660373cf1fd0edb778fa4203e3948b12fd4..aeedddd4b2ade905455c04ce475d35042c54e741 100644 --- a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java -@@ -293,8 +293,10 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento +@@ -302,8 +302,10 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento return !this.cannotHunt; } + private int behaviorTick; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel) this.level(), this); + this.getBrain().tick(world, this); PiglinAi.updateActivity(this); - super.customServerAiStep(); + super.customServerAiStep(world); diff --git a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java -index 1cb55c9240dfa46cf117ac5b8923b064a96788c3..37e682452ecc30646faf1ae8da47f91779619d42 100644 +index 9d9d58ab055b5bccedd6ebc9f6853ca8206cde65..64f3204b4b6ac0c57d0eb833a959f666f5259c6b 100644 --- a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java +++ b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java -@@ -272,10 +272,12 @@ public class Warden extends Monster implements VibrationSystem { +@@ -273,8 +273,10 @@ public class Warden extends Monster implements VibrationSystem { } + private int behaviorTick = 0; // Pufferfish @Override - protected void customServerAiStep() { - ServerLevel worldserver = (ServerLevel) this.level(); - + protected void customServerAiStep(ServerLevel world) { + if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick(worldserver, this); - super.customServerAiStep(); + this.getBrain().tick(world, this); + super.customServerAiStep(world); if ((this.tickCount + this.getId()) % 120 == 0) { diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 491a4c38cbb393c1a565d75a87c0444e321938c0..e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba 100644 +index de542de264d2a4ffa84699c34d3c576578c3d2a5..99f1c604a2e67043cbc53092a50d84b745640069 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -144,6 +144,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -142,6 +142,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler return holder.is(PoiTypes.MEETING); }); @@ -272,22 +270,22 @@ index 491a4c38cbb393c1a565d75a87c0444e321938c0..e1fd6ad56c0fbaf59c9d9ac985ab5301 public Villager(EntityType entityType, Level world) { this(entityType, world, VillagerType.PLAINS); } -@@ -247,6 +249,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -245,6 +247,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } // Spigot End + private int behaviorTick = 0; // Pufferfish @Override - @Deprecated // Paper - protected void customServerAiStep() { -@@ -255,7 +258,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + protected void customServerAiStep(ServerLevel world) { + // Paper start - EAR 2 +@@ -252,7 +255,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } - protected void customServerAiStep(final boolean inactive) { - // Paper end -- if (!inactive) this.getBrain().tick((ServerLevel) this.level(), this); // Paper + protected void customServerAiStep(ServerLevel world, final boolean inactive) { + // Paper end - EAR 2 +- if (!inactive) this.getBrain().tick(world, this); + // Pufferfish start + if (!inactive && this.behaviorTick++ % this.activatedPriority == 0) { -+ this.getBrain().tick((ServerLevel) this.level(), this); // Paper ++ this.getBrain().tick(world, this); // Paper + } + // Pufferfish end if (this.assignProfessionWhenSpawned) { @@ -381,10 +379,10 @@ index 0000000000000000000000000000000000000000..7e1e06ff65d1e186e6ec41917945d3d9 + } +} diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 881ef0d7a7d0ed2ab63f92358c16d2eb2059f5e7..54c9075029161212827c07cc83a5ed439b5ae5bf 100644 +index 5d1cc9b9150f84bb84cef5dd741e72787c02f089..62bb1fa77045ea83afe8a181c3b3a4d7284103b7 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -235,6 +235,23 @@ public class ActivationRange +@@ -233,6 +233,23 @@ public class ActivationRange } // Paper end - Configurable marker ticking ActivationRange.activateEntity(entity); @@ -408,7 +406,7 @@ index 881ef0d7a7d0ed2ab63f92358c16d2eb2059f5e7..54c9075029161212827c07cc83a5ed43 } // Paper end } -@@ -251,12 +268,12 @@ public class ActivationRange +@@ -248,12 +265,12 @@ public class ActivationRange if ( MinecraftServer.currentTick > entity.activatedTick ) { if ( entity.defaultActivationState ) diff --git a/patches/server/0011-Purpur-Server-Changes.patch b/patches/server/0010-Purpur-Server-Changes.patch similarity index 88% rename from patches/server/0011-Purpur-Server-Changes.patch rename to patches/server/0010-Purpur-Server-Changes.patch index 20624b3db..581d96556 100644 --- a/patches/server/0011-Purpur-Server-Changes.patch +++ b/patches/server/0010-Purpur-Server-Changes.patch @@ -1,12 +1,12 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Github Actions -Date: Fri, 21 Jun 2024 03:34:00 +0000 +Date: Thu, 12 Dec 2024 11:10:14 +0000 Subject: [PATCH] Purpur Server Changes Original license: MIT Original project: https://github.com/PurpurMC/Purpur -Commit: 803bf624d9e6616b879a16e6ce3c7e196468c577 +Commit: 16ce24aa7eb08232030e4570e027f7baefa5f3f9 Patches below are removed in this patch: Pufferfish-Server-Changes.patch @@ -25,16 +25,14 @@ Add-5-second-tps-average-in-tps.patch Arrows-should-not-reset-despawn-counter.patch MC-238526-Fix-spawner-not-spawning-water-animals-cor.patch Option-to-disable-kick-for-out-of-order-chat.patch -Remove-Timings.patch -Remove-Mojang-Profiler.patch Make-pufferfish-config-relocatable.patch MC-121706-Fix-mobs-not-looking-up-and-down-when-stra.patch diff --git a/build.gradle.kts b/build.gradle.kts -index a56ff254fb752030600fdf1d4ce62ff7ec14765d..d1bcbd39120480b2e1e402040d20b8567019a4b0 100644 +index 2fddb2f371b5b901be668fb60dbf871830ec571f..3b0cd45cb07d9563c84901729f1f7edc498653bd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -54,6 +54,12 @@ dependencies { +@@ -67,6 +67,12 @@ dependencies { runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18") @@ -47,7 +45,7 @@ index a56ff254fb752030600fdf1d4ce62ff7ec14765d..d1bcbd39120480b2e1e402040d20b856 testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") testImplementation("org.junit.platform:junit-platform-suite-engine:1.10.0") -@@ -170,7 +176,7 @@ fun TaskContainer.registerRunTask( +@@ -189,7 +195,7 @@ fun TaskContainer.registerRunTask( name: String, block: JavaExec.() -> Unit ): TaskProvider = register(name) { @@ -148,7 +146,7 @@ index 0000000000000000000000000000000000000000..15a226e3854d731f7724025ea3459c8a + } +} diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -index f7241c5292f1c012404eea11256813fbc2c2df1a..fad407d0cec0605e303e93a79752435f0b4646d7 100644 +index 3470720466fc81f977c18e3a97bb918926025a22..c8651af322927c46d075f88890fcd0476bd85440 100644 --- a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java +++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java @@ -136,6 +136,10 @@ public class MobGoalHelper { @@ -303,10 +301,10 @@ index f0fce4113fb07c64adbec029d177c236cbdcbae8..865dc183276720d54d31d2a54d1bb5c8 } diff --git a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java -index 1dd9531ffa272b8248f78a9ec029edcd15339b5a..6a43683f2d6932fa6149759c09d7cab4441e06fd 100644 +index b993d3e2e9d987115129067e3a51060880453ee2..a9d5bad94d499ea8c63beff268713261cbdea216 100644 --- a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java +++ b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java -@@ -260,6 +260,7 @@ public class PaperConfigurations extends Configurations 0 || SysoutCatcher.NAG_TIMEOUT > 0) { diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java -index 2d344df35d47b4b1ecddf32ccaa4dae41e5f58cb..08e783882d0b2ef3ebf88e664f1a3d8bf65f49f2 100644 +index 13bd145b1e8006a53c22f5dc0c78f29b540c7663..0d133cd7993eb40b19e2aabe8e2bfcdcf5352398 100644 --- a/src/main/java/net/minecraft/commands/CommandSourceStack.java +++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java -@@ -209,6 +209,19 @@ public class CommandSourceStack implements ExecutionCommandSource> { @@ -573,21 +571,8 @@ index 71bcc4c69ea4bf12eed7b3238c7703b9cdbc159e..652c25272832cf80fbd05eb7ac109024 Connection.joinAttemptsThisTick = 0; } // Paper end - Buffer joins to world -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java -index 76ef195a5074006b009acd9cc1744667c6aecbb9..659577549e132754281df76a7a1bfd884443c56a 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java -@@ -10,7 +10,7 @@ public class ClientboundSetTimePacket implements Packet processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; // Paper - don't store the vanilla dispatcher -@@ -304,6 +305,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper - BlockPhysicsEvent +@@ -1807,6 +1841,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper - Add EntityMoveEvent net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers -- worldserver.updateLagCompensationTick(); // Paper - lag compensation -+ worldserver.updateLagCompensationTick(); // Paper - lag + worldserver.updateLagCompensationTick(); // Paper - lag compensation + worldserver.hasRidableMoveEvent = org.purpurmc.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur /* Drop global time updates if (this.tickCount % 20 == 0) { diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java -index 720c9bc6f93a979c18024175e7986db60c224420..e06e4600066bab6a747d8ddd10cf6b51da82f521 100644 +index 66e7fa8a01d5364f7a82ed36f41edc6735b0b5ef..67f7c397328c8fbdbd30e1f3b94821a785ff1036 100644 --- a/src/main/java/net/minecraft/server/PlayerAdvancements.java +++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java @@ -249,6 +249,7 @@ public class PlayerAdvancements { advancement.value().display().ifPresent((advancementdisplay) -> { // Paper start - Add Adventure message to PlayerAdvancementDoneEvent - if (event.message() != null && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { + if (event.message() != null && this.player.serverLevel().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { + if (org.purpurmc.purpur.PurpurConfig.advancementOnlyBroadcastToAffectedPlayer) this.player.sendMessage(message); else // Purpur this.playerList.broadcastSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.message()), false); // Paper end } diff --git a/src/main/java/net/minecraft/server/commands/EnchantCommand.java b/src/main/java/net/minecraft/server/commands/EnchantCommand.java -index 99695e38b6a10c3cffda6e453f9f0619c7406cc0..2283f69607cb769545c85bcae940ac956779e80b 100644 +index cf0a5943f457c532958f40b4989fa18f967abae6..2ab8ff8ca51eb841932ccca4a348acc0141264a8 100644 --- a/src/main/java/net/minecraft/server/commands/EnchantCommand.java +++ b/src/main/java/net/minecraft/server/commands/EnchantCommand.java @@ -70,7 +70,7 @@ public class EnchantCommand { @@ -772,10 +755,10 @@ index 0d9de4c61c7b26a6ff37c12fde629161fd0c3d5a..2f7897744f4aea718170698881773e90 entityitem = entityplayer.drop(itemstack, false, false, false); // CraftBukkit - SPIGOT-2942: Add boolean to call event if (entityitem != null) { diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 5ed84fbccf65aa91a4e8a19566207e1e7bb49620..d87c0d251d8ba31d18478fbf107642c600f62c3d 100644 +index 535dc6414c6b14ebd652695615e5a62d82f34171..940fdcfe0e1bd68891903f33d61d63c2d72fc3df 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -114,6 +114,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -111,6 +111,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface return; } // Paper start - Use TerminalConsoleAppender @@ -783,7 +766,7 @@ index 5ed84fbccf65aa91a4e8a19566207e1e7bb49620..d87c0d251d8ba31d18478fbf107642c6 new com.destroystokyo.paper.console.PaperConsole(DedicatedServer.this).start(); /* jline.console.ConsoleReader bufferedreader = DedicatedServer.this.reader; -@@ -222,6 +223,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -219,6 +220,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface org.spigotmc.SpigotConfig.registerCommands(); // Spigot end io.papermc.paper.util.ObfHelper.INSTANCE.getClass(); // Paper - load mappings for stacktrace deobf and etc. @@ -799,7 +782,7 @@ index 5ed84fbccf65aa91a4e8a19566207e1e7bb49620..d87c0d251d8ba31d18478fbf107642c6 // Paper start - initialize global and world-defaults configuration this.paperConfigurations.initializeGlobalConfiguration(this.registryAccess()); this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess()); -@@ -298,6 +308,30 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -295,6 +305,30 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface if (true) throw new IllegalStateException("Failed to bind to port", ioexception); // Paper - Propagate failed to bind to port error return false; } @@ -830,7 +813,7 @@ index 5ed84fbccf65aa91a4e8a19566207e1e7bb49620..d87c0d251d8ba31d18478fbf107642c6 // CraftBukkit start // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // Spigot - moved up -@@ -372,6 +406,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -369,6 +403,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled) mobSpawnExecutor.start(); // Pufferfish @@ -840,7 +823,7 @@ index 5ed84fbccf65aa91a4e8a19566207e1e7bb49620..d87c0d251d8ba31d18478fbf107642c6 } } diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index d6431376184e5650b370cbab204e28bc31f4dac6..9ebe1f1797b5be562bc4f6d92b9a4d6022ca2151 100644 +index c3ec370b83b895be0f03662e3884fa4a2442a2a6..05e16103af3fd276f0196ddf1a2e5b729b025c34 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java @@ -56,6 +56,7 @@ public class DedicatedServerProperties extends Settings> trackedDataValues; // CraftBukkit start @@ -1002,10 +985,10 @@ index c80be65d190c85e7f0ea8233ebbbdbc1ea67f276..97e793c971614299504605aeb4f99cad public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { this.trackedPlayers = trackedPlayers; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbafa6426470 100644 +index ea586b6c382ac49ffce0675442cc5dfb5c638628..7d3d42e4fb09ac466cd41df3830fbcffc92d2737 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -220,6 +220,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -221,6 +221,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe private final StructureManager structureManager; private final StructureCheck structureCheck; private final boolean tickTime; @@ -1014,7 +997,7 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf private final RandomSequences randomSequences; // CraftBukkit start -@@ -228,6 +230,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -229,6 +231,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current) @@ -1022,8 +1005,8 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf public LevelChunk getChunkIfLoaded(int x, int z) { return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately -@@ -520,7 +523,24 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - this.dragonParts = new Int2ObjectOpenHashMap(); +@@ -602,7 +605,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + // CraftBukkit end this.tickTime = flag1; this.server = minecraftserver; - this.customSpawners = list; @@ -1048,15 +1031,15 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf this.serverLevelData = iworlddataserver; ChunkGenerator chunkgenerator = worlddimension.generator(); // CraftBukkit start -@@ -591,6 +611,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - this.chunkTaskScheduler = new ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler((ServerLevel)(Object)this, ca.spottedleaf.moonrise.common.util.MoonriseCommon.WORKER_POOL); +@@ -674,6 +694,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler); // Paper end - rewrite chunk system this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit + this.preciseTime = this.serverLevelData.getDayTime(); // Purpur } // Paper start -@@ -637,7 +658,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -720,7 +741,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); long j; @@ -1065,10 +1048,10 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf // CraftBukkit start j = this.levelData.getDayTime() + 24000L; TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (j - j % 24000L) - this.getDayTime()); -@@ -759,6 +780,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -828,6 +849,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.serverLevelData.setGameTime(i); this.serverLevelData.getScheduledEvents().tick(this.server, i); - if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + if (this.serverLevelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + // Purpur start + int incrementTicks = isDay() ? this.purpurConfig.daytimeTicks : this.purpurConfig.nighttimeTicks; + if (incrementTicks != 12000) { @@ -1079,7 +1062,7 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf this.setDayTime(this.levelData.getDayTime() + 1L); } -@@ -767,8 +795,22 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -836,8 +864,22 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public void setDayTime(long timeOfDay) { this.serverLevelData.setDayTime(timeOfDay); @@ -1102,17 +1085,17 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf public void tickCustomSpawners(boolean spawnMonsters, boolean spawnAnimals) { Iterator iterator = this.customSpawners.iterator(); -@@ -864,10 +906,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -923,10 +965,18 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * this.paperConfig().entities.spawning.skeletonHorseThunderSpawnChance.or(0.01D) && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper - Configurable spawn chances for skeleton horses if (flag1) { -- SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this); +- SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT); + // Purpur start + net.minecraft.world.entity.animal.horse.AbstractHorse entityhorseskeleton; + if (purpurConfig.zombieHorseSpawnChance > 0D && random.nextDouble() <= purpurConfig.zombieHorseSpawnChance) { -+ entityhorseskeleton = EntityType.ZOMBIE_HORSE.create(this); ++ entityhorseskeleton = EntityType.ZOMBIE_HORSE.create(this, EntitySpawnReason.EVENT); + } else { -+ entityhorseskeleton = EntityType.SKELETON_HORSE.create(this); ++ entityhorseskeleton = EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT); + if (entityhorseskeleton != null) ((SkeletonHorse) entityhorseskeleton).setTrap(true); + } + // Purpur end @@ -1123,7 +1106,7 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf entityhorseskeleton.setAge(0); entityhorseskeleton.setPos((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); this.addFreshEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit -@@ -946,7 +996,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1002,7 +1052,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe return holder.is(PoiTypes.LIGHTNING_ROD); }, (blockposition1) -> { return blockposition1.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockposition1.getX(), blockposition1.getZ()) - 1; @@ -1132,7 +1115,7 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf return optional.map((blockposition1) -> { return blockposition1.above(1); -@@ -995,11 +1045,27 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1051,11 +1101,27 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe if (this.canSleepThroughNights()) { if (!this.getServer().isSingleplayer() || this.getServer().isPublished()) { int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); @@ -1161,7 +1144,7 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf ichatmutablecomponent = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(i)); } -@@ -1139,6 +1205,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1195,6 +1261,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @VisibleForTesting public void resetWeatherCycle() { // CraftBukkit start @@ -1169,7 +1152,7 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf this.serverLevelData.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - Add cause to Weather/ThunderChangeEvents // If we stop due to everyone sleeping we should reset the weather duration to some other random value. // Not that everyone ever manages to get the whole server to sleep at the same time.... -@@ -1146,6 +1213,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1202,6 +1269,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.serverLevelData.setRainTime(0); } // CraftBukkit end @@ -1177,7 +1160,7 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf this.serverLevelData.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - Add cause to Weather/ThunderChangeEvents // CraftBukkit start // If we stop due to everyone sleeping we should reset the weather duration to some other random value. -@@ -2586,7 +2654,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2741,7 +2809,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // Spigot Start if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message // Paper start - Fix merchant inventory not closing on entity removal @@ -1187,10 +1170,10 @@ index 9e4b4737ffcd777ad973e5c3c8f6c78c58995829..fd285a768218ec56f4fdf58e17c7dbaf } // Paper end - Fix merchant inventory not closing on entity removal diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3ca77af28 100644 +index 7e06a80e6deb80df865f7798588a92b88084411b..61a990d17adaa9f4144d8a1010e764ae5b4ee2fa 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -303,6 +303,10 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -328,6 +328,10 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent public @Nullable String clientBrandName = null; // Paper - Brand support public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event @@ -1201,7 +1184,7 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 // Paper start - rewrite chunk system private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader; -@@ -600,6 +604,9 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -690,6 +694,9 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple }); } @@ -1211,17 +1194,17 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 } @Override -@@ -676,6 +683,9 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple - }); +@@ -742,6 +749,9 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple } + this.saveEnderPearls(nbt); + nbt.putBoolean("Purpur.RamBar", this.ramBar); // Purpur + nbt.putBoolean("Purpur.TPSBar", this.tpsBar); // Purpur + nbt.putBoolean("Purpur.CompassBar", this.compassBar); // Purpur } - // CraftBukkit start - World fallback code, either respawn location or global spawn -@@ -805,6 +815,15 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple + private void saveParentVehicle(CompoundTag nbt) { +@@ -1031,6 +1041,15 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple this.trackEnteredOrExitedLavaOnVehicle(); this.updatePlayerAttributes(); this.advancements.flushDirty(this); @@ -1237,7 +1220,7 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 } private void updatePlayerAttributes() { -@@ -1070,6 +1089,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -1328,6 +1347,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple })); PlayerTeam scoreboardteam = this.getTeam(); @@ -1245,8 +1228,8 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 if (scoreboardteam != null && scoreboardteam.getDeathMessageVisibility() != Team.Visibility.ALWAYS) { if (scoreboardteam.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { this.server.getPlayerList().broadcastSystemToTeam(this, ichatbasecomponent); -@@ -1173,6 +1193,16 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple - if (this.isInvulnerableTo(source)) { +@@ -1431,6 +1451,16 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple + if (this.isInvulnerableTo(world, source)) { return false; } else { + // Purpur start @@ -1262,16 +1245,16 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 boolean flag = this.server.isDedicatedServer() && this.isPvpAllowed() && source.is(DamageTypeTags.IS_FALL); if (!flag && this.spawnInvulnerableTime > 0 && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { -@@ -1399,6 +1429,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -1658,6 +1688,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); this.unsetRemoved(); // CraftBukkit end + this.portalPos = io.papermc.paper.util.MCUtil.toBlockPosition(exit); // Purpur - Fix stuck in portals this.setServerLevel(worldserver); - this.connection.teleport(exit); // CraftBukkit - use internal teleport without event + this.connection.internalTeleport(PositionMoveRotation.of(teleportTarget), teleportTarget.relatives()); // CraftBukkit - use internal teleport without event this.connection.resetPosition(); -@@ -1502,7 +1533,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple - return entitymonster.isPreventingPlayerRest(this); +@@ -1767,7 +1798,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple + return entitymonster.isPreventingPlayerRest(this.serverLevel(), this); }); - if (!list.isEmpty()) { @@ -1279,7 +1262,7 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 return Either.left(net.minecraft.world.entity.player.Player.BedSleepingProblem.NOT_SAFE); } } -@@ -1542,7 +1573,19 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -1807,7 +1838,19 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple }); if (!this.serverLevel().canSleepThroughNights()) { @@ -1300,7 +1283,7 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 } ((ServerLevel) this.level()).updateSleepingPlayerList(); -@@ -1664,6 +1707,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -1929,6 +1972,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple @Override public void openTextEdit(SignBlockEntity sign, boolean front) { @@ -1308,7 +1291,7 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 this.connection.send(new ClientboundBlockUpdatePacket(this.level(), sign.getBlockPos())); this.connection.send(new ClientboundOpenSignEditorPacket(sign.getBlockPos(), front)); } -@@ -2004,6 +2048,26 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -2245,6 +2289,26 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple this.lastSentExp = -1; // CraftBukkit - Added to reset } @@ -1335,7 +1318,28 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 @Override public void displayClientMessage(Component message, boolean overlay) { this.sendSystemMessage(message, overlay); -@@ -2344,8 +2408,68 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -2475,6 +2539,20 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple + return new CommandSourceStack(this.commandSource(), this.position(), this.getRotationVector(), this.serverLevel(), this.getPermissionLevel(), this.getName().getString(), this.getDisplayName(), this.server, this); + } + ++ // Purpur Start ++ public void sendMiniMessage(@Nullable String message) { ++ if (message != null && !message.isEmpty()) { ++ this.sendMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message)); ++ } ++ } ++ ++ public void sendMessage(@Nullable net.kyori.adventure.text.Component message) { ++ if (message != null) { ++ this.sendSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message)); ++ } ++ } ++ // Purpur end ++ + public void sendSystemMessage(Component message) { + this.sendSystemMessage(message, false); + } +@@ -2596,8 +2674,68 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple public void resetLastActionTime() { this.lastActionTime = Util.getMillis(); @@ -1404,7 +1408,7 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 public ServerStatsCounter getStats() { return this.stats; } -@@ -2949,4 +3073,50 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -3304,4 +3442,50 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple return (CraftPlayer) super.getBukkitEntity(); } // CraftBukkit end @@ -1424,7 +1428,7 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 + + ServerLevel toLevel = ((CraftWorld) to.getWorld()).getHandle(); + if (this.level() == toLevel) { -+ this.connection.internalTeleport(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch(), java.util.EnumSet.noneOf(net.minecraft.world.entity.RelativeMovement.class)); ++ this.connection.teleport(to); + } else { + this.server.getPlayerList().respawn(this, true, RemovalReason.KILLED, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.DEATH, to); + } @@ -1456,10 +1460,10 @@ index 1b3d0bb2ea57572b1419373873f04cc4e62d3795..1dc2af59bafa5a5dc6721da02cde19a3 + // Purpur end } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index ee9e4521079137d7b72194e8789810e7a89b8e75..28731f0c5b0ba63fa8d5ce3ee580bf314a844f92 100644 +index a96f859a5d0c6ec692d4627a69f3c9ee49199dbc..88eb3774f688bcff383efa7f113bd0b1b97d8a11 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -405,6 +405,7 @@ public class ServerPlayerGameMode { +@@ -403,6 +403,7 @@ public class ServerPlayerGameMode { } else {capturedBlockEntity = true;} // Paper - Send block entities after destroy prediction return false; } @@ -1467,7 +1471,7 @@ index ee9e4521079137d7b72194e8789810e7a89b8e75..28731f0c5b0ba63fa8d5ce3ee580bf31 } // CraftBukkit end -@@ -517,6 +518,7 @@ public class ServerPlayerGameMode { +@@ -523,6 +524,7 @@ public class ServerPlayerGameMode { public InteractionHand interactHand; public ItemStack interactItemStack; public InteractionResult useItemOn(ServerPlayer player, Level world, ItemStack stack, InteractionHand hand, BlockHitResult hitResult) { @@ -1475,16 +1479,16 @@ index ee9e4521079137d7b72194e8789810e7a89b8e75..28731f0c5b0ba63fa8d5ce3ee580bf31 BlockPos blockposition = hitResult.getBlockPos(); BlockState iblockdata = world.getBlockState(blockposition); boolean cancelledBlock = false; -@@ -577,7 +579,7 @@ public class ServerPlayerGameMode { +@@ -583,7 +585,7 @@ public class ServerPlayerGameMode { ItemStack itemstack1 = stack.copy(); InteractionResult enuminteractionresult; - if (!flag1) { + if (!flag1 || (player.level().purpurConfig.composterBulkProcess && iblockdata.is(Blocks.COMPOSTER))) { // Purpur - ItemInteractionResult iteminteractionresult = iblockdata.useItemOn(player.getItemInHand(hand), world, player, hand, hitResult); + InteractionResult enuminteractionresult1 = iblockdata.useItemOn(player.getItemInHand(hand), world, player, hand, hitResult); - if (iteminteractionresult.consumesAction()) { -@@ -625,4 +627,18 @@ public class ServerPlayerGameMode { + if (enuminteractionresult1.consumesAction()) { +@@ -631,4 +633,18 @@ public class ServerPlayerGameMode { public void setLevel(ServerLevel world) { this.level = world; } @@ -1504,7 +1508,7 @@ index ee9e4521079137d7b72194e8789810e7a89b8e75..28731f0c5b0ba63fa8d5ce3ee580bf31 + // Purpur end } diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -index ea245f4074825f8d6ef9b70843e50af227d330f8..499572fe78f3b0918d2bbf6ead15a2acf6a07007 100644 +index 92815589da3c2a1cb768ac8081660c9c2ccb2b14..32ab2e0f7bae7d0a54cebdd46c95e574c41ad1e3 100644 --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java @@ -88,6 +88,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack @@ -1515,7 +1519,7 @@ index ea245f4074825f8d6ef9b70843e50af227d330f8..499572fe78f3b0918d2bbf6ead15a2ac public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit this.server = minecraftserver; -@@ -187,6 +188,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -193,6 +194,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex); this.disconnect(Component.literal("Invalid payload REGISTER!"), PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause } @@ -1530,10 +1534,10 @@ index ea245f4074825f8d6ef9b70843e50af227d330f8..499572fe78f3b0918d2bbf6ead15a2ac try { String channels = payload.toString(com.google.common.base.Charsets.UTF_8); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb835df170 100644 +index 3455b7f21fee42d21182b8b5f8af7a9a238f646c..eb8ea4df3996a22d46a6fdc1df2fa1f26aa95aec 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -332,6 +332,20 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -342,6 +342,20 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl private boolean justTeleported = false; // CraftBukkit end @@ -1554,9 +1558,9 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb @Override public void tick() { if (this.ackBlockChangesUpTo > -1) { -@@ -399,6 +413,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - +@@ -398,6 +412,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + this.recipeSpamPackets.tick(); // Paper - auto recipe limit + this.dropSpamThrottler.tick(); if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) this.server.getPlayerIdleTimeout() * 1000L * 60L && !this.player.wonGame) { // Paper - Prevent AFK kick while watching end credits + // Purpur start + this.player.setAfk(true); @@ -1567,7 +1571,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 this.disconnect((Component) Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause } -@@ -658,6 +678,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -663,6 +683,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.lastYaw = to.getYaw(); this.lastPitch = to.getPitch(); @@ -1576,7 +1580,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb Location oldTo = to.clone(); PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); this.cserver.getPluginManager().callEvent(event); -@@ -733,6 +755,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -739,6 +761,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); if (packet.getId() == this.awaitingTeleport) { if (this.awaitingPositionFromClient == null) { @@ -1584,7 +1588,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb this.disconnect((Component) Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause return; } -@@ -1170,6 +1193,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1185,6 +1208,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl final int maxBookPageSize = pageMax.intValue(); final double multiplier = Math.clamp(io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.bookSize.totalMultiplier, 0.3D, 1D); long byteAllowed = maxBookPageSize; @@ -1595,7 +1599,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb for (final String page : pageList) { final int byteLength = page.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; byteTotal += byteLength; -@@ -1194,7 +1221,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1209,7 +1236,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } if (byteTotal > byteAllowed) { @@ -1605,10 +1609,10 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb this.disconnectAsync(Component.literal("Book too large!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Paper - add proper async disconnect return; } -@@ -1219,10 +1247,14 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - +@@ -1231,10 +1259,14 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl Objects.requireNonNull(list); - stream.forEach(list::add); + optional.ifPresent(list::add); + list.addAll(packet.pages()); + // Purpur start + boolean hasEditPerm = getCraftPlayer().hasPermission("purpur.book.color.edit"); + boolean hasSignPerm = hasEditPerm || getCraftPlayer().hasPermission("purpur.book.color.sign"); @@ -1622,7 +1626,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb }; this.filterTextPacket((List) list).thenAcceptAsync(consumer, this.server); -@@ -1230,13 +1262,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1242,13 +1274,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } private void updateBookContents(List pages, int slotId) { @@ -1636,13 +1640,13 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb ItemStack itemstack = handItem.copy(); // CraftBukkit end - if (itemstack.is(Items.WRITABLE_BOOK)) { + if (itemstack.has(DataComponents.WRITABLE_BOOK_CONTENT)) { - List> list1 = pages.stream().map(this::filterableFromOutgoing).toList(); + List> list1 = pages.stream().map(filteredText -> filterableFromOutgoing(filteredText).map(s -> color(s, hasPerm))).toList(); // Purpur itemstack.set(DataComponents.WRITABLE_BOOK_CONTENT, new WritableBookContent(list1)); this.player.getInventory().setItem(slotId, CraftEventFactory.handleEditBookEvent(this.player, slotId, handItem, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) -@@ -1244,6 +1281,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1256,6 +1293,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } private void signBook(FilteredText title, List pages, int slotId) { @@ -1653,8 +1657,8 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb + // Purpur end ItemStack itemstack = this.player.getInventory().getItem(slotId); - if (itemstack.is(Items.WRITABLE_BOOK)) { -@@ -1251,10 +1293,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + if (itemstack.has(DataComponents.WRITABLE_BOOK_CONTENT)) { +@@ -1263,10 +1305,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl itemstack1.remove(DataComponents.WRITABLE_BOOK_CONTENT); List> list1 = (List>) (List) pages.stream().map((filteredtext1) -> { // CraftBukkit - decompile error @@ -1667,7 +1671,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb CraftEventFactory.handleEditBookEvent(this.player, slotId, itemstack, itemstack1); // CraftBukkit this.player.getInventory().setItem(slotId, itemstack); // CraftBukkit - event factory updates the hand book } -@@ -1264,6 +1306,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1276,6 +1318,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl return this.player.isTextFilteringEnabled() ? Filterable.passThrough(message.filteredOrEmpty()) : Filterable.from(message); } @@ -1684,7 +1688,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb @Override public void handleEntityTagQuery(ServerboundEntityTagQueryPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); -@@ -1313,7 +1365,15 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1325,7 +1377,15 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl @Override public void handleMovePlayer(ServerboundMovePlayerPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1701,7 +1705,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb this.disconnect((Component) Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause } else { ServerLevel worldserver = this.player.serverLevel(); -@@ -1493,7 +1553,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1505,7 +1565,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl movedWrongly = true; if (event.getLogWarning()) // Paper end @@ -1710,7 +1714,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb } // Paper } -@@ -1561,6 +1621,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1573,6 +1633,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.lastYaw = to.getYaw(); this.lastPitch = to.getPitch(); @@ -1719,7 +1723,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb Location oldTo = to.clone(); PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); this.cserver.getPluginManager().callEvent(event); -@@ -1605,6 +1667,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1618,6 +1680,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.player.tryResetCurrentImpulseContext(); } @@ -1733,7 +1737,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb this.player.checkMovementStatistics(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5); this.lastGoodX = this.player.getX(); this.lastGoodY = this.player.getY(); -@@ -1632,6 +1701,14 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1657,6 +1726,14 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } } @@ -1748,7 +1752,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb // Paper start - optimise out extra getCubes private boolean hasNewCollision(final ServerLevel world, final Entity entity, final AABB oldBox, final AABB newBox) { final List collisionsBB = new java.util.ArrayList<>(); -@@ -2011,6 +2088,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2030,6 +2107,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl boolean cancelled; if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) { @@ -1756,15 +1760,15 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemstack, enumhand); cancelled = event.useItemInHand() == Event.Result.DENY; } else { -@@ -2792,6 +2870,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2813,6 +2891,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl AABB axisalignedbb = entity.getBoundingBox(); - if (this.player.canInteractWithEntity(axisalignedbb, io.papermc.paper.configuration.GlobalConfiguration.get().misc.clientInteractionLeniencyDistance.or(1.0D))) { // Paper - configurable lenience value for interact range + if (this.player.canInteractWithEntity(axisalignedbb, io.papermc.paper.configuration.GlobalConfiguration.get().misc.clientInteractionLeniencyDistance.or(3.0D))) { // Paper - configurable lenience value for interact range + if (entity instanceof Mob mob) mob.ticksSinceLastInteraction = 0; // Purpur packet.dispatch(new ServerboundInteractPacket.Handler() { private void performInteraction(InteractionHand enumhand, ServerGamePacketListenerImpl.EntityInteraction playerconnection_a, PlayerInteractEntityEvent event) { // CraftBukkit ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(enumhand); -@@ -2805,6 +2884,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2826,6 +2905,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl ServerGamePacketListenerImpl.this.cserver.getPluginManager().callEvent(event); @@ -1774,7 +1778,7 @@ index abad5d2b6d96a13b57049f65edf9219a4f5cf1fb..182e5cb7bb9b62e78248330bb05c79fb if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem)) { entity.resendPossiblyDesyncedEntityData(ServerGamePacketListenerImpl.this.player); // Paper - The entire mob gets deleted, so resend it diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index cc426f77eb940982c495bb3037bebe78b7fcf504..5e64def50ba96778cbfaaf1dde0bd8193e9b6bfe 100644 +index 70534d9d58a209c0c8fd6f4d3ba65773f420f559..d5acf191e3f34c84b3711c0ba77e7cb001aee507 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -335,7 +335,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, @@ -1787,18 +1791,18 @@ index cc426f77eb940982c495bb3037bebe78b7fcf504..5e64def50ba96778cbfaaf1dde0bd819 } } catch (AuthenticationUnavailableException authenticationunavailableexception) { diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index c16abdc26c76ff62ee1c3e61fae35a2d6ddd44cd..fe8eba4f73a7df86912002c25516806c8cabf114 100644 +index 99521abc925e0c7754d9e5aaad52e4fa70383946..3d6a728c6f9542109e7466d590bb8f015b8c4ac1 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -491,6 +491,7 @@ public abstract class PlayerList { +@@ -430,6 +430,7 @@ public abstract class PlayerList { scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); } // Paper end - Configurable player collision + org.purpurmc.purpur.task.BossBarTask.addToAll(player); // Purpur if (org.galemc.gale.configuration.GaleGlobalConfiguration.get().logToConsole.playerLoginLocations) { // Gale - JettPack - make logging login location configurable PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ()); - // Gale start - JettPack - make logging login location configurable -@@ -608,6 +609,7 @@ public abstract class PlayerList { + // Gale start - JettPack - make logging login location configurable +@@ -557,6 +558,7 @@ public abstract class PlayerList { } public net.kyori.adventure.text.Component remove(ServerPlayer entityplayer, net.kyori.adventure.text.Component leaveMessage) { // Paper end - Fix kick event leave message not being sent @@ -1806,7 +1810,7 @@ index c16abdc26c76ff62ee1c3e61fae35a2d6ddd44cd..fe8eba4f73a7df86912002c25516806c ServerLevel worldserver = entityplayer.serverLevel(); entityplayer.awardStat(Stats.LEAVE_GAME); -@@ -764,7 +766,7 @@ public abstract class PlayerList { +@@ -727,7 +729,7 @@ public abstract class PlayerList { event.disallow(PlayerLoginEvent.Result.KICK_BANNED, io.papermc.paper.adventure.PaperAdventure.asAdventure(ichatmutablecomponent)); // Paper - Adventure } else { // return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile) ? IChatBaseComponent.translatable("multiplayer.disconnect.server_full") : null; @@ -1815,7 +1819,7 @@ index c16abdc26c76ff62ee1c3e61fae35a2d6ddd44cd..fe8eba4f73a7df86912002c25516806c event.disallow(PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure } } -@@ -1085,6 +1087,20 @@ public abstract class PlayerList { +@@ -1050,6 +1052,20 @@ public abstract class PlayerList { } // CraftBukkit end @@ -1836,7 +1840,7 @@ index c16abdc26c76ff62ee1c3e61fae35a2d6ddd44cd..fe8eba4f73a7df86912002c25516806c public void broadcastAll(Packet packet, ResourceKey dimension) { Iterator iterator = this.players.iterator(); -@@ -1188,6 +1204,7 @@ public abstract class PlayerList { +@@ -1153,6 +1169,7 @@ public abstract class PlayerList { } else { b0 = (byte) (24 + permissionLevel); } @@ -1844,7 +1848,7 @@ index c16abdc26c76ff62ee1c3e61fae35a2d6ddd44cd..fe8eba4f73a7df86912002c25516806c player.connection.send(new ClientboundEntityEventPacket(player, b0)); } -@@ -1196,6 +1213,27 @@ public abstract class PlayerList { +@@ -1161,6 +1178,27 @@ public abstract class PlayerList { player.getBukkitEntity().recalculatePermissions(); // CraftBukkit this.server.getCommands().sendCommands(player); } // Paper - Add sendOpLevel API @@ -1895,7 +1899,7 @@ index 823efad652d8ff9e96b99375b102fef6f017716e..caa8a69bde0c212c36dd990a67836ac2 } // CraftBukkit start diff --git a/src/main/java/net/minecraft/util/StringUtil.java b/src/main/java/net/minecraft/util/StringUtil.java -index 0bd191acb9596d3aa21c337230d26f09d26f6888..20211f40aeeade9217ece087688974bdf55afc56 100644 +index 6c33002dc8bbb3759c3156302ab7d1f26ce5e8ee..c89fc375aff548a2b03eaf4da3b6a075012df012 100644 --- a/src/main/java/net/minecraft/util/StringUtil.java +++ b/src/main/java/net/minecraft/util/StringUtil.java @@ -69,6 +69,7 @@ public class StringUtil { @@ -2026,10 +2030,10 @@ index 379b36944ddb149e2f48221aa39ad090bbd2faeb..91a5be2eaedb0fa94580de60a9625f94 return this.type().msgId(); } diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSources.java b/src/main/java/net/minecraft/world/damagesource/DamageSources.java -index e34584e4780f343d6c946af5377088d53818e88e..d143bba490bfb677361ab82c44f0f31a4a2a43d6 100644 +index be87cb3cfa15a7d889118cdc4b87232e30749023..d343fd5c9f31073f1b3a0f91b8ea61a67077cc12 100644 --- a/src/main/java/net/minecraft/world/damagesource/DamageSources.java +++ b/src/main/java/net/minecraft/world/damagesource/DamageSources.java -@@ -45,11 +45,15 @@ public class DamageSources { +@@ -46,11 +46,15 @@ public class DamageSources { // CraftBukkit start private final DamageSource melting; private final DamageSource poison; @@ -2037,7 +2041,7 @@ index e34584e4780f343d6c946af5377088d53818e88e..d143bba490bfb677361ab82c44f0f31a + private final DamageSource stonecutter; // Purpur public DamageSources(RegistryAccess registryManager) { - this.damageTypes = registryManager.registryOrThrow(Registries.DAMAGE_TYPE); + this.damageTypes = registryManager.lookupOrThrow(Registries.DAMAGE_TYPE); this.melting = this.source(DamageTypes.ON_FIRE).melting(); this.poison = this.source(DamageTypes.MAGIC).poison(); + this.scissors = this.source(DamageTypes.MAGIC).scissors(); // Purpur @@ -2045,7 +2049,7 @@ index e34584e4780f343d6c946af5377088d53818e88e..d143bba490bfb677361ab82c44f0f31a // CraftBukkit end this.inFire = this.source(DamageTypes.IN_FIRE); this.campfire = this.source(DamageTypes.CAMPFIRE); -@@ -99,6 +103,15 @@ public class DamageSources { +@@ -101,6 +105,15 @@ public class DamageSources { } // CraftBukkit end @@ -2062,12 +2066,12 @@ index e34584e4780f343d6c946af5377088d53818e88e..d143bba490bfb677361ab82c44f0f31a return this.inFire; } diff --git a/src/main/java/net/minecraft/world/effect/HungerMobEffect.java b/src/main/java/net/minecraft/world/effect/HungerMobEffect.java -index a476b56ed98d0a1afc6a396ce29424df78f24ada..5119ff3414fbd9a1ae0a8db0fd15bd3c57c8e148 100644 +index 11d1ee8fae7670f02cb3f5d57f4774dbde77f48c..88cf1353892a7ead4e0f16822216b151726ac0e4 100644 --- a/src/main/java/net/minecraft/world/effect/HungerMobEffect.java +++ b/src/main/java/net/minecraft/world/effect/HungerMobEffect.java -@@ -12,7 +12,7 @@ class HungerMobEffect extends MobEffect { +@@ -13,7 +13,7 @@ class HungerMobEffect extends MobEffect { @Override - public boolean applyEffectTick(LivingEntity entity, int amplifier) { + public boolean applyEffectTick(ServerLevel world, LivingEntity entity, int amplifier) { if (entity instanceof Player entityhuman) { - entityhuman.causeFoodExhaustion(0.005F * (float) (amplifier + 1), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.HUNGER_EFFECT); // CraftBukkit - EntityExhaustionEvent + entityhuman.causeFoodExhaustion(entity.level().purpurConfig.humanHungerExhaustionAmount * (float) (amplifier + 1), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.HUNGER_EFFECT); // CraftBukkit - EntityExhaustionEvent // Purpur @@ -2075,27 +2079,27 @@ index a476b56ed98d0a1afc6a396ce29424df78f24ada..5119ff3414fbd9a1ae0a8db0fd15bd3c return true; diff --git a/src/main/java/net/minecraft/world/effect/PoisonMobEffect.java b/src/main/java/net/minecraft/world/effect/PoisonMobEffect.java -index 3e7a703632251e0a5234259e3702b58b332e5ef0..f2cc43fbccb5d2ba012b350268065c2cfe014faf 100644 +index 83c6d17f75c3f0b531bdfd5b5f9bc2a5b3eb7a2c..df43c007e7b9fee58b2cd0892b966ce88cb1f890 100644 --- a/src/main/java/net/minecraft/world/effect/PoisonMobEffect.java +++ b/src/main/java/net/minecraft/world/effect/PoisonMobEffect.java -@@ -10,8 +10,8 @@ class PoisonMobEffect extends MobEffect { +@@ -11,8 +11,8 @@ class PoisonMobEffect extends MobEffect { @Override - public boolean applyEffectTick(LivingEntity entity, int amplifier) { + public boolean applyEffectTick(ServerLevel world, LivingEntity entity, int amplifier) { - if (entity.getHealth() > 1.0F) { -- entity.hurt(entity.damageSources().poison(), 1.0F); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON +- entity.hurtServer(world, entity.damageSources().poison(), 1.0F); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON + if (entity.getHealth() > entity.level().purpurConfig.entityMinimalHealthPoison) { // Purpur -+ entity.hurt(entity.damageSources().poison(), entity.level().purpurConfig.entityPoisonDegenerationAmount); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON // Purpur ++ entity.hurtServer(world, entity.damageSources().poison(), entity.level().purpurConfig.entityPoisonDegenerationAmount); // CraftBukkit - DamageSource.MAGIC -> CraftEventFactory.POISON // Purpur } return true; diff --git a/src/main/java/net/minecraft/world/effect/RegenerationMobEffect.java b/src/main/java/net/minecraft/world/effect/RegenerationMobEffect.java -index 4dba3e813e054951cbfbe0b323c1f5d973469cc0..426f61d55b9692cf085368df4e4df6f6997aa420 100644 +index b43e573e91d1f1b407774bb2d60ee5f099f171e7..25aa932fc03eeebc5aabca6c5eae0cbfc8ad8396 100644 --- a/src/main/java/net/minecraft/world/effect/RegenerationMobEffect.java +++ b/src/main/java/net/minecraft/world/effect/RegenerationMobEffect.java -@@ -11,7 +11,7 @@ class RegenerationMobEffect extends MobEffect { +@@ -12,7 +12,7 @@ class RegenerationMobEffect extends MobEffect { @Override - public boolean applyEffectTick(LivingEntity entity, int amplifier) { + public boolean applyEffectTick(ServerLevel world, LivingEntity entity, int amplifier) { if (entity.getHealth() < entity.getMaxHealth()) { - entity.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC_REGEN); // CraftBukkit + entity.heal(entity.level().purpurConfig.entityHealthRegenAmount, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC_REGEN); // CraftBukkit // Purpur @@ -2103,53 +2107,54 @@ index 4dba3e813e054951cbfbe0b323c1f5d973469cc0..426f61d55b9692cf085368df4e4df6f6 return true; diff --git a/src/main/java/net/minecraft/world/effect/SaturationMobEffect.java b/src/main/java/net/minecraft/world/effect/SaturationMobEffect.java -index 7b415dca88f50dc472fe4be96e5ef0996f117913..2bb872f29350d15db46b32c686aef78fc1b6fa29 100644 +index 98b74649a667fb9b10afef0ba5383a73022d8c71..0c7c0524e487ff32e16dd9939d92bc6441602747 100644 --- a/src/main/java/net/minecraft/world/effect/SaturationMobEffect.java +++ b/src/main/java/net/minecraft/world/effect/SaturationMobEffect.java -@@ -20,7 +20,7 @@ class SaturationMobEffect extends InstantenousMobEffect { +@@ -21,7 +21,8 @@ class SaturationMobEffect extends InstantenousMobEffect { int oldFoodLevel = entityhuman.getFoodData().foodLevel; org.bukkit.event.entity.FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(entityhuman, amplifier + 1 + oldFoodLevel); if (!event.isCancelled()) { - entityhuman.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 1.0F); ++ if (entityhuman.level().purpurConfig.playerBurpWhenFull && event.getFoodLevel() == 20 && oldFoodLevel < 20) entityhuman.burpDelay = entityhuman.level().purpurConfig.playerBurpDelay; // Purpur + entityhuman.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, entity.level().purpurConfig.humanSaturationRegenAmount); // Purpur } ((CraftPlayer) entityhuman.getBukkitEntity()).sendHealthUpdate(); diff --git a/src/main/java/net/minecraft/world/effect/WitherMobEffect.java b/src/main/java/net/minecraft/world/effect/WitherMobEffect.java -index f43bf280999ff3860cc702def50cc62b131eb1bd..66d9e99a351f5fc6cf58be3bee4397d92c932d64 100644 +index 303cefba51e19ac43b1f6188ad64ef480715ebaf..98ec88751b3e71c2e7aad633096b7f41608c0b33 100644 --- a/src/main/java/net/minecraft/world/effect/WitherMobEffect.java +++ b/src/main/java/net/minecraft/world/effect/WitherMobEffect.java -@@ -9,7 +9,7 @@ class WitherMobEffect extends MobEffect { +@@ -10,7 +10,7 @@ class WitherMobEffect extends MobEffect { @Override - public boolean applyEffectTick(LivingEntity entity, int amplifier) { -- entity.hurt(entity.damageSources().wither(), 1.0F); -+ entity.hurt(entity.damageSources().wither(), entity.level().purpurConfig.entityWitherDegenerationAmount); // Purpur + public boolean applyEffectTick(ServerLevel world, LivingEntity entity, int amplifier) { +- entity.hurtServer(world, entity.damageSources().wither(), 1.0F); ++ entity.hurtServer(world, entity.damageSources().wither(), entity.level().purpurConfig.entityWitherDegenerationAmount); // Purpur return true; } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956eac8b7e73 100644 +index e9438f3b2acabcb9d3ecd6484704db1a94b21a0e..68f94543395c143234957cd5e33600a0c4b1c87d 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -168,7 +168,7 @@ import org.bukkit.plugin.PluginManager; +@@ -175,7 +175,7 @@ import org.bukkit.plugin.PluginManager; // CraftBukkit end - public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, CommandSource, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker + public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, ScoreHolder, ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity, ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity { // Paper - rewrite chunk system // Paper - optimise entity tracker - + public static javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); // Purpur // CraftBukkit start private static final int CURRENT_LEVEL = 2; public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first setPositionRotation -@@ -344,6 +344,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -299,6 +299,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public double xOld; public double yOld; public double zOld; + public float maxUpStep; // Purpur public boolean noPhysics; + private boolean wasOnFire; public final RandomSource random; - public int tickCount; -@@ -384,7 +385,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -339,7 +340,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess private final Set tags; private final double[] pistonDeltas; private long pistonDeltasGameTime; @@ -2158,15 +2163,15 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e private float eyeHeight; public boolean isInPowderSnow; public boolean wasInPowderSnow; -@@ -432,6 +433,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - public boolean fixedPose = false; // Paper - Expand Pose API +@@ -390,6 +391,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + private final int despawnTime; // Paper - entity despawn time limit public boolean activatedPriorityReset = false; // Pufferfish - DAB public int activatedPriority = org.dreeam.leaf.config.modules.opt.DynamicActivationofBrain.maximumActivationPrio; // Pufferfish - DAB (golf score) + public @Nullable Boolean immuneToFire = null; // Purpur - Fire immune API public void setOrigin(@javax.annotation.Nonnull Location location) { this.origin = location.toVector(); -@@ -553,6 +555,27 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -570,6 +572,27 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } // Paper end - optimise entity tracker @@ -2194,7 +2199,7 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e public Entity(EntityType type, Level world) { this.id = Entity.ENTITY_COUNTER.incrementAndGet(); -@@ -561,7 +584,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -579,7 +602,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.bb = Entity.INITIAL_AABB; this.stuckSpeedMultiplier = Vec3.ZERO; this.nextStep = 1.0F; @@ -2203,7 +2208,7 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e this.remainingFireTicks = -this.getFireImmuneTicks(); this.fluidHeight = new Object2DoubleArrayMap(2); this.fluidOnEyes = new HashSet(); -@@ -951,6 +974,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -977,6 +1000,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess && this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> this.getY() >= v) && (!(this instanceof Player player) || !player.getAbilities().invulnerable))) { // Paper end - Configurable nether ceiling damage @@ -2211,7 +2216,7 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e this.onBelowWorld(); } -@@ -1869,7 +1893,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1943,7 +1967,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public boolean fireImmune() { @@ -2220,7 +2225,7 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e } public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) { -@@ -1942,7 +1966,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2016,7 +2040,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return this.isInWater() || flag; } @@ -2228,8 +2233,8 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e + public void updateInWaterStateAndDoWaterCurrentPushing() { // Purpur - package-private -> public Entity entity = this.getVehicle(); - if (entity instanceof Boat entityboat) { -@@ -2588,6 +2612,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + if (entity instanceof AbstractBoat abstractboat) { +@@ -2708,6 +2732,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess nbttagcompound.putBoolean("Paper.FreezeLock", true); } // Paper end @@ -2241,7 +2246,7 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e return nbttagcompound; } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); -@@ -2735,6 +2764,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2856,6 +2885,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess freezeLocked = nbt.getBoolean("Paper.FreezeLock"); } // Paper end @@ -2253,7 +2258,7 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); -@@ -2953,6 +2987,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3107,6 +3141,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess if (this.isAlive() && this instanceof Leashable leashable) { if (leashable.getLeashHolder() == player) { if (!this.level().isClientSide()) { @@ -2261,7 +2266,7 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e // CraftBukkit start - fire PlayerUnleashEntityEvent // Paper start - Expand EntityUnleashEvent org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand, !player.hasInfiniteMaterials()); -@@ -3156,6 +3191,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3312,6 +3347,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.passengers = ImmutableList.copyOf(list); } @@ -2275,7 +2280,7 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e this.gameEvent(GameEvent.ENTITY_MOUNT, passenger); } } -@@ -3195,6 +3237,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3351,6 +3393,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return false; } // CraftBukkit end @@ -2290,7 +2295,7 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e if (this.passengers.size() == 1 && this.passengers.get(0) == entity) { this.passengers = ImmutableList.of(); } else { -@@ -3273,13 +3323,16 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3431,14 +3481,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return Vec3.directionFromRotation(this.getRotationVector()); } @@ -2302,13 +2307,14 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e - } else { + } else if (this.level.purpurConfig.entitiesCanUsePortals || this instanceof ServerPlayer) { // Purpur - Entities can use portals if (this.portalProcess != null && this.portalProcess.isSamePortal(portal)) { - this.portalProcess.updateEntryPosition(pos.immutable()); - this.portalProcess.setAsInsidePortalThisTick(true); -+ this.portalPos = BlockPos.ZERO; // Purpur - Fix stuck in portals + if (!this.portalProcess.isInsidePortalThisTick()) { + this.portalProcess.updateEntryPosition(pos.immutable()); + this.portalProcess.setAsInsidePortalThisTick(true); ++ this.portalPos = BlockPos.ZERO; // Purpur - Fix stuck in portals + } } else { this.portalProcess = new PortalProcessor(portal, pos.immutable()); - } -@@ -3487,7 +3540,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3650,7 +3703,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public int getMaxAirSupply() { @@ -2317,7 +2323,7 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e } public int getAirSupply() { -@@ -3897,7 +3950,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4139,7 +4192,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // CraftBukkit end public boolean canUsePortal(boolean allowVehicles) { @@ -2325,29 +2331,8 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e + return (allowVehicles || !this.isPassenger()) && this.isAlive() && (this.level.purpurConfig.entitiesCanUsePortals || this instanceof ServerPlayer); // Purpur - Entities can use portals } - public boolean canChangeDimensions(Level from, Level to) { -@@ -4219,6 +4272,20 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - return SlotAccess.NULL; - } - -+ // Purpur Start -+ public void sendMiniMessage(@Nullable String message) { -+ if (message != null && !message.isEmpty()) { -+ this.sendMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message)); -+ } -+ } -+ -+ public void sendMessage(@Nullable net.kyori.adventure.text.Component message) { -+ if (message != null) { -+ this.sendSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message)); -+ } -+ } -+ // Purpur end -+ - @Override - public void sendSystemMessage(Component message) {} - -@@ -4490,6 +4557,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + public boolean canTeleport(Level from, Level to) { +@@ -4732,6 +4785,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return Mth.lerp(delta, this.yRotO, this.yRot); } @@ -2357,10 +2342,10 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e + } + // Purpur end + - public boolean updateFluidHeightAndDoFluidPushing(TagKey tag, double speed) { - if (false && this.touchingUnloadedChunk()) { // Gale - Airplane - reduce entity fluid lookups if no fluids - cost of a lookup here is the same cost as below, so skip - return false; -@@ -4901,7 +4974,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + // Paper start - optimise collisions + public boolean updateFluidHeightAndDoFluidPushing(final TagKey fluid, final double flowScale) { + if (this.touchingUnloadedChunk()) { +@@ -5143,7 +5202,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public float maxUpStep() { @@ -2369,8 +2354,8 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e } public void onExplosionHit(@Nullable Entity entity) {} -@@ -5093,4 +5166,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - return ((net.minecraft.server.level.ServerChunkCache) level.getChunkSource()).isPositionTicking(this); +@@ -5344,4 +5403,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + return ((net.minecraft.server.level.ServerLevel) this.level).isPositionEntityTicking(this.blockPosition()); } // Paper end - Expose entity id counter + // Purpur start @@ -2415,10 +2400,10 @@ index 60fbed7a31fbeca07eae8ea6b0fb97705961bb7e..b652bfd4aea7eca7eebc0265a518956e + // Purpur end } diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java -index dca7b99e97f21bf6cfae6ee69eeac95d0bcf6863..4830ebddade00f62287bcc9d7b17be83c0ad3a56 100644 +index 6bf691fcc6486bde73bae30eff09142802c29eda..59c4d3753c7084e92402608b7fb3c4adbc6c2f65 100644 --- a/src/main/java/net/minecraft/world/entity/EntitySelector.java +++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java -@@ -40,6 +40,7 @@ public final class EntitySelector { +@@ -39,6 +39,7 @@ public final class EntitySelector { return net.minecraft.util.Mth.clamp(serverPlayer.getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= playerInsomniaTicks; }; // Paper end - Ability to control player's insomnia and phantoms @@ -2427,21 +2412,21 @@ index dca7b99e97f21bf6cfae6ee69eeac95d0bcf6863..4830ebddade00f62287bcc9d7b17be83 private EntitySelector() {} // Paper start - Affects Spawning API diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index f9440014ab2fe753c16b9383f5fffbb8adb76e79..d3de0362dd1ef3954d05c4d8fa56a25edfe1bb2b 100644 +index 24eaa9a2e6f0cf198a307058e655d5eb16a2c8c5..002795df9c9c8d27f07f855dff148dfe353bef68 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -324,7 +324,8 @@ public class EntityType implements FeatureElement, EntityTypeT - private Component description; +@@ -389,7 +389,8 @@ public class EntityType implements FeatureElement, EntityTypeT @Nullable - private ResourceKey lootTable; + private Component description; + private final Optional> lootTable; - private final EntityDimensions dimensions; + private EntityDimensions dimensions; // Purpur - remove final + public void setDimensions(EntityDimensions dimensions) { this.dimensions = dimensions; } // Purpur private final float spawnDimensionsScale; private final FeatureFlagSet requiredFeatures; -@@ -332,6 +333,16 @@ public class EntityType implements FeatureElement, EntityTypeT - return (EntityType) Registry.register(BuiltInRegistries.ENTITY_TYPE, id, (EntityType) type.build(id)); // CraftBukkit - decompile error +@@ -405,6 +406,16 @@ public class EntityType implements FeatureElement, EntityTypeT + return EntityType.register(EntityType.vanillaEntityId(id), type); } + // Purpur start @@ -2450,14 +2435,14 @@ index f9440014ab2fe753c16b9383f5fffbb8adb76e79..d3de0362dd1ef3954d05c4d8fa56a25e + } + + public static EntityType getFromKey(ResourceLocation location) { -+ return BuiltInRegistries.ENTITY_TYPE.get(location); ++ return BuiltInRegistries.ENTITY_TYPE.getValue(location); + } + // Purpur end + public static ResourceLocation getKey(EntityType type) { return BuiltInRegistries.ENTITY_TYPE.getKey(type); } -@@ -539,6 +550,16 @@ public class EntityType implements FeatureElement, EntityTypeT +@@ -605,6 +616,16 @@ public class EntityType implements FeatureElement, EntityTypeT return this.category; } @@ -2472,9 +2457,9 @@ index f9440014ab2fe753c16b9383f5fffbb8adb76e79..d3de0362dd1ef3954d05c4d8fa56a25e + // Purpur end + public String getDescriptionId() { - if (this.descriptionId == null) { - this.descriptionId = Util.makeDescriptionId("entity", BuiltInRegistries.ENTITY_TYPE.getKey(this)); -@@ -606,6 +627,12 @@ public class EntityType implements FeatureElement, EntityTypeT + return this.descriptionId; + } +@@ -662,6 +683,12 @@ public class EntityType implements FeatureElement, EntityTypeT entity.load(nbt); }, () -> { EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id")); @@ -2488,10 +2473,10 @@ index f9440014ab2fe753c16b9383f5fffbb8adb76e79..d3de0362dd1ef3954d05c4d8fa56a25e } diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -index a58ff67052fb5f33782f8b5c83465ec03ef1d073..1cdf71a76c629bcc42da7fcc451b7031dbe644bd 100644 +index bf0838f574fa3fb9654e087d602b8d380bd7fb28..32a0db7e8f974712bd8a05f16f3bd48ac66142d5 100644 --- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java -@@ -329,7 +329,7 @@ public class ExperienceOrb extends Entity { +@@ -333,7 +333,7 @@ public class ExperienceOrb extends Entity { public void playerTouch(Player player) { if (player instanceof ServerPlayer entityplayer) { if (player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(entityplayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent @@ -2500,7 +2485,7 @@ index a58ff67052fb5f33782f8b5c83465ec03ef1d073..1cdf71a76c629bcc42da7fcc451b7031 player.take(this, 1); int i = this.repairPlayerItems(entityplayer, this.value); -@@ -347,7 +347,7 @@ public class ExperienceOrb extends Entity { +@@ -351,7 +351,7 @@ public class ExperienceOrb extends Entity { } private int repairPlayerItems(ServerPlayer player, int amount) { @@ -2510,10 +2495,10 @@ index a58ff67052fb5f33782f8b5c83465ec03ef1d073..1cdf71a76c629bcc42da7fcc451b7031 if (optional.isPresent()) { ItemStack itemstack = ((EnchantedItemInUse) optional.get()).itemStack(); diff --git a/src/main/java/net/minecraft/world/entity/GlowSquid.java b/src/main/java/net/minecraft/world/entity/GlowSquid.java -index 09fdea983772612ef3fff6b2da3cf469a34e4ec0..3e2ea26c23e88c395856b65001f2895db6a52bd4 100644 +index b851c3ee1426bc0a259bf6c4a662af0c9883dd71..3283228d7ebf98ce98780725a0a412bea4200da5 100644 --- a/src/main/java/net/minecraft/world/entity/GlowSquid.java +++ b/src/main/java/net/minecraft/world/entity/GlowSquid.java -@@ -23,6 +23,39 @@ public class GlowSquid extends Squid { +@@ -25,6 +25,39 @@ public class GlowSquid extends Squid { super(type, world); } @@ -2554,10 +2539,10 @@ index 09fdea983772612ef3fff6b2da3cf469a34e4ec0..3e2ea26c23e88c395856b65001f2895d protected ParticleOptions getInkParticle() { return ParticleTypes.GLOW_SQUID_INK; diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16b3092450 100644 +index 167d164d07285bfff6eb8076d7abe17ca9543df9..260e9b0398ddaacacfe5de352ac686ef273a6167 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -237,9 +237,9 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -246,9 +246,9 @@ public abstract class LivingEntity extends Entity implements Attackable { protected int deathScore; public float lastHurt; public boolean jumping; @@ -2570,7 +2555,7 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 protected int lerpSteps; protected double lerpX; protected double lerpY; -@@ -286,6 +286,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -295,6 +295,7 @@ public abstract class LivingEntity extends Entity implements Attackable { public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API @@ -2578,9 +2563,9 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 @Override public float getBukkitYaw() { -@@ -313,7 +314,8 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -323,7 +324,8 @@ public abstract class LivingEntity extends Entity implements Attackable { this.lastClimbablePos = Optional.empty(); - this.activeLocationDependentEnchantments = new Reference2ObjectArrayMap(); + this.activeLocationDependentEnchantments = new EnumMap(EquipmentSlot.class); this.appliedScale = 1.0F; - this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type)); + this.attributes = new AttributeMap(DefaultAttributes.getSupplier(type), this); // Purpur @@ -2588,7 +2573,7 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 this.craftAttributes = new CraftAttributeMap(this.attributes); // CraftBukkit // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor this.entityData.set(LivingEntity.DATA_HEALTH_ID, (float) this.getAttribute(Attributes.MAX_HEALTH).getValue()); -@@ -328,6 +330,8 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -338,6 +340,8 @@ public abstract class LivingEntity extends Entity implements Attackable { this.brain = this.makeBrain(new Dynamic(dynamicopsnbt, (Tag) dynamicopsnbt.createMap((Map) ImmutableMap.of(dynamicopsnbt.createString("memories"), (Tag) dynamicopsnbt.emptyMap())))); } @@ -2597,7 +2582,7 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 public Brain getBrain() { return this.brain; } -@@ -363,6 +367,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -373,6 +377,7 @@ public abstract class LivingEntity extends Entity implements Attackable { public static AttributeSupplier.Builder createLivingAttributes() { return AttributeSupplier.builder().add(Attributes.MAX_HEALTH).add(Attributes.KNOCKBACK_RESISTANCE).add(Attributes.MOVEMENT_SPEED).add(Attributes.ARMOR).add(Attributes.ARMOR_TOUGHNESS).add(Attributes.MAX_ABSORPTION).add(Attributes.STEP_HEIGHT).add(Attributes.SCALE).add(Attributes.GRAVITY).add(Attributes.SAFE_FALL_DISTANCE).add(Attributes.FALL_DAMAGE_MULTIPLIER).add(Attributes.JUMP_STRENGTH).add(Attributes.OXYGEN_BONUS).add(Attributes.BURNING_TIME).add(Attributes.EXPLOSION_KNOCKBACK_RESISTANCE).add(Attributes.WATER_MOVEMENT_EFFICIENCY).add(Attributes.MOVEMENT_EFFICIENCY).add(Attributes.ATTACK_KNOCKBACK); } @@ -2605,15 +2590,15 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 @Override protected void checkFallDamage(double heightDifference, boolean onGround, BlockState state, BlockPos landedPosition) { -@@ -460,6 +465,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - double d1 = this.level().getWorldBorder().getDamagePerBlock(); - - if (d1 > 0.0D) { +@@ -474,6 +479,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + if (d1 < 0.0D) { + d0 = this.level().getWorldBorder().getDamagePerBlock(); + if (d0 > 0.0D) { + if (level().purpurConfig.teleportIfOutsideBorder && this instanceof ServerPlayer serverPlayer) { serverPlayer.teleport(io.papermc.paper.util.MCUtil.toLocation(level(), ((ServerLevel) level()).getSharedSpawnPos())); return; } // Purpur - this.hurt(this.damageSources().outOfBorder(), (float) Math.max(1, Mth.floor(-d0 * d1))); + this.hurtServer(worldserver1, this.damageSources().outOfBorder(), (float) Math.max(1, Mth.floor(-d1 * d0))); } } -@@ -471,7 +477,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -485,7 +491,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (flag1) { this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); @@ -2622,8 +2607,8 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 this.setAirSupply(0); Vec3 vec3d = this.getDeltaMovement(); -@@ -483,7 +489,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.level().addParticle(ParticleTypes.BUBBLE, this.getX() + d2, this.getY() + d3, this.getZ() + d4, vec3d.x, vec3d.y, vec3d.z); +@@ -497,7 +503,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + this.level().addParticle(ParticleTypes.BUBBLE, this.getX() + d0, this.getY() + d2, this.getZ() + d3, vec3d.x, vec3d.y, vec3d.z); } - this.hurt(this.damageSources().drown(), 2.0F); @@ -2631,7 +2616,7 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 } } -@@ -811,6 +817,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -830,6 +836,7 @@ public abstract class LivingEntity extends Entity implements Attackable { dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { nbt.put("Brain", nbtbase); }); @@ -2639,7 +2624,7 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 } @Override -@@ -899,6 +906,11 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -918,6 +925,11 @@ public abstract class LivingEntity extends Entity implements Attackable { this.brain = this.makeBrain(new Dynamic(NbtOps.INSTANCE, nbt.get("Brain"))); } @@ -2651,7 +2636,7 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 } // CraftBukkit start -@@ -1033,9 +1045,28 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1052,9 +1064,29 @@ public abstract class LivingEntity extends Entity implements Attackable { if (entity != null) { EntityType entitytypes = entity.getType(); @@ -2662,7 +2647,8 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 + d0 *= entity.level().purpurConfig.skeletonHeadVisibilityPercent; + } else if (entitytypes == EntityType.ZOMBIE && itemstack.is(Items.ZOMBIE_HEAD)) { + d0 *= entity.level().purpurConfig.zombieHeadVisibilityPercent; -+ } else if (entitytypes == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) { ++ } ++ else if (entitytypes == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) { + d0 *= entity.level().purpurConfig.creeperHeadVisibilityPercent; + } else if ((entitytypes == EntityType.PIGLIN || entitytypes == EntityType.PIGLIN_BRUTE) && itemstack.is(Items.PIGLIN_HEAD)) { + d0 *= entity.level().purpurConfig.piglinHeadVisibilityPercent; @@ -2682,15 +2668,15 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 } return d0; -@@ -1094,6 +1125,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - for (flag = false; iterator.hasNext(); flag = true) { - // CraftBukkit start - MobEffectInstance effect = (MobEffectInstance) iterator.next(); +@@ -1110,6 +1142,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + + while (iterator.hasNext()) { + MobEffectInstance effect = iterator.next(); + if (cause == EntityPotionEffectEvent.Cause.MILK && !this.level().purpurConfig.milkClearsBeneficialEffects && effect.getEffect().value().isBeneficial()) continue; // Purpur EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED); if (event.isCancelled()) { continue; -@@ -1431,6 +1463,24 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1454,6 +1487,24 @@ public abstract class LivingEntity extends Entity implements Attackable { this.stopSleeping(); } @@ -2713,9 +2699,9 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 + // Purpur end + this.noActionTime = 0; - float f1 = amount; final float originalAmount = f1; // Paper - revert to vanilla #hurt - OBFHELPER - boolean flag = amount > 0.0F && this.isDamageSourceBlocked(source); // Copied from below -@@ -1522,13 +1572,13 @@ public abstract class LivingEntity extends Entity implements Attackable { + if (amount < 0.0F) { + amount = 0.0F; +@@ -1553,13 +1604,13 @@ public abstract class LivingEntity extends Entity implements Attackable { if (entity1 instanceof net.minecraft.world.entity.player.Player) { net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) entity1; @@ -2731,7 +2717,7 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 LivingEntity entityliving2 = entitywolf.getOwner(); if (entityliving2 instanceof net.minecraft.world.entity.player.Player) { -@@ -1669,6 +1719,18 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1706,6 +1757,18 @@ public abstract class LivingEntity extends Entity implements Attackable { } } @@ -2750,26 +2736,24 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null; EntityResurrectEvent event = new EntityResurrectEvent((org.bukkit.entity.LivingEntity) this.getBukkitEntity(), handSlot); event.setCancelled(itemstack == null); -@@ -1835,7 +1897,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1877,7 +1940,7 @@ public abstract class LivingEntity extends Entity implements Attackable { boolean flag = false; if (this.dead && adversary instanceof WitherBoss) { // Paper -- if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ if (this.level().purpurConfig.witherBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur +- if (worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (worldserver.purpurConfig.witherBypassMobGriefing ^ worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur BlockPos blockposition = this.blockPosition(); BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); -@@ -1871,7 +1933,8 @@ public abstract class LivingEntity extends Entity implements Attackable { - boolean flag = this.lastHurtByPlayerTime > 0; +@@ -1914,6 +1977,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.dropEquipment(); // CraftBukkit - from below -- if (this.shouldDropLoot() && world.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { -+ if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + this.dropEquipment(world); // CraftBukkit - from below + if (this.shouldDropLoot() && world.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + if (!(damageSource.is(net.minecraft.world.damagesource.DamageTypes.CRAMMING) && level().purpurConfig.disableDropsOnCrammingDeath)) { // Purpur - this.dropFromLootTable(damageSource, flag); + this.dropFromLootTable(world, damageSource, flag); // Paper start final boolean prev = this.clearEquipmentSlots; -@@ -1880,6 +1943,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1922,6 +1986,7 @@ public abstract class LivingEntity extends Entity implements Attackable { // Paper end this.dropCustomDeathLoot(world, damageSource, flag); this.clearEquipmentSlots = prev; // Paper @@ -2777,17 +2761,17 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 } // CraftBukkit start - Call death event // Paper start - call advancement triggers with correct entity equipment org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, damageSource, this.drops, () -> { -@@ -3028,6 +3092,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - - if (f3 > 0.0F) { - this.playSound(this.getFallDamageSound((int) f3), 1.0F, 1.0F); -+ if (level().purpurConfig.elytraKineticDamage) // Purpur - this.hurt(this.damageSources().flyIntoWall(), f3); - } - } -@@ -3582,8 +3647,10 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3188,6 +3253,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + if (f > 0.0F) { + this.playSound(this.getFallDamageSound((int) f), 1.0F, 1.0F); ++ if (level().purpurConfig.elytraKineticDamage) // Purpur + this.hurt(this.damageSources().flyIntoWall(), f); + } + } +@@ -3717,8 +3783,10 @@ public abstract class LivingEntity extends Entity implements Attackable { this.pushEntities(); + // Paper start - Add EntityMoveEvent - if (((ServerLevel) this.level()).hasEntityMoveEvent && !(this instanceof net.minecraft.world.entity.player.Player)) { - if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) { @@ -2798,7 +2782,7 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 Location from = new Location(this.level().getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO); Location to = new Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); io.papermc.paper.event.entity.EntityMoveEvent event = new io.papermc.paper.event.entity.EntityMoveEvent(this.getBukkitLivingEntity(), from, to.clone()); -@@ -3593,12 +3660,55 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3728,6 +3796,21 @@ public abstract class LivingEntity extends Entity implements Attackable { this.absMoveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); } } @@ -2819,8 +2803,9 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 + // Purpur end } // Paper end - Add EntityMoveEvent - if (!this.level().isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { - this.hurt(this.damageSources().drown(), 1.0F); + world = this.level(); +@@ -3737,6 +3820,34 @@ public abstract class LivingEntity extends Entity implements Attackable { + } } + // Purpur start - copied from Zombie - API for any mob to burn daylight @@ -2854,26 +2839,45 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 } public boolean isSensitiveToWater() { -@@ -3619,7 +3729,16 @@ public abstract class LivingEntity extends Entity implements Attackable { - int j = i / 10; +@@ -3763,7 +3874,17 @@ public abstract class LivingEntity extends Entity implements Attackable { + }).toList(); + EquipmentSlot enumitemslot = (EquipmentSlot) Util.getRandom(list, this.random); - if (j % 2 == 0) { -- itemstack.hurtAndBreak(1, this, EquipmentSlot.CHEST); -+ // Purpur start -+ int damage = level().purpurConfig.elytraDamagePerSecond; -+ if (level().purpurConfig.elytraDamageMultiplyBySpeed > 0) { -+ double speed = getDeltaMovement().lengthSqr(); -+ if (speed > level().purpurConfig.elytraDamageMultiplyBySpeed) { -+ damage *= (int) speed; -+ } +- this.getItemBySlot(enumitemslot).hurtAndBreak(1, this, enumitemslot); ++ // Purpur start ++ int damage = level().purpurConfig.elytraDamagePerSecond; ++ if (level().purpurConfig.elytraDamageMultiplyBySpeed > 0) { ++ double speed = getDeltaMovement().lengthSqr(); ++ if (speed > level().purpurConfig.elytraDamageMultiplyBySpeed) { ++ damage *= (int) speed; + } -+ itemstack.hurtAndBreak(damage, this, EquipmentSlot.CHEST); -+ // Purpur end - } ++ } ++ ++ this.getItemBySlot(enumitemslot).hurtAndBreak(damage, this, enumitemslot); ++ // Purpur end + } + + this.gameEvent(GameEvent.ELYTRA_GLIDE); +@@ -3772,7 +3893,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.gameEvent(GameEvent.ELYTRA_GLIDE); -@@ -4579,6 +4698,12 @@ public abstract class LivingEntity extends Entity implements Attackable { - return EquipmentSlot.MAINHAND; + } + +- protected boolean canGlide() { ++ public boolean canGlide() { // Purpur + if (!this.onGround() && !this.isPassenger() && !this.hasEffect(MobEffects.LEVITATION)) { + Iterator iterator = EquipmentSlot.VALUES.iterator(); + +@@ -4694,7 +4815,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + if (equippable != null && equippable.dispensable()) { + EquipmentSlot enumitemslot = equippable.slot(); + +- return this.canUseSlot(enumitemslot) && equippable.canBeEquippedBy(this.getType()) ? this.getItemBySlot(enumitemslot).isEmpty() && this.canDispenserEquipIntoSlot(enumitemslot) : false; ++ return this.canUseSlot(enumitemslot) && equippable.canBeEquippedBy(this.getType()) && this.getItemBySlot(enumitemslot).isEmpty() && this.canDispenserEquipIntoSlot(enumitemslot); + } else { + return false; + } +@@ -4719,6 +4840,12 @@ public abstract class LivingEntity extends Entity implements Attackable { + return equippable == null ? slot == EquipmentSlot.MAINHAND && this.canUseSlot(EquipmentSlot.MAINHAND) : slot == equippable.slot() && this.canUseSlot(equippable.slot()) && equippable.canBeEquippedBy(this.getType()); } + // Purpur start - Dispenser curse of binding protection @@ -2886,10 +2890,10 @@ index 914c5bbcd088d0f7fd5626310cdbcd163565143a..92b0e53ca1e154dde919502a99e82b16 return slot != EquipmentSlot.HEAD && slot != EquipmentSlot.MAINHAND && slot != EquipmentSlot.OFFHAND ? SlotAccess.forEquipmentSlot(entity, slot, (itemstack) -> { return itemstack.isEmpty() || entity.getEquipmentSlotForItem(itemstack) == slot; diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311f2ff3ebd 100644 +index 45c6001811a45f989464c7d5bb27f1362f6a84de..dfae42ed76d11438ac79d083c82914c60f0e606e 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -145,6 +145,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -146,6 +146,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab private BlockPos restrictCenter; private float restrictRadius; @@ -2898,9 +2902,9 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 protected Mob(EntityType type, Level world) { @@ -161,8 +162,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + this.restrictRadius = -1.0F; this.goalSelector = new GoalSelector(); this.targetSelector = new GoalSelector(); - // Gale end - Purpur - remove vanilla profiler - this.lookControl = new LookControl(this); - this.moveControl = new MoveControl(this); + this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this); // Purpur @@ -2916,7 +2920,7 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 this.target = entityliving; return true; // CraftBukkit end -@@ -373,8 +375,29 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -374,8 +376,29 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab this.resetAmbientSoundTime(); this.playAmbientSound(); } @@ -2946,7 +2950,7 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 @Override protected void playHurtSound(DamageSource damageSource) { this.resetAmbientSoundTime(); -@@ -549,6 +572,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -543,6 +566,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab } nbt.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit @@ -2954,7 +2958,7 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 } @Override -@@ -626,6 +650,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -620,6 +644,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab this.aware = nbt.getBoolean("Bukkit.Aware"); } // CraftBukkit end @@ -2966,16 +2970,16 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 } @Override -@@ -676,7 +705,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab - @Override - public void aiStep() { - super.aiStep(); -- if (!this.level().isClientSide && this.canPickUpLoot() && this.isAlive() && !this.dead && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ if (!this.level().isClientSide && this.canPickUpLoot() && this.isAlive() && !this.dead && (this.level().purpurConfig.entitiesPickUpLootBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { - Vec3i baseblockposition = this.getPickupReach(); - List list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate((double) baseblockposition.getX(), (double) baseblockposition.getY(), (double) baseblockposition.getZ())); - Iterator iterator = list.iterator(); -@@ -1387,7 +1416,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -670,7 +699,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + Level world = this.level(); + + if (world instanceof ServerLevel worldserver) { +- if (this.canPickUpLoot() && this.isAlive() && !this.dead && worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (this.canPickUpLoot() && this.isAlive() && !this.dead && (worldserver.purpurConfig.entitiesPickUpLootBypassMobGriefing ^ worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // Purpur + Vec3i baseblockposition = this.getPickupReach(); + List list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate((double) baseblockposition.getX(), (double) baseblockposition.getY(), (double) baseblockposition.getZ())); + Iterator iterator = list.iterator(); +@@ -1370,7 +1399,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab attributemodifiable.addPermanentModifier(new AttributeModifier(Mob.RANDOM_SPAWN_BONUS_ID, randomsource.triangle(0.0D, 0.11485000000000001D), AttributeModifier.Operation.ADD_MULTIPLIED_BASE)); } @@ -2984,7 +2988,7 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 return entityData; } -@@ -1488,7 +1517,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1472,7 +1501,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab protected void onOffspringSpawnedFromEgg(Player player, Mob child) {} protected InteractionResult mobInteract(Player player, InteractionHand hand) { @@ -2993,7 +2997,7 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 } public boolean isWithinRestriction() { -@@ -1727,6 +1756,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1711,6 +1740,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab this.playAttackSound(); } @@ -3001,7 +3005,7 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 return flag; } -@@ -1738,28 +1768,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1722,28 +1752,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab // Gale end - JettPack - optimize sun burn tick - cache eye blockpos public boolean isSunBurnTick() { @@ -3032,9 +3036,9 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 } @Override -@@ -1802,4 +1812,56 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab - - return itemmonsteregg == null ? null : new ItemStack(itemmonsteregg); +@@ -1805,4 +1815,58 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + public float[] getArmorDropChances() { + return this.armorDropChances; } + + // Purpur start @@ -3076,7 +3080,9 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 + } + } + if (!player.getBukkitEntity().hasPermission("allow.ride." + net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.getKey(getType()).getPath())) { -+ player.sendMiniMessage(org.purpurmc.purpur.PurpurConfig.cannotRideMob); ++ if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) { ++ serverPlayer.sendMiniMessage(org.purpurmc.purpur.PurpurConfig.cannotRideMob); ++ } + return InteractionResult.PASS; + } + player.setYRot(this.getYRot()); @@ -3089,24 +3095,11 @@ index aa6d06c5b873ae92d7de6c091a8b9d27221ef7f8..78745bc7373c36a871ed9672b7fb4311 + } + // Purpur end } -diff --git a/src/main/java/net/minecraft/world/entity/Shearable.java b/src/main/java/net/minecraft/world/entity/Shearable.java -index 2ee48ac3b665db2b02bcb1a30ec972d43a3725b0..59e8f5431ce5026209e1428b5fa5b5485dcfebc7 100644 ---- a/src/main/java/net/minecraft/world/entity/Shearable.java -+++ b/src/main/java/net/minecraft/world/entity/Shearable.java -@@ -8,7 +8,7 @@ public interface Shearable { - - boolean readyForShearing(); - // Paper start - custom shear drops; ensure all implementing entities override this -- default java.util.List generateDefaultDrops() { -+ default java.util.List generateDefaultDrops(int looting) { // Purpur - return java.util.Collections.emptyList(); - } - // Paper end - custom shear drops diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java -index f8174dd45cef1c521a96a7bbda811630c438cb4a..14ceb3308474e76220bd64b0254df3f2925d4206 100644 +index e45ed0ffa031f7ab5fa39b71a2678c5a282e0561..7bc3a6f4dabc6411b6ff17e6dbbd190d57076cd1 100644 --- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java -@@ -26,15 +26,23 @@ public class AttributeMap { +@@ -26,15 +26,22 @@ public class AttributeMap { // Gale end - Lithium - replace AI attributes with optimized collections private final AttributeSupplier supplier; private final java.util.function.Function, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations @@ -3116,7 +3109,6 @@ index f8174dd45cef1c521a96a7bbda811630c438cb4a..14ceb3308474e76220bd64b0254df3f2 + // Purpur start + this(defaultAttributes, null); + } -+ + public AttributeMap(AttributeSupplier defaultAttributes, net.minecraft.world.entity.LivingEntity entity) { + this.entity = entity; + // Purpur end @@ -3131,7 +3123,7 @@ index f8174dd45cef1c521a96a7bbda811630c438cb4a..14ceb3308474e76220bd64b0254df3f2 this.attributesToSync.add(instance); } } -@@ -48,7 +56,7 @@ public class AttributeMap { +@@ -48,7 +55,7 @@ public class AttributeMap { } public Collection getSyncableAttributes() { @@ -3141,10 +3133,10 @@ index f8174dd45cef1c521a96a7bbda811630c438cb4a..14ceb3308474e76220bd64b0254df3f2 @Nullable diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java b/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java -index 10a1434313b11dae8210484583c6bf3b627416f7..35af18f371b3beaf81fcdca79fefe85e0a862b50 100644 +index 386f9bca728055f7b75fb690b307ff4510068105..0bb08af954d224a2b4404615bee720ac4bdbac55 100644 --- a/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java +++ b/src/main/java/net/minecraft/world/entity/ai/attributes/DefaultAttributes.java -@@ -129,7 +129,7 @@ public class DefaultAttributes { +@@ -130,7 +130,7 @@ public class DefaultAttributes { .put(EntityType.OCELOT, Ocelot.createAttributes().build()) .put(EntityType.PANDA, Panda.createAttributes().build()) .put(EntityType.PARROT, Parrot.createAttributes().build()) @@ -3153,6 +3145,15 @@ index 10a1434313b11dae8210484583c6bf3b627416f7..35af18f371b3beaf81fcdca79fefe85e .put(EntityType.PIG, Pig.createAttributes().build()) .put(EntityType.PIGLIN, Piglin.createAttributes().build()) .put(EntityType.PIGLIN_BRUTE, PiglinBrute.createAttributes().build()) +@@ -161,7 +161,7 @@ public class DefaultAttributes { + .put(EntityType.VILLAGER, Villager.createAttributes().build()) + .put(EntityType.VINDICATOR, Vindicator.createAttributes().build()) + .put(EntityType.WARDEN, Warden.createAttributes().build()) +- .put(EntityType.WANDERING_TRADER, Mob.createMobAttributes().build()) ++ .put(EntityType.WANDERING_TRADER, net.minecraft.world.entity.npc.WanderingTrader.createAttributes().build()) // Purpur + .put(EntityType.WITCH, Witch.createAttributes().build()) + .put(EntityType.WITHER, WitherBoss.createAttributes().build()) + .put(EntityType.WITHER_SKELETON, AbstractSkeleton.createAttributes().build()) diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/RangedAttribute.java b/src/main/java/net/minecraft/world/entity/ai/attributes/RangedAttribute.java index f0703302e7dbbda88de8c648d20d87c55ed9b1e0..a913ebabaa5f443afa987b972355a8f8d1723c78 100644 --- a/src/main/java/net/minecraft/world/entity/ai/attributes/RangedAttribute.java @@ -3166,7 +3167,7 @@ index f0703302e7dbbda88de8c648d20d87c55ed9b1e0..a913ebabaa5f443afa987b972355a8f8 } } diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java -index 59732e3b17c20143ecbdc6afa480fdbdc1afc55f..e74c39e279c6af2742a158100578cb1a00ca07ef 100644 +index 59732e3b17c20143ecbdc6afa480fdbdc1afc55f..93d17d93922841354fb0bfb15ce43776fafb19d2 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java @@ -81,7 +81,7 @@ public class AcquirePoi { @@ -3174,12 +3175,12 @@ index 59732e3b17c20143ecbdc6afa480fdbdc1afc55f..e74c39e279c6af2742a158100578cb1a // Paper start - optimise POI access java.util.List, BlockPos>> poiposes = new java.util.ArrayList<>(); - io.papermc.paper.util.PoiAccess.findNearestPoiPositions(poiManager, poiPredicate, predicate2, entity.blockPosition(), 48, 48*48, PoiManager.Occupancy.HAS_SPACE, false, 5, poiposes); -+ io.papermc.paper.util.PoiAccess.findNearestPoiPositions(poiManager, poiPredicate, predicate2, entity.blockPosition(), world.purpurConfig.villagerAcquirePoiSearchRadius, world.purpurConfig.villagerAcquirePoiSearchRadius*world.purpurConfig.villagerAcquirePoiSearchRadius, PoiManager.Occupancy.HAS_SPACE, false, 5, poiposes); // Purpur ++ io.papermc.paper.util.PoiAccess.findNearestPoiPositions(poiManager, poiPredicate, predicate2, entity.blockPosition(), world.purpurConfig.villagerAcquirePoiSearchRadius, world.purpurConfig.villagerAcquirePoiSearchRadius*world.purpurConfig.villagerAcquirePoiSearchRadius, PoiManager.Occupancy.HAS_SPACE, false, 5, poiposes); Set, BlockPos>> set = new java.util.HashSet<>(poiposes); // Paper end - optimise POI access Path path = findPathToPois(entity, set); diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java b/src/main/java/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java -index 2ade08d1466660ee1787fa97908002ef56389712..8d4e206aa05b95b7bfec5d23496085cf55a3e1de 100644 +index 2ade08d1466660ee1787fa97908002ef56389712..018cc6ff39641157668fca09e64bcddf7d4d3a5c 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java @@ -41,17 +41,19 @@ public class HarvestFarmland extends Behavior { @@ -3194,7 +3195,7 @@ index 2ade08d1466660ee1787fa97908002ef56389712..8d4e206aa05b95b7bfec5d23496085cf protected boolean checkExtraStartConditions(ServerLevel world, Villager entity) { - if (!world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ if (!world.purpurConfig.villagerBypassMobGriefing && !world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur ++ if (!world.purpurConfig.villagerBypassMobGriefing == !world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur return false; - } else if (entity.getVillagerData().getProfession() != VillagerProfession.FARMER) { + } else if (entity.getVillagerData().getProfession() != VillagerProfession.FARMER && !(world.purpurConfig.villagerClericsFarmWarts && entity.getVillagerData().getProfession() == VillagerProfession.CLERIC)) { // Purpur @@ -3306,7 +3307,7 @@ index 73e20e1f7d2bb1cd3d08e6bdca50efac22c9d958..b96e596fb123f5b69d2b2f5b4a65537b if (this.trades != null && entity.getInventory().hasAnyOf(this.trades)) { throwHalfStack(entity, this.trades, villager); diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java b/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java -index f000a6c1e61198e6dd06ae5f084d12fdf309f50a..3091d985ba9c55d404332576320718840538722e 100644 +index bb65d46967cb04f611b3c9c97d5732cfb21ede9b..7f4156e4690bbd57f9e9141f008851062cae733d 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerGoalPackages.java @@ -52,8 +52,13 @@ public class VillagerGoalPackages { @@ -3389,28 +3390,28 @@ index fbfc2f2515ad709b2c1212aef9521e795547d66b..e77bd11af62682d5eca41f6c9e1aed30 this.lookAtCooldown--; this.getYRotD().ifPresent(yaw -> this.mob.yHeadRot = this.rotateTowards(this.mob.yHeadRot, yaw + 20.0F, this.yMaxRotSpeed)); diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java -index a85885ee51df585fa11ae9f8fcd67ff2a71c5a18..d81509e08e70ec5b2f837c9dc66b1254c86854e4 100644 +index 7324da6b7dd2623ce394e3827ff77ef684a3b98b..d0ba8f74cd0d676640776c46df1913852f4a4a2e 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java -@@ -32,7 +32,7 @@ public class BreakDoorGoal extends DoorInteractGoal { +@@ -33,7 +33,7 @@ public class BreakDoorGoal extends DoorInteractGoal { @Override public boolean canUse() { -- return !super.canUse() ? false : (!this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.isValidDifficulty(this.mob.level().getDifficulty()) && !this.isOpen()); -+ return !super.canUse() ? false : ((!this.mob.level().purpurConfig.zombieBypassMobGriefing && !this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) ? false : this.isValidDifficulty(this.mob.level().getDifficulty()) && !this.isOpen()); // Purpur +- return !super.canUse() ? false : (!getServerLevel((Entity) this.mob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.isValidDifficulty(this.mob.level().getDifficulty()) && !this.isOpen()); ++ return !super.canUse() ? false : (!this.mob.level().purpurConfig.zombieBypassMobGriefing == !getServerLevel((Entity) this.mob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.isValidDifficulty(this.mob.level().getDifficulty()) && !this.isOpen()); // Purpur } @Override diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java -index 4e2c23ccdf4e4a4d65b291dbe20952bae1838bff..0da884a833f6c707fea512e826658c3bb73f7a77 100644 +index 32bb591371fe78ba10a2bc52389ef33978cbc0eb..13f5e5c199688954c263b9e3397e02c9f77bbb92 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java @@ -74,7 +74,7 @@ public class EatBlockGoal extends Goal { final BlockState blockState = this.level.getBlockState(blockposition); // Paper - fix wrong block state if (EatBlockGoal.IS_TALL_GRASS.test(blockState)) { // Paper - fix wrong block state -- if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, blockState.getFluidState().createLegacyBlock(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state -+ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, blockState.getFluidState().createLegacyBlock(), !this.level.purpurConfig.sheepBypassMobGriefing && !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state // Purpur +- if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, blockState.getFluidState().createLegacyBlock(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, blockState.getFluidState().createLegacyBlock(), !getServerLevel(this.level).purpurConfig.sheepBypassMobGriefing == !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - fix wrong block state // Purpur this.level.destroyBlock(blockposition, false); } @@ -3418,8 +3419,8 @@ index 4e2c23ccdf4e4a4d65b291dbe20952bae1838bff..0da884a833f6c707fea512e826658c3b BlockPos blockposition1 = blockposition.below(); if (this.level.getBlockState(blockposition1).is(Blocks.GRASS_BLOCK)) { -- if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.DIRT.defaultBlockState(), !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - Fix wrong block state -+ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.DIRT.defaultBlockState(), !this.level.purpurConfig.sheepBypassMobGriefing && !this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - Fix wrong block state // Purpur +- if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.DIRT.defaultBlockState(), !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - Fix wrong block state ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition1, Blocks.DIRT.defaultBlockState(), !getServerLevel(this.level).purpurConfig.sheepBypassMobGriefing == !getServerLevel(this.level).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Paper - Fix wrong block state // Purpur this.level.levelEvent(2001, blockposition1, Block.getId(Blocks.GRASS_BLOCK.defaultBlockState())); this.level.setBlock(blockposition1, Blocks.DIRT.defaultBlockState(), 2); } @@ -3444,15 +3445,15 @@ index df695b444fa2a993d381e2f197182c3e91a68502..0f4f546cd0eda4bd82b47446ae23ac32 double d = this.llama.distanceToSqr(this.llama.getCaravanHead()); if (d > 676.0) { diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java -index 6634228ef002cbef67980272a26be4a75c954116..a61abba840a55fb4fbc9716a5e05eb2778068785 100644 +index 9d245d08be61d7edee9138196ae3bf52023e3993..771bb96032149a8573d1de14fa2ab19012c82000 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java -@@ -40,7 +40,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { +@@ -41,7 +41,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal { @Override public boolean canUse() { -- if (!this.removerMob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ if (!this.removerMob.level().purpurConfig.zombieBypassMobGriefing && !this.removerMob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur +- if (!getServerLevel((Entity) this.removerMob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (!getServerLevel(this.removerMob).purpurConfig.zombieBypassMobGriefing == !getServerLevel((Entity) this.removerMob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur return false; } else if (this.nextStartTick > 0) { --this.nextStartTick; @@ -3489,10 +3490,10 @@ index 137ec75ee803789deb7b1ca93dd9369c9af362b9..ca95d25af3e9a0536868b0c7fd8e7d2f } } diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java -index 13f8c2cb42334ba3b573ca44ace1d3df76e41ff7..baca552e52c728867fcb0527b6c3eb394b2b9c7f 100644 +index 84ab90dd1fe693da71732533ccff940c1007e1b6..179fdf7b7f68db610925a9d7b88879289b1b98b8 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java -@@ -64,7 +64,7 @@ public class TemptGoal extends Goal { +@@ -67,7 +67,7 @@ public class TemptGoal extends Goal { } private boolean shouldFollow(LivingEntity entity) { @@ -3542,25 +3543,25 @@ index 8bed5992f639f805ccdec56a90101004570dc265..675126d9ab94b6c69d0436a42b9594a5 if (list != null) { list.trimToSize(); diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -index 4addcfe248dd4705be7e67551b258ce86c57e194..82d3e442f6d31211701878fc5ae7a346247ef124 100644 +index b51a04d3e006bc770006cff790791bc0f6bee77d..886ca1c8a22714bc299ad08659e5279281669bb3 100644 --- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java @@ -64,6 +64,10 @@ public class TargetingConditions { return false; - } else if (this.selector != null && !this.selector.test(targetEntity)) { + } else if (this.selector != null && !this.selector.test(target, world)) { return false; + // Purpur start -+ } else if (!targetEntity.level().purpurConfig.idleTimeoutTargetPlayer && targetEntity instanceof net.minecraft.server.level.ServerPlayer player && player.isAfk()) { ++ } else if (!world.purpurConfig.idleTimeoutTargetPlayer && target instanceof net.minecraft.server.level.ServerPlayer player && player.isAfk()) { + return false; + // Purpur end } else { - if (baseEntity == null) { - if (this.isCombat && (!targetEntity.canBeSeenAsEnemy() || targetEntity.level().getDifficulty() == Difficulty.PEACEFUL)) { + if (tester == null) { + if (this.isCombat && (!target.canBeSeenAsEnemy() || world.getDifficulty() == Difficulty.PEACEFUL)) { diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java -index 13131a24d96094583406329d81bf51bec0d803d5..bad6c54be6ac7fa5de83db79695fbbe7d12e997b 100644 +index 05ab901becfc7ffe4e4483ac2c7acb2e2a72490f..75445d2fa84620f3d27235a941107db199f563d9 100644 --- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java +++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java -@@ -44,12 +44,59 @@ public class Bat extends AmbientCreature { +@@ -47,12 +47,59 @@ public class Bat extends AmbientCreature { public Bat(EntityType type, Level world) { super(type, world); @@ -3620,7 +3621,7 @@ index 13131a24d96094583406329d81bf51bec0d803d5..bad6c54be6ac7fa5de83db79695fbbe7 @Override public boolean isFlapping() { return !this.isResting() && (float) this.tickCount % 10.0F == 0.0F; -@@ -99,7 +146,7 @@ public class Bat extends AmbientCreature { +@@ -102,7 +149,7 @@ public class Bat extends AmbientCreature { protected void pushEntities() {} public static AttributeSupplier.Builder createAttributes() { @@ -3629,10 +3630,10 @@ index 13131a24d96094583406329d81bf51bec0d803d5..bad6c54be6ac7fa5de83db79695fbbe7 } public boolean isResting() { -@@ -132,6 +179,14 @@ public class Bat extends AmbientCreature { +@@ -135,6 +182,14 @@ public class Bat extends AmbientCreature { @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + // Purpur start + if (getRider() != null && this.isControllable()) { + Vec3 mot = getDeltaMovement(); @@ -3641,10 +3642,10 @@ index 13131a24d96094583406329d81bf51bec0d803d5..bad6c54be6ac7fa5de83db79695fbbe7 + } + // Purpur end + - super.customServerAiStep(); + super.customServerAiStep(world); BlockPos blockposition = this.blockPosition(); BlockPos blockposition1 = blockposition.above(); -@@ -210,6 +265,29 @@ public class Bat extends AmbientCreature { +@@ -213,6 +268,29 @@ public class Bat extends AmbientCreature { } } @@ -3674,7 +3675,7 @@ index 13131a24d96094583406329d81bf51bec0d803d5..bad6c54be6ac7fa5de83db79695fbbe7 @Override public void readAdditionalSaveData(CompoundTag nbt) { super.readAdditionalSaveData(nbt); -@@ -229,7 +307,7 @@ public class Bat extends AmbientCreature { +@@ -232,7 +310,7 @@ public class Bat extends AmbientCreature { int i = world.getMaxLocalRawBrightness(pos); byte b0 = 4; @@ -3683,17 +3684,17 @@ index 13131a24d96094583406329d81bf51bec0d803d5..bad6c54be6ac7fa5de83db79695fbbe7 b0 = 7; } else if (random.nextBoolean()) { return false; -@@ -272,6 +350,8 @@ public class Bat extends AmbientCreature { - */ - private static long nextHalloweenEnd = 0; +@@ -242,6 +320,8 @@ public class Bat extends AmbientCreature { + } + } + public static boolean isHalloweenSeason(Level level) { return level.purpurConfig.forceHalloweenSeason || isHalloween(); } // Purpur + - // The Halloween begins at 10/20 0:00, and end with 11/04 0:00 - // Only when the current Halloween period ends, the `nextHalloweenStart` - // and `nextHalloweenEnd` will adjust to the epoch ms of date of next year + // Gale start - predict Halloween + /** + * The 1-indexed month of the year that Halloween starts (inclusive). diff --git a/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java b/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java -index 3231eaa6af2ddfe4095ff2d650f580ebd4d43aea..e8cb124d232f7316cc8c35dd8bd12f79bbcda7d6 100644 +index 9aedc62b1766f6a7db4da7eba55167d21d698791..9708ed3e00059fdf5d1d60e0c607d0ab153d1d3f 100644 --- a/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java +++ b/src/main/java/net/minecraft/world/entity/animal/AbstractFish.java @@ -87,6 +87,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { @@ -3707,7 +3708,7 @@ index 3231eaa6af2ddfe4095ff2d650f580ebd4d43aea..e8cb124d232f7316cc8c35dd8bd12f79 @@ -100,7 +101,7 @@ public abstract class AbstractFish extends WaterAnimal implements Bucketable { @Override public void travel(Vec3 movementInput) { - if (this.isEffectiveAi() && this.isInWater()) { + if (this.isControlledByLocalInstance() && this.isInWater()) { - this.moveRelative(0.01F, movementInput); + this.moveRelative(getRider() != null ? getSpeed() : 0.01F, movementInput); // Purpur this.move(MoverType.SELF, this.getDeltaMovement()); @@ -3748,10 +3749,10 @@ index 3231eaa6af2ddfe4095ff2d650f580ebd4d43aea..e8cb124d232f7316cc8c35dd8bd12f79 double d = this.wantedX - this.fish.getX(); double e = this.wantedY - this.fish.getY(); diff --git a/src/main/java/net/minecraft/world/entity/animal/Animal.java b/src/main/java/net/minecraft/world/entity/animal/Animal.java -index 1808e1b01afa3041a54c9c9a7586d4d61960527a..91c1093ecef7c8917b69674ffc936b4ae71871e2 100644 +index 5677dc97ed83652f261100cf391883cfac7d16fe..9987d28ea145f6d0126cb4ea22001e0922fb51bd 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Animal.java +++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java -@@ -43,6 +43,7 @@ public abstract class Animal extends AgeableMob { +@@ -49,6 +49,7 @@ public abstract class Animal extends AgeableMob { @Nullable public UUID loveCause; public ItemStack breedItem; // CraftBukkit - Add breedItem variable @@ -3759,7 +3760,7 @@ index 1808e1b01afa3041a54c9c9a7586d4d61960527a..91c1093ecef7c8917b69674ffc936b4a protected Animal(EntityType type, Level world) { super(type, world); -@@ -147,7 +148,7 @@ public abstract class Animal extends AgeableMob { +@@ -157,7 +158,7 @@ public abstract class Animal extends AgeableMob { if (this.isFood(itemstack)) { int i = this.getAge(); @@ -3768,7 +3769,7 @@ index 1808e1b01afa3041a54c9c9a7586d4d61960527a..91c1093ecef7c8917b69674ffc936b4a final ItemStack breedCopy = itemstack.copy(); // Paper - Fix EntityBreedEvent copying this.usePlayerItem(player, hand, itemstack); this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying -@@ -235,12 +236,20 @@ public abstract class Animal extends AgeableMob { +@@ -261,12 +262,20 @@ public abstract class Animal extends AgeableMob { AgeableMob entityageable = this.getBreedOffspring(world, other); if (entityageable != null) { @@ -3792,7 +3793,7 @@ index 1808e1b01afa3041a54c9c9a7586d4d61960527a..91c1093ecef7c8917b69674ffc936b4a int experience = this.getRandom().nextInt(7) + 1; EntityBreedEvent entityBreedEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityBreedEvent(entityageable, this, other, breeder, this.breedItem, experience); if (entityBreedEvent.isCancelled()) { -@@ -268,8 +277,10 @@ public abstract class Animal extends AgeableMob { +@@ -294,8 +303,10 @@ public abstract class Animal extends AgeableMob { entityplayer.awardStat(Stats.ANIMALS_BRED); CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this, entityanimal, entityageable); } // Paper @@ -3806,10 +3807,10 @@ index 1808e1b01afa3041a54c9c9a7586d4d61960527a..91c1093ecef7c8917b69674ffc936b4a entityanimal.resetLove(); worldserver.broadcastEntityEvent(this, (byte) 18); diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9a6ec5e465684be7f0d54b1f7e66bdf52603e442 100644 +index 42276acfeadec6e7aa9a91d3f446f4fedb04829d..dc8df0912c1d18176e18a8f4dc43c4f60f81b659 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -144,6 +144,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -150,6 +150,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { public Bee(EntityType type, Level world) { super(type, world); this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60); @@ -3817,7 +3818,7 @@ index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9a6ec5e465684be7f0d54b1f7e66bdf5 // Paper start - Fix MC-167279 class BeeFlyingMoveControl extends FlyingMoveControl { public BeeFlyingMoveControl(final Mob entity, final int maxPitchChange, final boolean noGravity) { -@@ -152,22 +153,69 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -158,22 +159,69 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public void tick() { @@ -3827,7 +3828,7 @@ index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9a6ec5e465684be7f0d54b1f7e66bdf5 + return; + } + // Purpur end - if (this.mob.getY() <= Bee.this.level().getMinBuildHeight()) { + if (this.mob.getY() <= Bee.this.level().getMinY()) { this.mob.setNoGravity(false); } super.tick(); @@ -3888,7 +3889,7 @@ index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9a6ec5e465684be7f0d54b1f7e66bdf5 @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); -@@ -182,6 +230,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -188,6 +236,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override protected void registerGoals() { @@ -3896,7 +3897,7 @@ index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9a6ec5e465684be7f0d54b1f7e66bdf5 this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 1.399999976158142D, true)); this.goalSelector.addGoal(1, new Bee.BeeEnterHiveGoal()); this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); -@@ -199,6 +248,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -207,6 +256,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { this.goalSelector.addGoal(7, new Bee.BeeGrowCropGoal()); this.goalSelector.addGoal(8, new Bee.BeeWanderGoal()); this.goalSelector.addGoal(9, new FloatGoal(this)); @@ -3904,25 +3905,25 @@ index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9a6ec5e465684be7f0d54b1f7e66bdf5 this.targetSelector.addGoal(1, (new Bee.BeeHurtByOtherGoal(this)).setAlertOthers(new Class[0])); this.targetSelector.addGoal(2, new Bee.BeeBecomeAngryTargetGoal(this)); this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true)); -@@ -356,7 +406,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -376,7 +426,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + } - boolean wantsToEnterHive() { - if (this.stayOutOfHiveCountdown <= 0 && !this.beePollinateGoal.isPollinating() && !this.hasStung() && this.getTarget() == null) { -- boolean flag = this.isTiredOfLookingForNectar() || this.level().isRaining() || this.level().isNight() || this.hasNectar(); -+ boolean flag = this.isTiredOfLookingForNectar() || (this.level().isRaining() && !this.level().purpurConfig.beeCanWorkInRain) || (this.level().isNight() && !this.level().purpurConfig.beeCanWorkAtNight) || this.hasNectar(); // Purpur + public static boolean isNightOrRaining(Level world) { +- return world.dimensionType().hasSkyLight() && (world.isNight() || world.isRaining()); ++ return world.dimensionType().hasSkyLight() && ((world.isNight() && !world.purpurConfig.beeCanWorkAtNight) || (world.isRaining() && !world.purpurConfig.beeCanWorkInRain)); // Purpur + } - return flag && !this.isHiveNearFire(); - } else { -@@ -396,6 +446,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - this.hurt(this.damageSources().drown(), 1.0F); + public void setStayOutOfHiveCountdown(int cannotEnterHiveTicks) { +@@ -411,6 +461,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + this.hurtServer(world, this.damageSources().drown(), 1.0F); } + if (flag && !this.level().purpurConfig.beeDiesAfterSting) setHasStung(false); else // Purpur if (flag) { ++this.timeSinceSting; if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, 1, 1200)) == 0) { -@@ -428,6 +479,27 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - } +@@ -435,6 +486,27 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + return tileentitybeehive != null && tileentitybeehive.isFireNearby(); } + @Override @@ -3949,32 +3950,8 @@ index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9a6ec5e465684be7f0d54b1f7e66bdf5 @Override public int getRemainingPersistentAngerTime() { return (Integer) this.entityData.get(Bee.DATA_REMAINING_ANGER_TIME); -@@ -737,6 +809,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - if (optional.isPresent()) { - Bee.this.savedFlowerPos = (BlockPos) optional.get(); - Bee.this.navigation.moveTo((double) Bee.this.savedFlowerPos.getX() + 0.5D, (double) Bee.this.savedFlowerPos.getY() + 0.5D, (double) Bee.this.savedFlowerPos.getZ() + 0.5D, 1.2000000476837158D); -+ new org.purpurmc.purpur.event.entity.BeeFoundFlowerEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos)).callEvent(); // Purpur - return true; - } else { - Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60); -@@ -793,6 +866,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - this.pollinating = false; - Bee.this.navigation.stop(); - Bee.this.remainingCooldownBeforeLocatingNewFlower = 200; -+ new org.purpurmc.purpur.event.entity.BeeStopPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), Bee.this.savedFlowerPos == null ? null : io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos), Bee.this.hasNectar()).callEvent(); // Purpur - } - - @Override -@@ -839,6 +913,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - this.setWantedPos(); - } - -+ if (this.successfulPollinatingTicks == 0) new org.purpurmc.purpur.event.entity.BeeStartedPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos)).callEvent(); // Purpur - ++this.successfulPollinatingTicks; - if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) { - this.lastSoundPlayedTick = this.successfulPollinatingTicks; -@@ -883,16 +958,16 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - } +@@ -701,16 +773,16 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + this.hivePos = pos; } - private class BeeLookControl extends LookControl { @@ -3993,11 +3970,35 @@ index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9a6ec5e465684be7f0d54b1f7e66bdf5 } } +@@ -882,6 +954,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + if (optional.isPresent()) { + Bee.this.savedFlowerPos = (BlockPos) optional.get(); + Bee.this.navigation.moveTo((double) Bee.this.savedFlowerPos.getX() + 0.5D, (double) Bee.this.savedFlowerPos.getY() + 0.5D, (double) Bee.this.savedFlowerPos.getZ() + 0.5D, 1.2000000476837158D); ++ new org.purpurmc.purpur.event.entity.BeeFoundFlowerEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos)).callEvent(); // Purpur + return true; + } else { + Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60); +@@ -925,6 +998,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + this.pollinating = false; + Bee.this.navigation.stop(); + Bee.this.remainingCooldownBeforeLocatingNewFlower = 200; ++ new org.purpurmc.purpur.event.entity.BeeStopPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), Bee.this.savedFlowerPos == null ? null : io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos), Bee.this.hasNectar()).callEvent(); // Purpur + } + + @Override +@@ -974,6 +1048,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + this.setWantedPos(); + } + ++ if (this.successfulPollinatingTicks == 0) new org.purpurmc.purpur.event.entity.BeeStartedPollinatingEvent((org.bukkit.entity.Bee) Bee.this.getBukkitEntity(), io.papermc.paper.util.MCUtil.toLocation(Bee.this.level(), Bee.this.savedFlowerPos)).callEvent(); // Purpur + ++this.successfulPollinatingTicks; + if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) { + this.lastSoundPlayedTick = this.successfulPollinatingTicks; diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java -index 23d4dcc82115fd1a0a77565a0472304042d5f12d..765cc746e0469f24de0e84666dc5a41b3d55f472 100644 +index 471d5727b964922d8e898be9e1d5c30f9d3bac97..4aad4fdc80070f4000e929fff126714fc67050b0 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cat.java +++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java -@@ -103,6 +103,54 @@ public class Cat extends TamableAnimal implements VariantHolder { return itemstack.is(ItemTags.CAT_FOOD); }, true); this.goalSelector.addGoal(1, new FloatGoal(this)); @@ -4060,15 +4058,15 @@ index 23d4dcc82115fd1a0a77565a0472304042d5f12d..765cc746e0469f24de0e84666dc5a41b this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5D)); this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); this.goalSelector.addGoal(3, new Cat.CatRelaxOnOwnerGoal(this)); -@@ -125,6 +174,7 @@ public class Cat extends TamableAnimal implements VariantHolder(this, Rabbit.class, false, (Predicate) null)); + this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Rabbit.class, false, (TargetingConditions.Selector) null)); this.targetSelector.addGoal(1, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR)); } -@@ -308,6 +358,14 @@ public class Cat extends TamableAnimal implements VariantHolder { return itemstack.is(ItemTags.CHICKEN_FOOD); -@@ -66,6 +108,14 @@ public class Chicken extends Animal { +@@ -65,6 +107,14 @@ public class Chicken extends Animal { this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); @@ -4173,12 +4171,12 @@ index 8e347718f72297398b5e6d34a893264bc10efe18..85faf59227c2a0b1609422227a688bd8 } @Override -@@ -74,7 +124,7 @@ public class Chicken extends Animal { +@@ -73,7 +123,7 @@ public class Chicken extends Animal { } public static AttributeSupplier.Builder createAttributes() { -- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 4.0D).add(Attributes.MOVEMENT_SPEED, 0.25D); -+ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 4.0D).add(Attributes.MOVEMENT_SPEED, 0.25D).add(Attributes.ATTACK_DAMAGE, 0.0D); // Purpur +- return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 4.0D).add(Attributes.MOVEMENT_SPEED, 0.25D); ++ return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 4.0D).add(Attributes.MOVEMENT_SPEED, 0.25D).add(Attributes.ATTACK_DAMAGE, 0.0D); // Purpur } @Override @@ -4221,7 +4219,7 @@ index 824e5e4fe7619ae46061c3c978c9a044db8c84ab..f0b6118a9995bb41836685bbf94d2e7f public ItemStack getBucketItemStack() { return new ItemStack(Items.COD_BUCKET); diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java -index e336934f37075a827843e4b1bb2b6b660d2c60c9..11510e320e4df95e2f2903a07e7ba78b27545b45 100644 +index 3e00bbff266fc71b07014e7e047d77b7f809239f..6b517deec01445de4205eedb1557995a92d3ae67 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cow.java +++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java @@ -37,6 +37,7 @@ import org.bukkit.event.player.PlayerBucketFillEvent; @@ -4271,7 +4269,7 @@ index e336934f37075a827843e4b1bb2b6b660d2c60c9..11510e320e4df95e2f2903a07e7ba78b + } + + @Override -+ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, net.minecraft.world.entity.SpawnGroupData entityData) { ++ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.EntitySpawnReason spawnReason, net.minecraft.world.entity.SpawnGroupData entityData) { + this.isNaturallyAggressiveToPlayers = world.getLevel().purpurConfig.cowNaturallyAggressiveToPlayersChance > 0.0D && random.nextDouble() <= world.getLevel().purpurConfig.cowNaturallyAggressiveToPlayersChance; + return super.finalizeSpawn(world, difficulty, spawnReason, entityData); + } @@ -4296,7 +4294,7 @@ index e336934f37075a827843e4b1bb2b6b660d2c60c9..11510e320e4df95e2f2903a07e7ba78b this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); -+ this.targetSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, target -> isNaturallyAggressiveToPlayers)); // Purpur ++ this.targetSelector.addGoal(0, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (ignored, ignored2) -> isNaturallyAggressiveToPlayers)); // Purpur } @Override @@ -4304,8 +4302,8 @@ index e336934f37075a827843e4b1bb2b6b660d2c60c9..11510e320e4df95e2f2903a07e7ba78b } public static AttributeSupplier.Builder createAttributes() { -- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D); -+ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D).add(Attributes.ATTACK_DAMAGE, 0.0D); // Purpur +- return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D); ++ return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D).add(Attributes.ATTACK_DAMAGE, 0.0D); // Purpur } @Override @@ -4329,7 +4327,7 @@ index e336934f37075a827843e4b1bb2b6b660d2c60c9..11510e320e4df95e2f2903a07e7ba78b @@ -111,6 +161,10 @@ public class Cow extends Animal { player.setItemInHand(hand, itemstack1); - return InteractionResult.sidedSuccess(this.level().isClientSide); + return InteractionResult.SUCCESS; + // Purpur start - feed mushroom to change to mooshroom + } else if (level().purpurConfig.cowFeedMushrooms > 0 && this.getType() != EntityType.MOOSHROOM && isMushroom(itemstack)) { + return this.feedMushroom(player, itemstack); @@ -4367,14 +4365,14 @@ index e336934f37075a827843e4b1bb2b6b660d2c60c9..11510e320e4df95e2f2903a07e7ba78b + } + return InteractionResult.CONSUME; // require 5 mushrooms to transform (prevents mushroom duping) + } -+ MushroomCow mooshroom = EntityType.MOOSHROOM.create(level()); ++ MushroomCow mooshroom = EntityType.MOOSHROOM.create(level(), EntitySpawnReason.CONVERSION); + if (mooshroom == null) { + return InteractionResult.PASS; + } + if (stack.getItem() == net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem()) { -+ mooshroom.setVariant(MushroomCow.MushroomType.BROWN); ++ mooshroom.setVariant(MushroomCow.Variant.BROWN); + } else { -+ mooshroom.setVariant(MushroomCow.MushroomType.RED); ++ mooshroom.setVariant(MushroomCow.Variant.RED); + } + mooshroom.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + mooshroom.setHealth(this.getHealth()); @@ -4405,13 +4403,13 @@ index e336934f37075a827843e4b1bb2b6b660d2c60c9..11510e320e4df95e2f2903a07e7ba78b + // Purpur end } diff --git a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java -index da45cc62985f8b67cdfeffc21cb33837db673555..ef0124ceb7cafd58c01c7f0b4b542f38a383ab88 100644 +index 5af4d590a9b0f17ba53c6959d9c18bd1269878a4..c1842894f96a567707992d8ff938dbf689dd0df6 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java +++ b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java -@@ -81,19 +81,105 @@ public class Dolphin extends WaterAnimal { - public static final Predicate ALLOWED_ITEMS = (entityitem) -> { +@@ -85,14 +85,99 @@ public class Dolphin extends AgeableWaterCreature { return !entityitem.hasPickUpDelay() && entityitem.isAlive() && entityitem.isInWater(); }; + public static final float BABY_SCALE = 0.65F; + private boolean isNaturallyAggressiveToPlayers; // Purpur + private int spitCooldown; // Purpur @@ -4508,14 +4506,16 @@ index da45cc62985f8b67cdfeffc21cb33837db673555..ef0124ceb7cafd58c01c7f0b4b542f38 + @Nullable @Override - public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData) { - this.setAirSupply(this.getMaxAirSupply()); - this.setXRot(0.0F); + public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, EntitySpawnReason spawnReason, @Nullable SpawnGroupData entityData) { +@@ -101,6 +186,7 @@ public class Dolphin extends AgeableWaterCreature { + SpawnGroupData groupdataentity1 = (SpawnGroupData) Objects.requireNonNullElseGet(entityData, () -> { + return new AgeableMob.AgeableMobGroupData(0.1F); + }); + this.isNaturallyAggressiveToPlayers = world.getLevel().purpurConfig.dolphinNaturallyAggressiveToPlayersChance > 0.0D && random.nextDouble() <= world.getLevel().purpurConfig.dolphinNaturallyAggressiveToPlayersChance; // Purpur - return super.finalizeSpawn(world, difficulty, spawnReason, entityData); - } -@@ -158,17 +244,21 @@ public class Dolphin extends WaterAnimal { + return super.finalizeSpawn(world, difficulty, spawnReason, groupdataentity1); + } +@@ -177,17 +263,21 @@ public class Dolphin extends AgeableWaterCreature { protected void registerGoals() { this.goalSelector.addGoal(0, new BreathAirGoal(this)); this.goalSelector.addGoal(0, new TryFindWaterGoal(this)); @@ -4534,11 +4534,11 @@ index da45cc62985f8b67cdfeffc21cb33837db673555..ef0124ceb7cafd58c01c7f0b4b542f38 this.goalSelector.addGoal(9, new AvoidEntityGoal<>(this, Guardian.class, 8.0F, 1.0D, 1.0D)); + this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Guardian.class})).setAlertOthers()); -+ this.targetSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, target -> isNaturallyAggressiveToPlayers)); // Purpur ++ this.targetSelector.addGoal(2, new net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (ignored, ignored2) -> isNaturallyAggressiveToPlayers)); // Purpur } public static AttributeSupplier.Builder createAttributes() { -@@ -207,7 +297,7 @@ public class Dolphin extends WaterAnimal { +@@ -231,7 +321,7 @@ public class Dolphin extends AgeableWaterCreature { @Override protected boolean canRide(Entity entity) { @@ -4547,7 +4547,7 @@ index da45cc62985f8b67cdfeffc21cb33837db673555..ef0124ceb7cafd58c01c7f0b4b542f38 } @Override -@@ -242,6 +332,11 @@ public class Dolphin extends WaterAnimal { +@@ -264,6 +354,11 @@ public class Dolphin extends AgeableWaterCreature { @Override public void tick() { super.tick(); @@ -4559,7 +4559,7 @@ index da45cc62985f8b67cdfeffc21cb33837db673555..ef0124ceb7cafd58c01c7f0b4b542f38 if (this.isNoAi()) { this.setAirSupply(this.getMaxAirSupply()); } else { -@@ -384,6 +479,7 @@ public class Dolphin extends WaterAnimal { +@@ -412,6 +507,7 @@ public class Dolphin extends AgeableWaterCreature { @Override public boolean canUse() { @@ -4568,11 +4568,11 @@ index da45cc62985f8b67cdfeffc21cb33837db673555..ef0124ceb7cafd58c01c7f0b4b542f38 } diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java -index 9a0adf65d4d54852301a91b6fe444e4c5a139f5d..5d13c8827c0746d180b5a838b3f2be2cbd2cba14 100644 +index a9a8ebb2cebe668628d5bdb33fa1399e0ab1e08b..ac044be03494c3d6bad6bbc22321445e04d430cc 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Fox.java +++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java -@@ -145,6 +145,65 @@ public class Fox extends Animal implements VariantHolder { - this.setCanPickUpLoot(true); +@@ -144,6 +144,65 @@ public class Fox extends Animal implements VariantHolder { + this.getNavigation().setRequiredPathLength(32.0F); } + // Purpur start @@ -4637,7 +4637,7 @@ index 9a0adf65d4d54852301a91b6fe444e4c5a139f5d..5d13c8827c0746d180b5a838b3f2be2c @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); -@@ -164,6 +223,7 @@ public class Fox extends Animal implements VariantHolder { +@@ -163,6 +222,7 @@ public class Fox extends Animal implements VariantHolder { return entityliving instanceof AbstractSchoolingFish; }); this.goalSelector.addGoal(0, new Fox.FoxFloatGoal()); @@ -4645,15 +4645,15 @@ index 9a0adf65d4d54852301a91b6fe444e4c5a139f5d..5d13c8827c0746d180b5a838b3f2be2c this.goalSelector.addGoal(0, new ClimbOnTopOfPowderSnowGoal(this, this.level())); this.goalSelector.addGoal(1, new Fox.FaceplantGoal()); this.goalSelector.addGoal(2, new Fox.FoxPanicGoal(2.2D)); -@@ -190,6 +250,7 @@ public class Fox extends Animal implements VariantHolder { +@@ -189,6 +249,7 @@ public class Fox extends Animal implements VariantHolder { this.goalSelector.addGoal(11, new Fox.FoxSearchForItemsGoal()); this.goalSelector.addGoal(12, new Fox.FoxLookAtPlayerGoal(this, Player.class, 24.0F)); this.goalSelector.addGoal(13, new Fox.PerchAndSearchGoal()); + this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(3, new Fox.DefendTrustedTargetGoal(LivingEntity.class, false, false, (entityliving) -> { + this.targetSelector.addGoal(3, new Fox.DefendTrustedTargetGoal(LivingEntity.class, false, false, (entityliving, worldserver) -> { return Fox.TRUSTED_TARGET_SELECTOR.test(entityliving) && !this.trusts(entityliving.getUUID()); })); -@@ -344,6 +405,11 @@ public class Fox extends Animal implements VariantHolder { +@@ -338,6 +399,11 @@ public class Fox extends Animal implements VariantHolder { } private void setTargetGoals() { @@ -4662,34 +4662,34 @@ index 9a0adf65d4d54852301a91b6fe444e4c5a139f5d..5d13c8827c0746d180b5a838b3f2be2c + this.targetSelector.removeGoal(this.turtleEggTargetGoal); + this.targetSelector.removeGoal(this.fishTargetGoal); + // Purpur end - if (this.getVariant() == Fox.Type.RED) { + if (this.getVariant() == Fox.Variant.RED) { this.targetSelector.addGoal(4, this.landTargetGoal); this.targetSelector.addGoal(4, this.turtleEggTargetGoal); -@@ -377,6 +443,7 @@ public class Fox extends Animal implements VariantHolder { +@@ -367,6 +433,7 @@ public class Fox extends Animal implements VariantHolder { - public void setVariant(Fox.Type variant) { + public void setVariant(Fox.Variant variant) { this.entityData.set(Fox.DATA_TYPE_ID, variant.getId()); + this.setTargetGoals(); // Purpur - fix API bug not updating pathfinders on type change } List getTrustedUUIDs() { -@@ -717,6 +784,29 @@ public class Fox extends Animal implements VariantHolder { +@@ -702,6 +769,29 @@ public class Fox extends Animal implements VariantHolder { } // Paper end + // Purpur start + @Override -+ public net.minecraft.world.InteractionResult mobInteract(Player player, InteractionHand hand) { ++ public net.minecraft.world.InteractionResult mobInteract(Player player, net.minecraft.world.InteractionHand hand) { + if (level().purpurConfig.foxTypeChangesWithTulips) { + ItemStack itemstack = player.getItemInHand(hand); -+ if (getVariant() == Type.RED && itemstack.getItem() == Items.WHITE_TULIP) { -+ setVariant(Type.SNOW); ++ if (getVariant() == Variant.RED && itemstack.getItem() == Items.WHITE_TULIP) { ++ setVariant(Variant.SNOW); + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); + } + return net.minecraft.world.InteractionResult.SUCCESS; -+ } else if (getVariant() == Type.SNOW && itemstack.getItem() == Items.ORANGE_TULIP) { -+ setVariant(Type.RED); ++ } else if (getVariant() == Variant.SNOW && itemstack.getItem() == Items.ORANGE_TULIP) { ++ setVariant(Variant.RED); + if (!player.getAbilities().instabuild) { + itemstack.shrink(1); + } @@ -4703,7 +4703,7 @@ index 9a0adf65d4d54852301a91b6fe444e4c5a139f5d..5d13c8827c0746d180b5a838b3f2be2c @Override // Paper start - Cancellable death event protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(ServerLevel world, DamageSource damageSource) { -@@ -769,16 +859,16 @@ public class Fox extends Animal implements VariantHolder { +@@ -754,16 +844,16 @@ public class Fox extends Animal implements VariantHolder { return new Vec3(0.0D, (double) (0.55F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); } @@ -4723,7 +4723,7 @@ index 9a0adf65d4d54852301a91b6fe444e4c5a139f5d..5d13c8827c0746d180b5a838b3f2be2c } } -@@ -789,16 +879,16 @@ public class Fox extends Animal implements VariantHolder { +@@ -774,16 +864,16 @@ public class Fox extends Animal implements VariantHolder { } } @@ -4743,7 +4743,7 @@ index 9a0adf65d4d54852301a91b6fe444e4c5a139f5d..5d13c8827c0746d180b5a838b3f2be2c } } -@@ -916,8 +1006,10 @@ public class Fox extends Animal implements VariantHolder { +@@ -901,8 +991,10 @@ public class Fox extends Animal implements VariantHolder { CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer2, this.animal, this.partner, entityfox); } @@ -4756,17 +4756,17 @@ index 9a0adf65d4d54852301a91b6fe444e4c5a139f5d..5d13c8827c0746d180b5a838b3f2be2c this.animal.resetLove(); this.partner.resetLove(); worldserver.addFreshEntityWithPassengers(entityfox, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - added SpawnReason -@@ -1303,7 +1395,7 @@ public class Fox extends Animal implements VariantHolder { +@@ -1288,7 +1380,7 @@ public class Fox extends Animal implements VariantHolder { } protected void onReachedTarget() { -- if (Fox.this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ if (Fox.this.level().purpurConfig.foxBypassMobGriefing || Fox.this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur +- if (getServerLevel(Fox.this.level()).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (getServerLevel(Fox.this.level()).purpurConfig.foxBypassMobGriefing ^ getServerLevel(Fox.this.level()).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur BlockState iblockdata = Fox.this.level().getBlockState(this.blockPos); if (iblockdata.is(Blocks.SWEET_BERRY_BUSH)) { diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java -index 1807da10d07d1f6e4ddbc0fa1b8da34a688d67c3..7bec03979bb5a4c576549baba822ffb908d7a2be 100644 +index e07b79ef172095c1800c88342b3ac8dc7703aea2..9a6471d2f1eb1c8af006b70b6bba0b668220fb00 100644 --- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java @@ -57,13 +57,59 @@ public class IronGolem extends AbstractGolem implements NeutralMob { @@ -4853,7 +4853,7 @@ index 1807da10d07d1f6e4ddbc0fa1b8da34a688d67c3..7bec03979bb5a4c576549baba822ffb9 this.readPersistentAngerSaveData(this.level(), nbt); } -@@ -273,18 +322,19 @@ public class IronGolem extends AbstractGolem implements NeutralMob { +@@ -267,18 +316,19 @@ public class IronGolem extends AbstractGolem implements NeutralMob { ItemStack itemstack = player.getItemInHand(hand); if (!itemstack.is(Items.IRON_INGOT)) { @@ -4872,14 +4872,14 @@ index 1807da10d07d1f6e4ddbc0fa1b8da34a688d67c3..7bec03979bb5a4c576549baba822ffb9 this.playSound(SoundEvents.IRON_GOLEM_REPAIR, 1.0F, f1); itemstack.consume(1, player); + if (this.level().purpurConfig.ironGolemHealCalm && isAngry() && getHealth() == getMaxHealth()) stopBeingAngry(); // Purpur - return InteractionResult.sidedSuccess(this.level().isClientSide); + return InteractionResult.SUCCESS; } } diff --git a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java -index 5707c6287a691030841fa973e8f7f34a816103e4..4829e7178c3e8a4c8bbc2c70f2d5fb5e919b03c0 100644 +index 0047c9f3c6dc901944187784e42cd09a3c6b460c..24205e62b95833779a7dff598930c4672a33fa36 100644 --- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java +++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java -@@ -64,6 +64,43 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder drops = this.generateDefaultDrops(); -+ java.util.List drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.LOOTING, itemstack)); // Purpur - org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); - if (event != null) { - if (event.isCancelled()) { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } - drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops()); - } -@@ -150,7 +187,7 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder optional = this.getEffectsFromItemStack(itemstack); if (optional.isEmpty()) { @@ -4946,28 +4941,11 @@ index 5707c6287a691030841fa973e8f7f34a816103e4..4829e7178c3e8a4c8bbc2c70f2d5fb5e } itemstack.consume(1, player); -@@ -172,13 +209,13 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder generateDefaultDrops() { -+ public java.util.List generateDefaultDrops(int looting) { // Purpur - java.util.List dropEntities = new java.util.ArrayList<>(5); -- for (int i = 0; i < 5; ++i) { -+ for (int i = 0; i < 5 + (org.purpurmc.purpur.PurpurConfig.allowShearsLooting ? looting : 0); ++i) { // Purpur - dropEntities.add(new ItemStack(this.getVariant().getBlockState().getBlock())); - } - return dropEntities; diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -index 97f4cc522706ec5914672aa4fdfbc35edc94aeb6..82ba970f265142e2fe7c8c5152f5004af984dc03 100644 +index 0554ee499c452db6c1e6852f5022b1f197adb024..dee59cb4b87845c940ee089aa932aa69dd2539d6 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java +++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java -@@ -66,6 +66,44 @@ public class Ocelot extends Animal { +@@ -65,6 +65,44 @@ public class Ocelot extends Animal { this.reassessTrustingGoals(); } @@ -5012,7 +4990,7 @@ index 97f4cc522706ec5914672aa4fdfbc35edc94aeb6..82ba970f265142e2fe7c8c5152f5004a public boolean isTrusting() { return (Boolean) this.entityData.get(Ocelot.DATA_TRUSTING); } -@@ -99,12 +137,14 @@ public class Ocelot extends Animal { +@@ -98,12 +136,14 @@ public class Ocelot extends Animal { return itemstack.is(ItemTags.OCELOT_FOOD); }, true); this.goalSelector.addGoal(1, new FloatGoal(this)); @@ -5027,7 +5005,7 @@ index 97f4cc522706ec5914672aa4fdfbc35edc94aeb6..82ba970f265142e2fe7c8c5152f5004a this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Chicken.class, false)); this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, false, false, Turtle.BABY_ON_LAND_SELECTOR)); } -@@ -245,7 +285,7 @@ public class Ocelot extends Animal { +@@ -244,7 +284,7 @@ public class Ocelot extends Animal { if (world.isUnobstructed(this) && !world.containsAnyLiquid(this.getBoundingBox())) { BlockPos blockposition = this.blockPosition(); @@ -5037,10 +5015,10 @@ index 97f4cc522706ec5914672aa4fdfbc35edc94aeb6..82ba970f265142e2fe7c8c5152f5004a } diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java -index e108f876d3f129c6287f13d68427aed2a6f0c5b1..1a0ffbe2f835cbe37ef670d01daf08fb2f48b4fa 100644 +index be753557d7ebd6f1e82b1bdb6d60ecc450f72eec..83372c86bd54eedd9b136ddfcbfc67d303058c0a 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Panda.java +++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java -@@ -121,6 +121,54 @@ public class Panda extends Animal { +@@ -112,6 +112,54 @@ public class Panda extends Animal { } @@ -5093,9 +5071,9 @@ index e108f876d3f129c6287f13d68427aed2a6f0c5b1..1a0ffbe2f835cbe37ef670d01daf08fb + } + @Override - public boolean canTakeItem(ItemStack stack) { - EquipmentSlot enumitemslot = this.getEquipmentSlotForItem(stack); -@@ -282,6 +330,7 @@ public class Panda extends Animal { + protected boolean canDispenserEquipIntoSlot(EquipmentSlot slot) { + return slot == EquipmentSlot.MAINHAND && this.canPickUpLoot(); +@@ -271,6 +319,7 @@ public class Panda extends Animal { @Override protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); @@ -5103,7 +5081,7 @@ index e108f876d3f129c6287f13d68427aed2a6f0c5b1..1a0ffbe2f835cbe37ef670d01daf08fb this.goalSelector.addGoal(2, new Panda.PandaPanicGoal(this, 2.0D)); this.goalSelector.addGoal(2, new Panda.PandaBreedGoal(this, 1.0D)); this.goalSelector.addGoal(3, new Panda.PandaAttackGoal(this, 1.2000000476837158D, true)); -@@ -299,6 +348,7 @@ public class Panda extends Animal { +@@ -288,6 +337,7 @@ public class Panda extends Animal { this.goalSelector.addGoal(12, new Panda.PandaRollGoal(this)); this.goalSelector.addGoal(13, new FollowParentGoal(this, 1.25D)); this.goalSelector.addGoal(14, new WaterAvoidingRandomStrollGoal(this, 1.0D)); @@ -5111,7 +5089,7 @@ index e108f876d3f129c6287f13d68427aed2a6f0c5b1..1a0ffbe2f835cbe37ef670d01daf08fb this.targetSelector.addGoal(1, (new Panda.PandaHurtByTargetGoal(this, new Class[0])).setAlertOthers(new Class[0])); } -@@ -637,7 +687,10 @@ public class Panda extends Animal { +@@ -617,7 +667,10 @@ public class Panda extends Animal { public void setAttributes() { if (this.isWeak()) { @@ -5123,7 +5101,7 @@ index e108f876d3f129c6287f13d68427aed2a6f0c5b1..1a0ffbe2f835cbe37ef670d01daf08fb } if (this.isLazy()) { -@@ -660,7 +713,7 @@ public class Panda extends Animal { +@@ -640,7 +693,7 @@ public class Panda extends Animal { ItemStack itemstack = player.getItemInHand(hand); if (this.isScared()) { @@ -5131,27 +5109,24 @@ index e108f876d3f129c6287f13d68427aed2a6f0c5b1..1a0ffbe2f835cbe37ef670d01daf08fb + return tryRide(player, hand); // Purpur } else if (this.isOnBack()) { this.setOnBack(false); - return InteractionResult.sidedSuccess(this.level().isClientSide); -@@ -678,7 +731,7 @@ public class Panda extends Animal { - this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying - } else { - if (this.level().isClientSide || this.isSitting() || this.isInWater()) { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur + return InteractionResult.SUCCESS; +@@ -679,12 +732,12 @@ public class Panda extends Animal { + } } - this.tryToSit(); -@@ -697,7 +750,7 @@ public class Panda extends Animal { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } - return InteractionResult.SUCCESS; + return InteractionResult.SUCCESS_SERVER; } else { - return InteractionResult.PASS; + return tryRide(player, hand); // Purpur } } -@@ -742,7 +795,7 @@ public class Panda extends Animal { - return this.isBaby() ? Panda.BABY_DIMENSIONS : super.getDefaultDimensions(pose); +@@ -729,7 +782,7 @@ public class Panda extends Animal { + return itemEntity.getItem().is(ItemTags.PANDA_EATS_FROM_GROUND) && itemEntity.isAlive() && !itemEntity.hasPickUpDelay(); } - private static class PandaMoveControl extends MoveControl { @@ -5159,7 +5134,7 @@ index e108f876d3f129c6287f13d68427aed2a6f0c5b1..1a0ffbe2f835cbe37ef670d01daf08fb private final Panda panda; -@@ -752,9 +805,9 @@ public class Panda extends Animal { +@@ -739,9 +792,9 @@ public class Panda extends Animal { } @Override @@ -5172,10 +5147,10 @@ index e108f876d3f129c6287f13d68427aed2a6f0c5b1..1a0ffbe2f835cbe37ef670d01daf08fb } } diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java -index 97931bfd360725945ab9606ff698b518ae101076..82310253297d3046936ff4a29583c7c25177ebee 100644 +index 8883894da73c7d5975a8826d23ee7f542db98b0b..28a9d267099f6c24f71dc5a11179d59c27265a88 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java +++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java -@@ -124,12 +124,89 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder type, Level world) { super(type, world); @@ -5265,8 +5240,8 @@ index 97931bfd360725945ab9606ff698b518ae101076..82310253297d3046936ff4a29583c7c2 + @Nullable @Override - public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData) { -@@ -148,8 +225,11 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { -@@ -292,13 +373,13 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder type, LevelAccessor world, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random) { +@@ -294,13 +375,13 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder { -@@ -155,6 +194,17 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { +@@ -156,6 +195,17 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { public InteractionResult mobInteract(Player player, InteractionHand hand) { boolean flag = this.isFood(player.getItemInHand(hand)); @@ -5393,7 +5368,7 @@ index 03d29d5114237f5700c188510a12f26507844c3d..ce2a710fb258429a1aac3843b7afafea if (!this.level().isClientSide) { player.startRiding(this); diff --git a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java -index b69a2144769e598f0d70b0d5dfeb8af01ad740ca..4cf1fa73f082600dc1484bf6fe0b1361f65399db 100644 +index cd72d8f766069796ce1fe4a83b8646692005ff8c..86c44912a363401bdd716c22d24dfd7e92cfd0be 100644 --- a/src/main/java/net/minecraft/world/entity/animal/PolarBear.java +++ b/src/main/java/net/minecraft/world/entity/animal/PolarBear.java @@ -59,11 +59,82 @@ public class PolarBear extends Animal implements NeutralMob { @@ -5509,7 +5484,7 @@ index b69a2144769e598f0d70b0d5dfeb8af01ad740ca..4cf1fa73f082600dc1484bf6fe0b1361 this.targetSelector.addGoal(1, new PolarBear.PolarBearHurtByTargetGoal()); this.targetSelector.addGoal(2, new PolarBear.PolarBearAttackPlayersGoal()); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); -@@ -202,6 +281,12 @@ public class PolarBear extends Animal implements NeutralMob { +@@ -204,6 +283,12 @@ public class PolarBear extends Animal implements NeutralMob { if (!this.level().isClientSide) { this.updatePersistentAnger((ServerLevel)this.level(), true); } @@ -5522,7 +5497,7 @@ index b69a2144769e598f0d70b0d5dfeb8af01ad740ca..4cf1fa73f082600dc1484bf6fe0b1361 } @Override -@@ -221,6 +306,7 @@ public class PolarBear extends Animal implements NeutralMob { +@@ -223,6 +308,7 @@ public class PolarBear extends Animal implements NeutralMob { public void setStanding(boolean warning) { this.entityData.set(DATA_STANDING_ID, warning); @@ -5531,10 +5506,10 @@ index b69a2144769e598f0d70b0d5dfeb8af01ad740ca..4cf1fa73f082600dc1484bf6fe0b1361 public float getStandingAnimationScale(float tickDelta) { diff --git a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java -index 3f0fad476fe573c3ba946a9436d1b3f7c5260ee2..c758f759ccae81b7651bfcba254f54335f2c7cc8 100644 +index cdb74f86ee92ee143af29962a85d45ca585cee44..c5a39ea2ad0e5e5ac434d79c1a57e0068b8bc809 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java +++ b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java -@@ -51,6 +51,33 @@ public class Pufferfish extends AbstractFish { +@@ -52,6 +52,33 @@ public class Pufferfish extends AbstractFish { this.refreshDimensions(); } @@ -5569,10 +5544,10 @@ index 3f0fad476fe573c3ba946a9436d1b3f7c5260ee2..c758f759ccae81b7651bfcba254f5433 protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); diff --git a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java -index 0109c8ed8bf6a053674456fa4473934e028ca418..459c0c95a27ddeb72e8714d3c2fcae1870051b3c 100644 +index 8cc6022507c97af62fb2b4455198bc35744137c9..b3a0146ccfcda9fa33b91d33458086b510bb4d7b 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Rabbit.java +++ b/src/main/java/net/minecraft/world/entity/animal/Rabbit.java -@@ -89,6 +89,7 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -88,6 +88,7 @@ public class Rabbit extends Animal implements VariantHolder { private boolean wasOnGround; private int jumpDelayTicks; public int moreCarrotTicks; @@ -5580,7 +5555,7 @@ index 0109c8ed8bf6a053674456fa4473934e028ca418..459c0c95a27ddeb72e8714d3c2fcae18 public Rabbit(EntityType type, Level world) { super(type, world); -@@ -96,9 +97,76 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -95,9 +96,76 @@ public class Rabbit extends Animal implements VariantHolder { this.moveControl = new Rabbit.RabbitMoveControl(this); } @@ -5657,7 +5632,7 @@ index 0109c8ed8bf6a053674456fa4473934e028ca418..459c0c95a27ddeb72e8714d3c2fcae18 this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level())); this.goalSelector.addGoal(1, new Rabbit.RabbitPanicGoal(this, 2.2D)); this.goalSelector.addGoal(2, new BreedGoal(this, 0.8D)); -@@ -115,6 +183,14 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -114,6 +182,14 @@ public class Rabbit extends Animal implements VariantHolder { @Override protected float getJumpPower() { @@ -5672,21 +5647,20 @@ index 0109c8ed8bf6a053674456fa4473934e028ca418..459c0c95a27ddeb72e8714d3c2fcae18 float f = 0.3F; if (this.horizontalCollision || this.moveControl.hasWanted() && this.moveControl.getWantedY() > this.getY() + 0.5D) { -@@ -189,6 +265,13 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -188,6 +264,12 @@ public class Rabbit extends Animal implements VariantHolder { @Override - public void customServerAiStep() { + public void customServerAiStep(ServerLevel world) { + // Purpur start + if (getRider() != null && this.isControllable()) { + handleJumping(); + return; + } + // Purpur end -+ if (this.jumpDelayTicks > 0) { --this.jumpDelayTicks; } -@@ -403,10 +486,23 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -402,10 +484,23 @@ public class Rabbit extends Animal implements VariantHolder { } this.setVariant(entityrabbit_variant); @@ -5710,7 +5684,7 @@ index 0109c8ed8bf6a053674456fa4473934e028ca418..459c0c95a27ddeb72e8714d3c2fcae18 Holder holder = world.getBiome(pos); int i = world.getRandom().nextInt(100); -@@ -470,7 +566,7 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -469,7 +564,7 @@ public class Rabbit extends Animal implements VariantHolder { } } @@ -5719,7 +5693,7 @@ index 0109c8ed8bf6a053674456fa4473934e028ca418..459c0c95a27ddeb72e8714d3c2fcae18 private final Rabbit rabbit; private double nextJumpSpeed; -@@ -481,14 +577,14 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -480,14 +575,14 @@ public class Rabbit extends Animal implements VariantHolder { } @Override @@ -5736,21 +5710,21 @@ index 0109c8ed8bf6a053674456fa4473934e028ca418..459c0c95a27ddeb72e8714d3c2fcae18 } @Override -@@ -550,7 +646,7 @@ public class Rabbit extends Animal implements VariantHolder { +@@ -549,7 +644,7 @@ public class Rabbit extends Animal implements VariantHolder { @Override public boolean canUse() { if (this.nextStartTick <= 0) { -- if (!this.rabbit.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ if (!this.rabbit.level().purpurConfig.rabbitBypassMobGriefing && !this.rabbit.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur +- if (!getServerLevel((Entity) this.rabbit).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (!getServerLevel((Entity) this.rabbit).purpurConfig.rabbitBypassMobGriefing == !getServerLevel((Entity) this.rabbit).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur return false; } diff --git a/src/main/java/net/minecraft/world/entity/animal/Salmon.java b/src/main/java/net/minecraft/world/entity/animal/Salmon.java -index 0af79daa357f53a8871e293b57e16c099e5d3f64..382e47f26ee94506cb76463a677351b9bdcf8040 100644 +index 661997c39df777b6e332f0a5710e7f63a116a499..1a0c71ed6f3bd3d961f9b30ab29a62d683195355 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Salmon.java +++ b/src/main/java/net/minecraft/world/entity/animal/Salmon.java -@@ -13,6 +13,33 @@ public class Salmon extends AbstractSchoolingFish { - super(type, world); +@@ -32,6 +32,33 @@ public class Salmon extends AbstractSchoolingFish implements VariantHolder { -@@ -257,7 +296,7 @@ public class Sheep extends Animal implements Shearable { - if (!this.level().isClientSide && this.readyForShearing()) { - // CraftBukkit start - // Paper start - custom shear drops -- java.util.List drops = this.generateDefaultDrops(); -+ java.util.List drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.LOOTING, itemstack)); // Purpur - org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); - if (event != null) { - if (event.isCancelled()) { -@@ -282,12 +321,13 @@ public class Sheep extends Animal implements Shearable { - @Override - public void shear(SoundSource shearedSoundCategory) { - // Paper start - custom shear drops -- this.shear(shearedSoundCategory, this.generateDefaultDrops()); -+ this.shear(shearedSoundCategory, this.generateDefaultDrops(0)); // Purpur - } - - @Override -- public java.util.List generateDefaultDrops() { -+ public java.util.List generateDefaultDrops(int looting) { // Purpur - int count = 1 + this.random.nextInt(3); -+ if (org.purpurmc.purpur.PurpurConfig.allowShearsLooting) count += looting; // Purpur - java.util.List dropEntities = new java.util.ArrayList<>(count); - for (int j = 0; j < count; ++j) { - dropEntities.add(new ItemStack(Sheep.ITEM_BY_DYE.get(this.getColor()))); diff --git a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java -index 5c2ed3c39c8eb850f3be1e2ea5b5a7ea266e16d1..7bd2d2b9bb1275fa8e4bdc6d498a59e47838930f 100644 +index fd9f6c17448a4d87f940eb8f544ecb9669068582..13eecc676e33623e776d32495969f111bf6c0e44 100644 --- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java +++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java -@@ -47,17 +47,57 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM +@@ -50,17 +50,57 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM private static final EntityDataAccessor DATA_PUMPKIN_ID = SynchedEntityData.defineId(SnowGolem.class, EntityDataSerializers.BYTE); private static final byte PUMPKIN_FLAG = 16; @@ -5922,10 +5871,10 @@ index 5c2ed3c39c8eb850f3be1e2ea5b5a7ea266e16d1..7bd2d2b9bb1275fa8e4bdc6d498a59e4 this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 6.0F)); this.goalSelector.addGoal(4, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (entityliving) -> { + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (entityliving, worldserver) -> { return entityliving instanceof Enemy; })); -@@ -77,6 +117,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM +@@ -80,6 +120,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM public void addAdditionalSaveData(CompoundTag nbt) { super.addAdditionalSaveData(nbt); nbt.putBoolean("Pumpkin", this.hasPumpkin()); @@ -5933,7 +5882,7 @@ index 5c2ed3c39c8eb850f3be1e2ea5b5a7ea266e16d1..7bd2d2b9bb1275fa8e4bdc6d498a59e4 } @Override -@@ -85,12 +126,13 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM +@@ -88,12 +129,13 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM if (nbt.contains("Pumpkin")) { this.setPumpkin(nbt.getBoolean("Pumpkin")); } @@ -5948,12 +5897,12 @@ index 5c2ed3c39c8eb850f3be1e2ea5b5a7ea266e16d1..7bd2d2b9bb1275fa8e4bdc6d498a59e4 } @Override -@@ -101,10 +143,11 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM - this.hurt(this.damageSources().melting(), 1.0F); // CraftBukkit - DamageSources.ON_FIRE -> CraftEventFactory.MELTING +@@ -106,10 +148,11 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM + this.hurtServer(worldserver, this.damageSources().melting(), 1.0F); // CraftBukkit - DamageSources.ON_FIRE -> CraftEventFactory.MELTING } -- if (!this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ if (!this.level().purpurConfig.snowGolemBypassMobGriefing && !this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur +- if (!worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (!worldserver.purpurConfig.snowGolemBypassMobGriefing == !worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur return; } @@ -5961,24 +5910,19 @@ index 5c2ed3c39c8eb850f3be1e2ea5b5a7ea266e16d1..7bd2d2b9bb1275fa8e4bdc6d498a59e4 BlockState iblockdata = Blocks.SNOW.defaultBlockState(); for (int i = 0; i < 4; ++i) { -@@ -147,11 +190,11 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM - if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { - // CraftBukkit start - // Paper start - custom shear drops -- java.util.List drops = this.generateDefaultDrops(); -+ java.util.List drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.LOOTING, itemstack)); // Purpur - org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); - if (event != null) { - if (event.isCancelled()) { -- return InteractionResult.PASS; -+ return tryRide(player, hand); // Purpur - } - drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops()); - } -@@ -164,19 +207,36 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM +@@ -166,7 +209,7 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM + org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); + if (event != null) { + if (event.isCancelled()) { +- return InteractionResult.PASS; ++ return tryRide(player, hand); // Purpur + } + drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops()); + // Paper end - custom shear drops +@@ -178,8 +221,16 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM } - return InteractionResult.sidedSuccess(this.level().isClientSide); + return InteractionResult.SUCCESS; + // Purpur start + } else if (level().purpurConfig.snowGolemPutPumpkinBack && !hasPumpkin() && itemstack.getItem() == Blocks.CARVED_PUMPKIN.asItem()) { + setPumpkin(true); @@ -5993,33 +5937,11 @@ index 5c2ed3c39c8eb850f3be1e2ea5b5a7ea266e16d1..7bd2d2b9bb1275fa8e4bdc6d498a59e4 } } - @Override - public void shear(SoundSource shearedSoundCategory) { - // Paper start - custom shear drops -- this.shear(shearedSoundCategory, this.generateDefaultDrops()); -+ this.shear(shearedSoundCategory, this.generateDefaultDrops(0)); // Purpur - } - - @Override -- public java.util.List generateDefaultDrops() { -+ // Purpur start -+ public java.util.List generateDefaultDrops(int looting) { -+ if (org.purpurmc.purpur.PurpurConfig.allowShearsLooting) { -+ java.util.ArrayList list = new java.util.ArrayList<>(); -+ for (int i = 0; i < 1 + looting; i++) { -+ list.add(new ItemStack(Items.CARVED_PUMPKIN)); -+ } -+ return java.util.Collections.unmodifiableList(list); -+ } -+ // Purpur end - return java.util.Collections.singletonList(new ItemStack(Items.CARVED_PUMPKIN)); - } - diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java -index 42f4e544fe7fbc342f15eacb5e38d40849e3c419..3ca9a7f289d8c3f0b0df8f1cd4a5ca1254653c50 100644 +index f9fdc600dc680c55219fcbf9bc8f151a733a093c..36a56553702fa6e4a2ac92b3639c210c94faee73 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Squid.java +++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java -@@ -41,13 +41,67 @@ public class Squid extends WaterAnimal { +@@ -46,13 +46,67 @@ public class Squid extends AgeableWaterCreature { public Squid(EntityType type, Level world) { super(type, world); @@ -6088,7 +6010,7 @@ index 42f4e544fe7fbc342f15eacb5e38d40849e3c419..3ca9a7f289d8c3f0b0df8f1cd4a5ca12 this.goalSelector.addGoal(1, new Squid.SquidFleeGoal()); } -@@ -116,6 +170,7 @@ public class Squid extends WaterAnimal { +@@ -127,6 +181,7 @@ public class Squid extends AgeableWaterCreature { } if (this.isInWaterOrBubble()) { @@ -6096,7 +6018,7 @@ index 42f4e544fe7fbc342f15eacb5e38d40849e3c419..3ca9a7f289d8c3f0b0df8f1cd4a5ca12 if (this.tentacleMovement < (float) Math.PI) { float f = this.tentacleMovement / (float) Math.PI; this.tentacleAngle = Mth.sin(f * f * (float) Math.PI) * (float) Math.PI * 0.25F; -@@ -289,10 +344,41 @@ public class Squid extends WaterAnimal { +@@ -305,10 +360,41 @@ public class Squid extends AgeableWaterCreature { @Override public void tick() { @@ -6124,23 +6046,23 @@ index 42f4e544fe7fbc342f15eacb5e38d40849e3c419..3ca9a7f289d8c3f0b0df8f1cd4a5ca12 + } + } + if (forward != 0.0F || strafe != 0.0F) { -+ squid.setMovementVector((float) dir.getX(), (float) dir.getY(), (float) dir.getZ()); ++ squid.movementVector = new Vec3((float) dir.getX(), (float) dir.getY(), (float) dir.getZ()); + } else { -+ squid.setMovementVector(0.0F, 0.0F, 0.0F); ++ squid.movementVector = Vec3.ZERO; + } + return; + } + // Purpur end int i = this.squid.getNoActionTime(); if (i > 100) { - this.squid.setMovementVector(0.0F, 0.0F, 0.0F); + this.squid.movementVector = Vec3.ZERO; - } else if (this.squid.getRandom().nextInt(reducedTickDelay(50)) == 0 || !this.squid.wasTouchingWater || !this.squid.hasMovementVector()) { + } else if (this.squid.getRandom().nextInt(reducedTickDelay(50)) == 0 || !this.squid.isInWater() || !this.squid.hasMovementVector()) { // Purpur float f = this.squid.getRandom().nextFloat() * (float) (Math.PI * 2); - float g = Mth.cos(f) * 0.2F; - float h = -0.1F + this.squid.getRandom().nextFloat() * 0.2F; + this.squid.movementVector = new Vec3( + (double)(Mth.cos(f) * 0.2F), (double)(-0.1F + this.squid.getRandom().nextFloat() * 0.2F), (double)(Mth.sin(f) * 0.2F) diff --git a/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java b/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java -index 3d03ffe2e12eca82dfa2f414471d12bb362d4552..2d04addd17d2c358fff598012b323cd7d8bf007e 100644 +index 8d59d606bdaaea7c64389572b2810b65414a1533..7f9d3177285f6496c4313da63f0fd0cc78266586 100644 --- a/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java +++ b/src/main/java/net/minecraft/world/entity/animal/TropicalFish.java @@ -67,6 +67,33 @@ public class TropicalFish extends AbstractSchoolingFish implements VariantHolder @@ -6178,10 +6100,10 @@ index 3d03ffe2e12eca82dfa2f414471d12bb362d4552..2d04addd17d2c358fff598012b323cd7 return "entity.minecraft.tropical_fish.predefined." + variant; } diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index 4bfa947531c4a67989e18032754dabf4c69e989c..55d83c57d76e73d73dca1400f4c0c18661d49a94 100644 +index d6605c15111dbdb6ee61a24822bc0a9aed7198d6..c9e307452a097329c26893673055cfb72a43e4c7 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java +++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -@@ -87,6 +87,44 @@ public class Turtle extends Animal { +@@ -86,6 +86,44 @@ public class Turtle extends Animal { this.moveControl = new Turtle.TurtleMoveControl(this); } @@ -6226,7 +6148,7 @@ index 4bfa947531c4a67989e18032754dabf4c69e989c..55d83c57d76e73d73dca1400f4c0c186 public void setHomePos(BlockPos pos) { this.entityData.set(Turtle.HOME_POS, pos); } -@@ -189,6 +227,7 @@ public class Turtle extends Animal { +@@ -188,6 +226,7 @@ public class Turtle extends Animal { @Override protected void registerGoals() { @@ -6234,7 +6156,7 @@ index 4bfa947531c4a67989e18032754dabf4c69e989c..55d83c57d76e73d73dca1400f4c0c186 this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2D)); this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0D)); this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0D)); -@@ -342,13 +381,15 @@ public class Turtle extends Animal { +@@ -349,13 +388,15 @@ public class Turtle extends Animal { return this.isBaby() ? Turtle.BABY_DIMENSIONS : super.getDefaultDimensions(pose); } @@ -6251,7 +6173,7 @@ index 4bfa947531c4a67989e18032754dabf4c69e989c..55d83c57d76e73d73dca1400f4c0c186 } private void updateSpeed() { -@@ -368,7 +409,7 @@ public class Turtle extends Animal { +@@ -375,7 +416,7 @@ public class Turtle extends Animal { } @Override @@ -6260,7 +6182,7 @@ index 4bfa947531c4a67989e18032754dabf4c69e989c..55d83c57d76e73d73dca1400f4c0c186 this.updateSpeed(); if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) { double d0 = this.wantedX - this.turtle.getX(); -@@ -384,7 +425,7 @@ public class Turtle extends Animal { +@@ -391,7 +432,7 @@ public class Turtle extends Animal { this.turtle.setYRot(this.rotlerp(this.turtle.getYRot(), f, 90.0F)); this.turtle.yBodyRot = this.turtle.getYRot(); @@ -6270,16 +6192,16 @@ index 4bfa947531c4a67989e18032754dabf4c69e989c..55d83c57d76e73d73dca1400f4c0c186 this.turtle.setSpeed(Mth.lerp(0.125F, this.turtle.getSpeed(), f1)); this.turtle.setDeltaMovement(this.turtle.getDeltaMovement().add(0.0D, (double) this.turtle.getSpeed() * d1 * 0.1D, 0.0D)); diff --git a/src/main/java/net/minecraft/world/entity/animal/Wolf.java b/src/main/java/net/minecraft/world/entity/animal/Wolf.java -index 22024d79b566ad5d388ceb644605ada3123ca608..ba6036633c1977b7f41b3bd0dd31370924b4bf35 100644 +index fb84ee1225cd762ef306d1fc3e1baed42c034a3c..420345f130a40c4f59a021a4bdce3e218dc87cde 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Wolf.java +++ b/src/main/java/net/minecraft/world/entity/animal/Wolf.java -@@ -107,6 +107,37 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder RABID_PREDICATE = entity -> entity instanceof net.minecraft.server.level.ServerPlayer || entity instanceof Mob; ++ private static final TargetingConditions.Selector RABID_PREDICATE = (entity, ignored) -> entity instanceof net.minecraft.server.level.ServerPlayer || entity instanceof net.minecraft.world.entity.Mob; + private final net.minecraft.world.entity.ai.goal.Goal PATHFINDER_VANILLA = new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR); + private final net.minecraft.world.entity.ai.goal.Goal PATHFINDER_RABID = new NonTameRandomTargetGoal<>(this, LivingEntity.class, false, RABID_PREDICATE); + private static final class AvoidRabidWolfGoal extends AvoidEntityGoal { @@ -6311,7 +6233,7 @@ index 22024d79b566ad5d388ceb644605ada3123ca608..ba6036633c1977b7f41b3bd0dd313709 private static final float START_HEALTH = 8.0F; private static final float TAME_HEALTH = 40.0F; private static final float ARMOR_REPAIR_UNIT = 0.125F; -@@ -127,12 +158,87 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR)); this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, AbstractSkeleton.class, false)); this.targetSelector.addGoal(8, new ResetUniversalAngerTargetGoal<>(this, true)); -@@ -194,6 +301,7 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder { nbt.putString("variant", resourcekey.location().toString()); }); -@@ -211,6 +319,10 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder, B this.lookControl = new Axolotl.AxolotlLookControl(this, 20); } @@ -6621,7 +6543,6 @@ index c75dccb977e0d620e3834ca0197e8fd51bf3bfd4..15d4ff5ed6ceb7c9ad312f8c01be6f28 + protected void registerGoals() { + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + } -+ // Purpur end + + @Override + public void initAttributes() { @@ -6643,20 +6564,21 @@ index c75dccb977e0d620e3834ca0197e8fd51bf3bfd4..15d4ff5ed6ceb7c9ad312f8c01be6f28 + protected boolean isAlwaysExperienceDropper() { + return this.level().purpurConfig.axolotlAlwaysDropExp; + } ++ // Purpur end + @Override - public Map getModelRotationValues() { - return this.modelRotationValues; -@@ -272,7 +310,7 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder, B private int behaviorTick = 0; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { - if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish + if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel) this.level(), this); + this.getBrain().tick(world, this); AxolotlAi.updateActivity(this); if (!this.isNoAi()) { -@@ -495,14 +533,22 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder, B private static class AxolotlMoveControl extends SmoothSwimmingMoveControl { private final Axolotl axolotl; @@ -6679,7 +6601,7 @@ index c75dccb977e0d620e3834ca0197e8fd51bf3bfd4..15d4ff5ed6ceb7c9ad312f8c01be6f28 if (!this.axolotl.isPlayingDead()) { super.tick(); } -@@ -517,9 +563,9 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder, B } @Override @@ -6692,10 +6614,10 @@ index c75dccb977e0d620e3834ca0197e8fd51bf3bfd4..15d4ff5ed6ceb7c9ad312f8c01be6f28 } diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java -index c841a7c4d73a416d4722b4d409167ddba3304ae8..5a704a4c815e6670c93c750bc9f0e22100cd6923 100644 +index 002e8b5a7037e48a7d9bd84c321b152f40fe1fce..542b972b266eae642b220025c6173c738fcff80f 100644 --- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java +++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java -@@ -87,6 +87,17 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl +@@ -85,6 +85,17 @@ public class Camel extends AbstractHorse { navigation.setCanWalkOverFences(true); } @@ -6713,7 +6635,7 @@ index c841a7c4d73a416d4722b4d409167ddba3304ae8..5a704a4c815e6670c93c750bc9f0e221 @Override public void addAdditionalSaveData(CompoundTag nbt) { super.addAdditionalSaveData(nbt); -@@ -308,6 +319,23 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl +@@ -306,6 +317,23 @@ public class Camel extends AbstractHorse { return this.dashCooldown; } @@ -6738,10 +6660,10 @@ index c841a7c4d73a416d4722b4d409167ddba3304ae8..5a704a4c815e6670c93c750bc9f0e221 protected SoundEvent getAmbientSound() { return SoundEvents.CAMEL_AMBIENT; diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java -index 29df5e116f8a7061081250622fd367e49e5e7171..7c4e7d55874fa968d52eab683e9979ba38e91c2e 100644 +index e6e12142c24e7fff99423678bc47c2e1d38e8afd..0f077f9be003a17b77e9b29fa2f398a4de1fa3c5 100644 --- a/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java +++ b/src/main/java/net/minecraft/world/entity/animal/frog/Frog.java -@@ -103,6 +103,8 @@ public class Frog extends Animal implements VariantHolder> { +@@ -104,6 +104,8 @@ public class Frog extends Animal implements VariantHolder> { public final AnimationState croakAnimationState = new AnimationState(); public final AnimationState tongueAnimationState = new AnimationState(); public final AnimationState swimIdleAnimationState = new AnimationState(); @@ -6750,7 +6672,7 @@ index 29df5e116f8a7061081250622fd367e49e5e7171..7c4e7d55874fa968d52eab683e9979ba public Frog(EntityType type, Level world) { super(type, world); -@@ -110,6 +112,58 @@ public class Frog extends Animal implements VariantHolder> { +@@ -111,6 +113,58 @@ public class Frog extends Animal implements VariantHolder> { this.setPathfindingMalus(PathType.WATER, 4.0F); this.setPathfindingMalus(PathType.TRAPDOOR, -1.0F); this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true); @@ -6809,16 +6731,16 @@ index 29df5e116f8a7061081250622fd367e49e5e7171..7c4e7d55874fa968d52eab683e9979ba } @Override -@@ -184,7 +238,7 @@ public class Frog extends Animal implements VariantHolder> { +@@ -185,7 +239,7 @@ public class Frog extends Animal implements VariantHolder> { private int behaviorTick = 0; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { - if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish + if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel)this.level(), this); + this.getBrain().tick(world, this); FrogAi.updateActivity(this); - super.customServerAiStep(); -@@ -369,7 +423,7 @@ public class Frog extends Animal implements VariantHolder> { + super.customServerAiStep(world); +@@ -379,7 +433,7 @@ public class Frog extends Animal implements VariantHolder> { return world.getBlockState(pos.below()).is(BlockTags.FROGS_SPAWNABLE_ON) && isBrightEnoughToSpawn(world, pos); } @@ -6828,10 +6750,10 @@ index 29df5e116f8a7061081250622fd367e49e5e7171..7c4e7d55874fa968d52eab683e9979ba super(entity); } diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java -index d3cf26a3bdf40f6c827880bc394e7034a1adf4dc..c51637514bf671c08dbe4e5ac55566b92b5876f9 100644 +index db617182d75f3418fef4b34cd8eddbfc90fc5a9e..2b3e722a5c802fbbebb339df4398905e144fd174 100644 --- a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java +++ b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java -@@ -51,13 +51,50 @@ public class Tadpole extends AbstractFish { +@@ -49,13 +49,50 @@ public class Tadpole extends AbstractFish { protected static final ImmutableList>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.FROG_TEMPTATIONS); protected static final ImmutableList> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.PATH, MemoryModuleType.NEAREST_VISIBLE_ADULT, MemoryModuleType.TEMPTATION_COOLDOWN_TICKS, MemoryModuleType.IS_TEMPTED, MemoryModuleType.TEMPTING_PLAYER, MemoryModuleType.BREED_TARGET, MemoryModuleType.IS_PANICKING); public boolean ageLocked; // Paper @@ -6883,21 +6805,21 @@ index d3cf26a3bdf40f6c827880bc394e7034a1adf4dc..c51637514bf671c08dbe4e5ac55566b9 @Override protected PathNavigation createNavigation(Level world) { return new WaterBoundPathNavigation(this, world); -@@ -86,7 +123,7 @@ public class Tadpole extends AbstractFish { +@@ -84,7 +121,7 @@ public class Tadpole extends AbstractFish { private int behaviorTick = 0; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { - if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish + if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel) this.level(), this); + this.getBrain().tick(world, this); TadpoleAi.updateActivity(this); - super.customServerAiStep(); + super.customServerAiStep(world); diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java -index 79ef4a1a4f4d404121087e2e6bcc3855556a88db..47edb3ee02eeb0e2e6a2d817ab8193dc26cd2bec 100644 +index 509d1d1497c3f015686dbc485b82649a98356a02..e9a42f8a73e17c6a7fe5603686c67424e1f8ed9b 100644 --- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java +++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java @@ -91,6 +91,38 @@ public class Goat extends Animal { - return InstrumentItem.create(Items.GOAT_HORN, (Holder) holderset.getRandomElement(randomsource).get()); + }); } + // Purpur start @@ -6938,12 +6860,12 @@ index 79ef4a1a4f4d404121087e2e6bcc3855556a88db..47edb3ee02eeb0e2e6a2d817ab8193dc @@ -193,7 +225,7 @@ public class Goat extends Animal { private int behaviorTick = 0; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { - if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish + if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel) this.level(), this); + this.getBrain().tick(world, this); GoatAi.updateActivity(this); - super.customServerAiStep(); + super.customServerAiStep(world); @@ -393,6 +425,7 @@ public class Goat extends Animal { // Paper start - Goat ram API @@ -6953,10 +6875,10 @@ index 79ef4a1a4f4d404121087e2e6bcc3855556a88db..47edb3ee02eeb0e2e6a2d817ab8193dc brain.setMemory(MemoryModuleType.RAM_TARGET, entity.position()); brain.eraseMemory(MemoryModuleType.RAM_COOLDOWN_TICKS); diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index 1f5ed236fb7c0c1b0181675747d25d233f534284..4eec1fe4e5996817c26c4f7e701e97fd5d8dcf60 100644 +index 8aed30cdbbfdd42c20dcd4c8773c8a0ee21a980d..b258be16f32ffd58ac8406deac9423cb01ca9a5c 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -219,11 +219,59 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -228,11 +228,59 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, protected AbstractHorse(EntityType type, Level world) { super(type, world); @@ -7016,7 +6938,7 @@ index 1f5ed236fb7c0c1b0181675747d25d233f534284..4eec1fe4e5996817c26c4f7e701e97fd this.goalSelector.addGoal(1, new PanicGoal(this, 1.2D)); this.goalSelector.addGoal(1, new RunAroundLikeCrazyGoal(this, 1.2D)); this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D, AbstractHorse.class)); -@@ -234,6 +282,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -243,6 +291,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, if (this.canPerformRearing()) { this.goalSelector.addGoal(9, new RandomStandGoal(this)); } @@ -7024,7 +6946,7 @@ index 1f5ed236fb7c0c1b0181675747d25d233f534284..4eec1fe4e5996817c26c4f7e701e97fd this.addBehaviourGoals(); } -@@ -1250,7 +1299,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, +@@ -1269,7 +1318,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, entityData = new AgeableMob.AgeableMobGroupData(0.2F); } @@ -7034,10 +6956,10 @@ index 1f5ed236fb7c0c1b0181675747d25d233f534284..4eec1fe4e5996817c26c4f7e701e97fd } diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java b/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java -index ff02169ba14f5264cea8beaf1779e2890c5d74b8..94021abe521aea4a70f5eaa78fb05f9f71b7c38c 100644 +index 5cafdde956d7a5b00cd5aec5c44849639307363d..dbf9fa551023cc9bf634fd5f5d504c4d689264cd 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/Donkey.java -@@ -15,6 +15,43 @@ public class Donkey extends AbstractChestedHorse { +@@ -16,6 +16,43 @@ public class Donkey extends AbstractChestedHorse { super(type, world); } @@ -7082,10 +7004,10 @@ index ff02169ba14f5264cea8beaf1779e2890c5d74b8..94021abe521aea4a70f5eaa78fb05f9f protected SoundEvent getAmbientSound() { return SoundEvents.DONKEY_AMBIENT; diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java b/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java -index b1188d05700cafc3a6956171bacde4962d6659be..d51d5fa03232c674fa4b4ed6b8e15ce3a40d2732 100644 +index b5ec7c8ad0e482930d1a54b590b26093f4e477ea..780cad91fff78bda6264cfd78ff7a408a79e8a2f 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/Horse.java -@@ -45,6 +45,43 @@ public class Horse extends AbstractHorse implements VariantHolder { +@@ -43,6 +43,43 @@ public class Horse extends AbstractHorse implements VariantHolder { super(type, world); } @@ -7130,10 +7052,10 @@ index b1188d05700cafc3a6956171bacde4962d6659be..d51d5fa03232c674fa4b4ed6b8e15ce3 protected void randomizeAttributes(RandomSource random) { this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)generateMaxHealth(random::nextInt)); diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -index cf6a3a63b6f2b96943c0f399e8c82d293fee31ba..7714d7f74836e5a765867fa0339c41fdce703863 100644 +index 18bd483fe46de3d9dc129bffbccfba9d4cab9550..8401c7ae749f6300281cbd6b2bfc77f03d5eb9ea 100644 --- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java +++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -@@ -75,10 +75,85 @@ public class Llama extends AbstractChestedHorse implements VariantHolder type, Level world) { super(type, world); + this.getNavigation().setRequiredPathLength(40.0F); this.maxDomestication = 30; // Paper - Missing entity API; configure max temper instead of a hardcoded value + // Purpur start + this.moveControl = new org.purpurmc.purpur.controller.MoveControllerWASD(this) { @@ -7184,7 +7107,7 @@ index cf6a3a63b6f2b96943c0f399e8c82d293fee31ba..7714d7f74836e5a765867fa0339c41fd + + @Override + public boolean isSaddled() { -+ return super.isSaddled() || (isTamed() && getSwag() != null); ++ return super.isSaddled() || (isTamed()); + } + // Purpur end + @@ -7219,7 +7142,7 @@ index cf6a3a63b6f2b96943c0f399e8c82d293fee31ba..7714d7f74836e5a765867fa0339c41fd } public boolean isTraderLlama() { -@@ -109,6 +184,7 @@ public class Llama extends AbstractChestedHorse implements VariantHolder entitytypes, Level world) { super(EntityType.ENDER_DRAGON, world); -@@ -130,6 +131,37 @@ public class EnderDragon extends Mob implements Enemy { - this.noCulling = true; +@@ -129,6 +130,37 @@ public class EnderDragon extends Mob implements Enemy { + this.noPhysics = true; this.phaseManager = new EnderDragonPhaseManager(this); - this.explosionSource = new Explosion(world, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.BlockInteraction.DESTROY, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE); // CraftBukkit + this.explosionSource = new ServerExplosion(world.getMinecraftWorld(), this, null, null, new Vec3(Double.NaN, Double.NaN, Double.NaN), Float.NaN, true, Explosion.BlockInteraction.DESTROY); // CraftBukkit + + // Purpur start + this.moveControl = new org.purpurmc.purpur.controller.FlyingMoveControllerWASD(this) { @@ -7717,7 +7640,7 @@ index 5868d2e9e05a698c77117cf87c79b636b50fe289..573ec75b5fed1c3d30aa9dc64cf3a8a7 } public void setDragonFight(EndDragonFight fight) { -@@ -144,6 +176,27 @@ public class EnderDragon extends Mob implements Enemy { +@@ -143,6 +175,27 @@ public class EnderDragon extends Mob implements Enemy { return this.fightOrigin; } @@ -7745,7 +7668,7 @@ index 5868d2e9e05a698c77117cf87c79b636b50fe289..573ec75b5fed1c3d30aa9dc64cf3a8a7 public static AttributeSupplier.Builder createAttributes() { return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0D); } -@@ -205,6 +258,37 @@ public class EnderDragon extends Mob implements Enemy { +@@ -184,6 +237,37 @@ public class EnderDragon extends Mob implements Enemy { @Override public void aiStep() { @@ -7783,7 +7706,7 @@ index 5868d2e9e05a698c77117cf87c79b636b50fe289..573ec75b5fed1c3d30aa9dc64cf3a8a7 this.processFlappingMovement(); if (this.level().isClientSide) { this.setHealth(this.getHealth()); -@@ -231,6 +315,8 @@ public class EnderDragon extends Mob implements Enemy { +@@ -210,6 +294,8 @@ public class EnderDragon extends Mob implements Enemy { float f; if (this.isDeadOrDying()) { @@ -7792,7 +7715,7 @@ index 5868d2e9e05a698c77117cf87c79b636b50fe289..573ec75b5fed1c3d30aa9dc64cf3a8a7 float f1 = (this.random.nextFloat() - 0.5F) * 8.0F; f = (this.random.nextFloat() - 0.5F) * 4.0F; -@@ -243,9 +329,9 @@ public class EnderDragon extends Mob implements Enemy { +@@ -222,9 +308,9 @@ public class EnderDragon extends Mob implements Enemy { f = 0.2F / ((float) vec3d.horizontalDistance() * 10.0F + 1.0F); f *= (float) Math.pow(2.0D, vec3d.y); @@ -7804,44 +7727,44 @@ index 5868d2e9e05a698c77117cf87c79b636b50fe289..573ec75b5fed1c3d30aa9dc64cf3a8a7 this.flapTime += f * 0.5F; } else { this.flapTime += f; -@@ -279,7 +365,7 @@ public class EnderDragon extends Mob implements Enemy { - } +@@ -240,7 +326,7 @@ public class EnderDragon extends Mob implements Enemy { + float f4; + float f5; - this.phaseManager.getCurrentPhase().doClientTick(); -- } else { -+ } else if (!hasRider) { // Purpur +- if (world1 instanceof ServerLevel) { ++ if (world1 instanceof ServerLevel && !hasRider) { // Purpur + ServerLevel worldserver1 = (ServerLevel) world1; DragonPhaseInstance idragoncontroller = this.phaseManager.getCurrentPhase(); - idragoncontroller.doServerTick(); -@@ -353,7 +439,7 @@ public class EnderDragon extends Mob implements Enemy { - if (world1 instanceof ServerLevel) { - ServerLevel worldserver1 = (ServerLevel) world1; +@@ -326,7 +412,7 @@ public class EnderDragon extends Mob implements Enemy { + if (world2 instanceof ServerLevel) { + ServerLevel worldserver2 = (ServerLevel) world2; - if (this.hurtTime == 0) { + if (!hasRider && this.hurtTime == 0) { // Purpur - this.knockBack(worldserver1, worldserver1.getEntities((Entity) this, this.wing1.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); - this.knockBack(worldserver1, worldserver1.getEntities((Entity) this, this.wing2.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); - this.hurt(worldserver1.getEntities((Entity) this, this.head.getBoundingBox().inflate(1.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); -@@ -398,7 +484,7 @@ public class EnderDragon extends Mob implements Enemy { - } - - if (!this.level().isClientSide) { -- this.inWall = this.checkWalls(this.head.getBoundingBox()) | this.checkWalls(this.neck.getBoundingBox()) | this.checkWalls(this.body.getBoundingBox()); -+ this.inWall = !hasRider && this.checkWalls(this.head.getBoundingBox()) | this.checkWalls(this.neck.getBoundingBox()) | this.checkWalls(this.body.getBoundingBox()); // Purpur + this.knockBack(worldserver2, worldserver2.getEntities((Entity) this, this.wing1.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); + this.knockBack(worldserver2, worldserver2.getEntities((Entity) this, this.wing2.getBoundingBox().inflate(4.0D, 2.0D, 4.0D).move(0.0D, -2.0D, 0.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); + this.hurt(worldserver2, worldserver2.getEntities((Entity) this, this.head.getBoundingBox().inflate(1.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR)); +@@ -374,7 +460,7 @@ public class EnderDragon extends Mob implements Enemy { + if (world3 instanceof ServerLevel) { + ServerLevel worldserver3 = (ServerLevel) world3; + +- this.inWall = this.checkWalls(worldserver3, this.head.getBoundingBox()) | this.checkWalls(worldserver3, this.neck.getBoundingBox()) | this.checkWalls(worldserver3, this.body.getBoundingBox()); ++ this.inWall = !hasRider && this.checkWalls(worldserver3, this.head.getBoundingBox()) | this.checkWalls(worldserver3, this.neck.getBoundingBox()) | this.checkWalls(worldserver3, this.body.getBoundingBox()); // Purpur if (this.dragonFight != null) { this.dragonFight.updateDragon(this); } -@@ -540,7 +626,7 @@ public class EnderDragon extends Mob implements Enemy { - BlockState iblockdata = this.level().getBlockState(blockposition); +@@ -510,7 +596,7 @@ public class EnderDragon extends Mob implements Enemy { + BlockState iblockdata = world.getBlockState(blockposition); if (!iblockdata.isAir() && !iblockdata.is(BlockTags.DRAGON_TRANSPARENT)) { -- if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !iblockdata.is(BlockTags.DRAGON_IMMUNE)) { -+ if ((this.level().purpurConfig.enderDragonBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && !iblockdata.is(BlockTags.DRAGON_IMMUNE)) { // Purpur +- if (world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !iblockdata.is(BlockTags.DRAGON_IMMUNE)) { ++ if ((world.purpurConfig.enderDragonBypassMobGriefing ^ world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && !iblockdata.is(BlockTags.DRAGON_IMMUNE)) { // Purpur // CraftBukkit start - Add blocks to list rather than destroying them - // flag1 = this.level().removeBlock(blockposition, false) || flag1; + // flag1 = worldserver.removeBlock(blockposition, false) || flag1; flag1 = true; -@@ -682,7 +768,7 @@ public class EnderDragon extends Mob implements Enemy { - boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); +@@ -651,7 +737,7 @@ public class EnderDragon extends Mob implements Enemy { + boolean flag = worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); short short0 = 500; - if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) { @@ -7849,7 +7772,7 @@ index 5868d2e9e05a698c77117cf87c79b636b50fe289..573ec75b5fed1c3d30aa9dc64cf3a8a7 short0 = 12000; } -@@ -1118,6 +1204,7 @@ public class EnderDragon extends Mob implements Enemy { +@@ -1069,6 +1155,7 @@ public class EnderDragon extends Mob implements Enemy { @Override protected boolean canRide(Entity entity) { @@ -7857,7 +7780,7 @@ index 5868d2e9e05a698c77117cf87c79b636b50fe289..573ec75b5fed1c3d30aa9dc64cf3a8a7 return false; } -@@ -1144,6 +1231,6 @@ public class EnderDragon extends Mob implements Enemy { +@@ -1095,6 +1182,6 @@ public class EnderDragon extends Mob implements Enemy { @Override protected float sanitizeScale(float scale) { @@ -7866,10 +7789,10 @@ index 5868d2e9e05a698c77117cf87c79b636b50fe289..573ec75b5fed1c3d30aa9dc64cf3a8a7 } } diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..a4995d114fd844e0d39726537a2e4076daf43120 100644 +index 244e38db508efa3eebebb6392c4ebb0805367baf..ac8f05e20e810e61e4c77aa7a6e41008779563dc 100644 --- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java -@@ -88,20 +88,60 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -86,20 +86,60 @@ public class WitherBoss extends Monster implements RangedAttackMob { return !entityliving.getType().is(EntityTypeTags.WITHER_FRIENDS) && entityliving.attackable(); }; private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); @@ -7931,7 +7854,7 @@ index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..a4995d114fd844e0d39726537a2e4076 @Override protected PathNavigation createNavigation(Level world) { FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, world); -@@ -112,13 +152,114 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -110,13 +150,114 @@ public class WitherBoss extends Monster implements RangedAttackMob { return navigationflying; } @@ -8046,7 +7969,7 @@ index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..a4995d114fd844e0d39726537a2e4076 this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 0, false, false, WitherBoss.LIVING_ENTITY_SELECTOR)); } -@@ -136,6 +277,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -134,6 +275,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { public void addAdditionalSaveData(CompoundTag nbt) { super.addAdditionalSaveData(nbt); nbt.putInt("Invul", this.getInvulnerableTicks()); @@ -8054,7 +7977,7 @@ index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..a4995d114fd844e0d39726537a2e4076 } @Override -@@ -145,6 +287,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -143,6 +285,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { if (this.hasCustomName()) { this.bossEvent.setName(this.getDisplayName()); } @@ -8062,10 +7985,10 @@ index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..a4995d114fd844e0d39726537a2e4076 } -@@ -263,6 +406,16 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -261,6 +404,15 @@ public class WitherBoss extends Monster implements RangedAttackMob { @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + // Purpur start + if (getRider() != null && this.isControllable()) { + Vec3 mot = getDeltaMovement(); @@ -8075,20 +7998,19 @@ index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..a4995d114fd844e0d39726537a2e4076 + shootCooldown--; + } + // Purpur end -+ int i; if (this.getInvulnerableTicks() > 0) { -@@ -279,7 +432,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -277,7 +429,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { } // CraftBukkit end - if (!this.isSilent()) { + if (!this.isSilent() && level().purpurConfig.witherPlaySpawnSound) { // CraftBukkit start - Use relative location for far away sounds - // this.level().globalLevelEvent(1023, new BlockPosition(this), 0); - int viewDistance = ((ServerLevel) this.level()).getCraftServer().getViewDistance() * 16; -@@ -304,7 +457,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + // worldserver.globalLevelEvent(1023, new BlockPosition(this), 0); + int viewDistance = world.getCraftServer().getViewDistance() * 16; +@@ -302,7 +454,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { this.setInvulnerableTicks(i); if (this.tickCount % 10 == 0) { @@ -8097,16 +8019,16 @@ index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..a4995d114fd844e0d39726537a2e4076 } } else { -@@ -364,7 +517,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -362,7 +514,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { if (this.destroyBlocksTick > 0) { --this.destroyBlocksTick; -- if (this.destroyBlocksTick == 0 && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ if (this.destroyBlocksTick == 0 && (this.level().purpurConfig.witherBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // Purpur +- if (this.destroyBlocksTick == 0 && world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (this.destroyBlocksTick == 0 && (world.purpurConfig.witherBypassMobGriefing ^ world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // Purpur boolean flag = false; j = Mth.floor(this.getBbWidth() / 2.0F + 1.0F); -@@ -391,8 +544,10 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -389,8 +541,10 @@ public class WitherBoss extends Monster implements RangedAttackMob { } } @@ -8119,7 +8041,7 @@ index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..a4995d114fd844e0d39726537a2e4076 } this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); -@@ -580,11 +735,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -579,11 +733,11 @@ public class WitherBoss extends Monster implements RangedAttackMob { } public int getAlternativeTarget(int headIndex) { @@ -8132,8 +8054,8 @@ index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..a4995d114fd844e0d39726537a2e4076 + if (getRider() == null || !this.isControllable()) this.entityData.set(WitherBoss.DATA_TARGETS.get(headIndex), id); // Purpur } - @Override -@@ -594,6 +749,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + public boolean isPowered() { +@@ -592,6 +746,7 @@ public class WitherBoss extends Monster implements RangedAttackMob { @Override protected boolean canRide(Entity entity) { @@ -8142,10 +8064,10 @@ index d3b4d492aee380dc17f4232d90eaae4f07bb9f86..a4995d114fd844e0d39726537a2e4076 } diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index c292f58ba4b29395484dbbf8591e455f449581d8..c0383771b08e1d89dfa4996b979248da1de8aca1 100644 +index 70b8023c3badc745f342d5b0ab54699e3923826a..037586c0fdb42a02660aba89dd741a647c67e52b 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -102,10 +102,12 @@ public class ArmorStand extends LivingEntity { +@@ -114,10 +114,12 @@ public class ArmorStand extends LivingEntity { private boolean noTickPoseDirty = false; private boolean noTickEquipmentDirty = false; // Paper end - Allow ArmorStands not to tick @@ -8158,7 +8080,7 @@ index c292f58ba4b29395484dbbf8591e455f449581d8..c0383771b08e1d89dfa4996b979248da this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY); this.headPose = ArmorStand.DEFAULT_HEAD_POSE; -@@ -114,6 +116,7 @@ public class ArmorStand extends LivingEntity { +@@ -126,6 +128,7 @@ public class ArmorStand extends LivingEntity { this.rightArmPose = ArmorStand.DEFAULT_RIGHT_ARM_POSE; this.leftLegPose = ArmorStand.DEFAULT_LEFT_LEG_POSE; this.rightLegPose = ArmorStand.DEFAULT_RIGHT_LEG_POSE; @@ -8166,7 +8088,7 @@ index c292f58ba4b29395484dbbf8591e455f449581d8..c0383771b08e1d89dfa4996b979248da } public ArmorStand(Level world, double x, double y, double z) { -@@ -620,6 +623,7 @@ public class ArmorStand extends LivingEntity { +@@ -618,6 +621,7 @@ public class ArmorStand extends LivingEntity { private org.bukkit.event.entity.EntityDeathEvent brokenByPlayer(ServerLevel world, DamageSource damageSource) { // Paper ItemStack itemstack = new ItemStack(Items.ARMOR_STAND); @@ -8174,7 +8096,7 @@ index c292f58ba4b29395484dbbf8591e455f449581d8..c0383771b08e1d89dfa4996b979248da itemstack.set(DataComponents.CUSTOM_NAME, this.getCustomName()); this.drops.add(new DefaultDrop(itemstack, stack -> Block.popResource(this.level(), this.blockPosition(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior return this.brokenByAnything(world, damageSource); // Paper -@@ -683,6 +687,7 @@ public class ArmorStand extends LivingEntity { +@@ -681,6 +685,7 @@ public class ArmorStand extends LivingEntity { @Override public void tick() { @@ -8182,7 +8104,7 @@ index c292f58ba4b29395484dbbf8591e455f449581d8..c0383771b08e1d89dfa4996b979248da // Paper start - Allow ArmorStands not to tick if (!this.canTick) { if (this.noTickPoseDirty) { -@@ -1015,4 +1020,18 @@ public class ArmorStand extends LivingEntity { +@@ -1013,4 +1018,18 @@ public class ArmorStand extends LivingEntity { } } // Paper end @@ -8202,45 +8124,45 @@ index c292f58ba4b29395484dbbf8591e455f449581d8..c0383771b08e1d89dfa4996b979248da + // Purpur end } diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java -index 5b7245cd99593ee90e17c97e0104f3aba9ae05ea..cf78531b193ba56991ccb0c4f62844208e4a5706 100644 +index bbdaaa1cc0b4aed28bc39385508d221055b99d4d..bd5e034ce58ebe53d2121209d76ae60134ce72fe 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java -@@ -227,7 +227,13 @@ public class ItemFrame extends HangingEntity { +@@ -240,7 +240,13 @@ public class ItemFrame extends HangingEntity { } - if (alwaysDrop) { -- this.spawnAtLocation(this.getFrameItemStack()); + if (dropSelf) { +- this.spawnAtLocation(world, this.getFrameItemStack()); + // Purpur start + final ItemStack itemFrame = this.getFrameItemStack(); + if (!this.level().purpurConfig.persistentDroppableEntityDisplayNames) { + itemFrame.set(DataComponents.CUSTOM_NAME, null); + } -+ this.spawnAtLocation(itemFrame); ++ this.spawnAtLocation(world, itemFrame); + // Purpur end } if (!itemstack.isEmpty()) { diff --git a/src/main/java/net/minecraft/world/entity/decoration/Painting.java b/src/main/java/net/minecraft/world/entity/decoration/Painting.java -index e86fdf5d6853b7bddfe19d6e5d41d3dec0c25f23..f45567aa7695da68f92809a6c208eb515c2f838a 100644 +index fd0e78a2318e3950d011c17358245e107b38154a..0fcab828e81176323cbdf16c0ec714d9a2846ae5 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/Painting.java +++ b/src/main/java/net/minecraft/world/entity/decoration/Painting.java -@@ -178,7 +178,13 @@ public class Painting extends HangingEntity implements VariantHolder type, Level world) { super(type, world); -@@ -397,7 +403,16 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -410,7 +416,16 @@ public class ItemEntity extends Entity implements TraceableEntity { @Override - public boolean hurt(DamageSource source, float amount) { -- if (this.isInvulnerableTo(source)) { + public final boolean hurtServer(ServerLevel world, DamageSource source, float amount) { +- if (this.isInvulnerableToBase(source)) { + // Purpur start + if ( + (immuneToCactus && source.is(net.minecraft.world.damagesource.DamageTypes.CACTUS)) || -+ (immuneToFire && (source.is(DamageTypeTags.IS_FIRE) || source.is(net.minecraft.world.damagesource.DamageTypes.ON_FIRE) || source.is(net.minecraft.world.damagesource.DamageTypes.IN_FIRE))) || ++ (immuneToFire && (source.is(net.minecraft.tags.DamageTypeTags.IS_FIRE) || source.is(net.minecraft.world.damagesource.DamageTypes.ON_FIRE) || source.is(net.minecraft.world.damagesource.DamageTypes.IN_FIRE))) || + (immuneToLightning && source.is(net.minecraft.world.damagesource.DamageTypes.LIGHTNING_BOLT)) || -+ (immuneToExplosion && source.is(DamageTypeTags.IS_EXPLOSION)) ++ (immuneToExplosion && source.is(net.minecraft.tags.DamageTypeTags.IS_EXPLOSION)) + ) { + return false; -+ } else if (this.isInvulnerableTo(source)) { ++ } else if (this.isInvulnerableToBase(source)) { + // Purpur end return false; - } else if (!this.getItem().isEmpty() && this.getItem().is(Items.NETHER_STAR) && source.is(DamageTypeTags.IS_EXPLOSION)) { + } else if (!world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && source.getEntity() instanceof Mob) { return false; -@@ -605,6 +620,12 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -621,6 +636,12 @@ public class ItemEntity extends Entity implements TraceableEntity { public void setItem(ItemStack stack) { this.getEntityData().set(ItemEntity.DATA_ITEM, stack); this.despawnRate = this.level().paperConfig().entities.spawning.altItemDespawnRate.enabled ? this.level().paperConfig().entities.spawning.altItemDespawnRate.items.getOrDefault(stack.getItem(), this.level().spigotConfig.itemDespawnRate) : this.level().spigotConfig.itemDespawnRate; // Paper - Alternative item-despawn-rate @@ -8288,32 +8210,34 @@ index 111ab64e0d928ea990175ae18a97492b98948f89..3e89e3f5760690f30221b64e40e69bcc @Override diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -index 42bd2d9a1528b6210e4dfb56233062fd97c9743b..2a4425d04917b32c7ae5af3e7422c0bafc2aa1c2 100644 +index de87483600e55d88176fe25db621bbd3e464729f..287ba483614e79e78022e703ef891f59f41ac455 100644 --- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -@@ -230,4 +230,29 @@ public class PrimedTnt extends Entity implements TraceableEntity { +@@ -249,4 +249,31 @@ public class PrimedTnt extends Entity implements TraceableEntity { return !level().paperConfig().fixes.preventTntFromMovingInWater && super.isPushedByFluid(); } // Paper end - Option to prevent TNT from moving in water + // Purpur start - Shears can defuse TNT + @Override + public net.minecraft.world.InteractionResult interact(net.minecraft.world.entity.player.Player player, net.minecraft.world.InteractionHand hand) { -+ if (!level().isClientSide && level().purpurConfig.shearsCanDefuseTnt) { ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel serverWorld && level().purpurConfig.shearsCanDefuseTnt) { + final net.minecraft.world.item.ItemStack inHand = player.getItemInHand(hand); + + if (!inHand.is(net.minecraft.world.item.Items.SHEARS) || !player.getBukkitEntity().hasPermission("purpur.tnt.defuse") || -+ level().random.nextFloat() > level().purpurConfig.shearsCanDefuseTntChance) return net.minecraft.world.InteractionResult.PASS; ++ serverWorld.random.nextFloat() > serverWorld.purpurConfig.shearsCanDefuseTntChance) return net.minecraft.world.InteractionResult.PASS; + -+ net.minecraft.world.entity.item.ItemEntity tntItem = new net.minecraft.world.entity.item.ItemEntity(level(), getX(), getY(), getZ(), ++ net.minecraft.world.entity.item.ItemEntity tntItem = new net.minecraft.world.entity.item.ItemEntity(serverWorld, getX(), getY(), getZ(), + new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.TNT)); + tntItem.setPickUpDelay(10); + + inHand.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand)); -+ level().addFreshEntity(tntItem, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CUSTOM); ++ serverWorld.addFreshEntity(tntItem, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CUSTOM); + + this.playSound(net.minecraft.sounds.SoundEvents.SHEEP_SHEAR); + -+ this.kill(); ++ this.kill(serverWorld); + return net.minecraft.world.InteractionResult.SUCCESS; + } + @@ -8322,10 +8246,10 @@ index 42bd2d9a1528b6210e4dfb56233062fd97c9743b..2a4425d04917b32c7ae5af3e7422c0ba + // Purpur end - Shears can defuse TNT } diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -index 3b5cf6ffb74d11bea5eb21bd66d679734ff5000c..f9532a45419699585d1f20d27d5857a3e953ec55 100644 +index 32670a3cb4b54b66d655197e3fde834d2b2b6d34..39d02cf0e31832e30c4f034b0b5385e3e0057e60 100644 --- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -@@ -66,16 +66,19 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo +@@ -68,16 +68,19 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo protected AbstractSkeleton(EntityType type, Level world) { super(type, world); this.reassessWeaponGoal(); @@ -8345,7 +8269,7 @@ index 3b5cf6ffb74d11bea5eb21bd66d679734ff5000c..f9532a45419699585d1f20d27d5857a3 this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); -@@ -94,37 +97,14 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo +@@ -96,37 +99,14 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo abstract SoundEvent getStepSound(); // Paper start - shouldBurnInDay API @@ -8385,7 +8309,7 @@ index 3b5cf6ffb74d11bea5eb21bd66d679734ff5000c..f9532a45419699585d1f20d27d5857a3 super.aiStep(); } -@@ -156,11 +136,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo +@@ -158,11 +138,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo this.reassessWeaponGoal(); this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper - Add world settings for mobs picking up loot if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { @@ -8398,16 +8322,16 @@ index 3b5cf6ffb74d11bea5eb21bd66d679734ff5000c..f9532a45419699585d1f20d27d5857a3 this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(randomsource.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; } -@@ -209,7 +185,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo - double d2 = target.getZ() - this.getZ(); - double d3 = Math.sqrt(d0 * d0 + d2 * d2); +@@ -221,7 +197,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + } -- entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); -+ entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, this.level().purpurConfig.skeletonBowAccuracyMap.getOrDefault(this.level().getDifficulty().getId(), (float) (14 - this.level().getDifficulty().getId() * 4))); // Purpur - // CraftBukkit start - org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getPickupItem(), entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper - if (event.isCancelled()) { -@@ -239,7 +215,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + if (event.getProjectile() == entityarrow.getBukkitEntity()) { +- Projectile.spawnProjectileUsingShoot(entityarrow, worldserver, itemstack1, d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - worldserver.getDifficulty().getId() * 4)); ++ Projectile.spawnProjectileUsingShoot(entityarrow, worldserver, itemstack1, d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, this.level().purpurConfig.skeletonBowAccuracyMap.getOrDefault(this.level().getDifficulty().getId(), (float) (14 - this.level().getDifficulty().getId() * 4))); // Purpur + } + // CraftBukkit end + } +@@ -243,7 +219,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo super.readAdditionalSaveData(nbt); this.reassessWeaponGoal(); // Paper start - shouldBurnInDay API @@ -8416,7 +8340,7 @@ index 3b5cf6ffb74d11bea5eb21bd66d679734ff5000c..f9532a45419699585d1f20d27d5857a3 this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay"); } // Paper end - shouldBurnInDay API -@@ -249,7 +225,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo +@@ -253,7 +229,7 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo @Override public void addAdditionalSaveData(CompoundTag nbt) { super.addAdditionalSaveData(nbt); @@ -8426,10 +8350,10 @@ index 3b5cf6ffb74d11bea5eb21bd66d679734ff5000c..f9532a45419699585d1f20d27d5857a3 // Paper end - shouldBurnInDay API diff --git a/src/main/java/net/minecraft/world/entity/monster/Blaze.java b/src/main/java/net/minecraft/world/entity/monster/Blaze.java -index 61004bb35b0edcc4578b8a9c1b280096466ba279..6c68c1df84e006f9992435f4c8e328c17e88c51c 100644 +index e33fa82ca1332b95bb067fd621212d3026eee1b7..07db4557ab0d7a4a0f5432257bd18195d2de7255 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Blaze.java +++ b/src/main/java/net/minecraft/world/entity/monster/Blaze.java -@@ -32,26 +32,74 @@ public class Blaze extends Monster { +@@ -33,26 +33,74 @@ public class Blaze extends Monster { public Blaze(EntityType type, Level world) { super(type, world); @@ -8506,7 +8430,7 @@ index 61004bb35b0edcc4578b8a9c1b280096466ba279..6c68c1df84e006f9992435f4c8e328c1 } @Override -@@ -111,11 +159,18 @@ public class Blaze extends Monster { +@@ -112,11 +160,18 @@ public class Blaze extends Monster { @Override public boolean isSensitiveToWater() { @@ -8515,7 +8439,7 @@ index 61004bb35b0edcc4578b8a9c1b280096466ba279..6c68c1df84e006f9992435f4c8e328c1 } @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + // Purpur start + if (getRider() != null && this.isControllable()) { + Vec3 mot = getDeltaMovement(); @@ -8527,10 +8451,10 @@ index 61004bb35b0edcc4578b8a9c1b280096466ba279..6c68c1df84e006f9992435f4c8e328c1 if (this.nextHeightOffsetChangeTick <= 0) { this.nextHeightOffsetChangeTick = 100; diff --git a/src/main/java/net/minecraft/world/entity/monster/Bogged.java b/src/main/java/net/minecraft/world/entity/monster/Bogged.java -index 9d50b9ac8084f3db1844cc7ad1ce9153614ff9d9..f3aae2c50d05a05ad4aef36d432b87b431ba07e8 100644 +index 975477663b6d76a69c006a89e440e21471b39b89..ca63ab37bc6b5b4cb5abf2848dae476b5d937f2a 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Bogged.java +++ b/src/main/java/net/minecraft/world/entity/monster/Bogged.java -@@ -48,6 +48,29 @@ public class Bogged extends AbstractSkeleton implements Shearable { +@@ -44,6 +44,29 @@ public class Bogged extends AbstractSkeleton implements Shearable { super(type, world); } @@ -8560,75 +8484,11 @@ index 9d50b9ac8084f3db1844cc7ad1ce9153614ff9d9..f3aae2c50d05a05ad4aef36d432b87b4 @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); -@@ -81,7 +104,7 @@ public class Bogged extends AbstractSkeleton implements Shearable { - if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { - // CraftBukkit start - // Paper start - expose drops in event -- java.util.List drops = generateDefaultDrops(); -+ java.util.List drops = generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.LOOTING, itemstack)); // Purpur - final org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); - if (event != null) { - if (event.isCancelled()) { -@@ -148,7 +171,7 @@ public class Bogged extends AbstractSkeleton implements Shearable { - @Override - public void shear(SoundSource shearedSoundCategory) { - // Paper start - shear drop API -- this.shear(shearedSoundCategory, generateDefaultDrops()); -+ this.shear(shearedSoundCategory, generateDefaultDrops(0)); // Purpur - } - - @Override -@@ -161,7 +184,7 @@ public class Bogged extends AbstractSkeleton implements Shearable { - - private void spawnShearedMushrooms() { - // Paper start - shear drops API -- this.spawnDrops(generateDefaultDrops()); // Only here for people calling spawnSheardMushrooms. Not used otherwise. -+ this.spawnDrops(generateDefaultDrops(0)); // Only here for people calling spawnSheardMushrooms. Not used otherwise. // Purpur - } - private void spawnDrops(java.util.List drops) { - drops.forEach(stack -> { -@@ -170,14 +193,22 @@ public class Bogged extends AbstractSkeleton implements Shearable { - this.forceDrops = false; - }); - } -- private void generateShearedMushrooms(java.util.function.Consumer stackConsumer) { -+ private void generateShearedMushrooms(java.util.function.Consumer stackConsumer, int looting) { // Purpur - // Paper end - shear drops API - Level world = this.level(); - - if (world instanceof ServerLevel worldserver) { - LootTable loottable = worldserver.getServer().reloadableRegistries().getLootTable(BuiltInLootTables.BOGGED_SHEAR); - LootParams lootparams = (new LootParams.Builder(worldserver)).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.THIS_ENTITY, this).create(LootContextParamSets.SHEARING); -- ObjectListIterator objectlistiterator = loottable.getRandomItems(lootparams).iterator(); -+ // Purpur start -+ it.unimi.dsi.fastutil.objects.ObjectArrayList randomItemsList = loottable.getRandomItems(lootparams); -+ if (org.purpurmc.purpur.PurpurConfig.allowShearsLooting && looting > 0) { -+ for (int i = 0; i < looting; i++) { -+ randomItemsList.addAll(loottable.getRandomItems(lootparams)); -+ } -+ } -+ ObjectListIterator objectlistiterator = randomItemsList.iterator(); -+ // Purpur end - - while (objectlistiterator.hasNext()) { - ItemStack itemstack = (ItemStack) objectlistiterator.next(); -@@ -190,9 +221,9 @@ public class Bogged extends AbstractSkeleton implements Shearable { - - // Paper start - shear drops API - @Override -- public java.util.List generateDefaultDrops() { -+ public java.util.List generateDefaultDrops(int looting) { // Purpur - final java.util.List drops = new java.util.ArrayList<>(); -- this.generateShearedMushrooms(drops::add); -+ this.generateShearedMushrooms(drops::add, looting); // Purpur - return drops; - } - // Paper end - shear drops API diff --git a/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java b/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java -index 87e4b300ac248f6c13d9b4a8f24fd78b24b565b4..98b255cfe2fd04c93398ad4120db9b2fddcbe3e8 100644 +index 4e621a7f36b3d718695434a2a4e3060283667bb2..9a274b83a3a7726cac421856dbc7be01de45d29b 100644 --- a/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java +++ b/src/main/java/net/minecraft/world/entity/monster/CaveSpider.java -@@ -26,6 +26,39 @@ public class CaveSpider extends Spider { +@@ -27,6 +27,39 @@ public class CaveSpider extends Spider { return Spider.createAttributes().add(Attributes.MAX_HEALTH, 12.0D); } @@ -8666,13 +8526,13 @@ index 87e4b300ac248f6c13d9b4a8f24fd78b24b565b4..98b255cfe2fd04c93398ad4120db9b2f + } + @Override - public boolean doHurtTarget(Entity target) { - if (super.doHurtTarget(target)) { + public boolean doHurtTarget(ServerLevel world, Entity target) { + if (super.doHurtTarget(world, target)) { diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a77c23aac 100644 +index 1906dfc22af208d6e801ad4a8f2f9e9702432691..38cbe2fce9c36195aa9bea2af26d14364b216825 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java +++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -@@ -61,21 +61,99 @@ public class Creeper extends Monster implements PowerableMob { +@@ -60,21 +60,99 @@ public class Creeper extends Monster { public int explosionRadius = 3; private int droppedSkulls; public Entity entityIgniter; // CraftBukkit @@ -8704,7 +8564,7 @@ index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a + } + + @Override -+ protected void customServerAiStep() { ++ protected void customServerAiStep(ServerLevel world) { + if (powerToggleDelay > 0) { + powerToggleDelay--; + } @@ -8719,7 +8579,7 @@ index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a + } + prevSpacebarCharge = spacebarCharge; + } -+ super.customServerAiStep(); ++ super.customServerAiStep(world); + } + + @Override @@ -8772,7 +8632,7 @@ index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true)); this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); } -@@ -175,6 +253,40 @@ public class Creeper extends Monster implements PowerableMob { +@@ -174,6 +252,40 @@ public class Creeper extends Monster { } } @@ -8782,7 +8642,7 @@ index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a + this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.creeperScale); + } + -+ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, @Nullable net.minecraft.world.entity.SpawnGroupData entityData) { ++ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.EntitySpawnReason spawnReason, @Nullable net.minecraft.world.entity.SpawnGroupData entityData) { + double chance = world.getLevel().purpurConfig.creeperChargedChance; + if (chance > 0D && random.nextDouble() <= chance) { + setPowered(true); @@ -8813,15 +8673,15 @@ index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a @Override protected SoundEvent getHurtSound(DamageSource source) { return SoundEvents.CREEPER_HURT; -@@ -263,15 +375,18 @@ public class Creeper extends Monster implements PowerableMob { - } +@@ -262,16 +374,18 @@ public class Creeper extends Monster { public void explodeCreeper() { + Level world = this.level(); + this.exploding = true; // Purpur - Config to make Creepers explode on death -+ - if (!this.level().isClientSide) { + + if (world instanceof ServerLevel worldserver) { float f = this.isPowered() ? 2.0F : 1.0F; -+ float multiplier = this.level().purpurConfig.creeperHealthRadius ? this.getHealth() / this.getMaxHealth() : 1; // Purpur ++ float multiplier = worldserver.purpurConfig.creeperHealthRadius ? this.getHealth() / this.getMaxHealth() : 1; // Purpur // CraftBukkit start - ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * f, false); @@ -8829,12 +8689,12 @@ index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a if (!event.isCancelled()) { // CraftBukkit end this.dead = true; -- this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this) -+ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), this.level().getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING) && level().purpurConfig.creeperAllowGriefing ? Level.ExplosionInteraction.MOB : Level.ExplosionInteraction.NONE); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this) // Purpur +- worldserver.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this) ++ worldserver.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), worldserver.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING) && level().purpurConfig.creeperAllowGriefing ? Level.ExplosionInteraction.MOB : Level.ExplosionInteraction.NONE); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this) // Purpur this.spawnLingeringCloud(); - this.triggerOnDeathMobEffects(Entity.RemovalReason.KILLED); + this.triggerOnDeathMobEffects(worldserver, Entity.RemovalReason.KILLED); this.discard(EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause -@@ -283,6 +398,7 @@ public class Creeper extends Monster implements PowerableMob { +@@ -283,6 +397,7 @@ public class Creeper extends Monster { // CraftBukkit end } @@ -8842,7 +8702,7 @@ index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a } private void spawnLingeringCloud() { -@@ -324,6 +440,7 @@ public class Creeper extends Monster implements PowerableMob { +@@ -324,6 +439,7 @@ public class Creeper extends Monster { com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); if (event.callEvent()) { this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited()); @@ -8851,11 +8711,11 @@ index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a } // Paper end - CreeperIgniteEvent diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -index cff1b5e0e3fd32d82157d5f13d83d4abdfad7378..94de51bf9acb32421838ffe54602310f0263b3c4 100644 +index 2e73917ce9270de7483bb1d4e9bf312a31ec9b1e..949207eda199c874f2f14074b5a4fff5462b86b9 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java +++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -@@ -71,6 +71,59 @@ public class Drowned extends Zombie implements RangedAttackMob { - return Zombie.createAttributes().add(Attributes.STEP_HEIGHT, 1.0D); +@@ -72,6 +72,59 @@ public class Drowned extends Zombie implements RangedAttackMob { + return Zombie.createAttributes().add(Attributes.STEP_HEIGHT, 1.0); } + // Purpur start @@ -8913,16 +8773,16 @@ index cff1b5e0e3fd32d82157d5f13d83d4abdfad7378..94de51bf9acb32421838ffe54602310f + @Override protected void addBehaviourGoals() { - this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0D)); -@@ -78,10 +131,23 @@ public class Drowned extends Zombie implements RangedAttackMob { - this.goalSelector.addGoal(2, new Drowned.DrownedAttackGoal(this, 1.0D, false)); - this.goalSelector.addGoal(5, new Drowned.DrownedGoToBeachGoal(this, 1.0D)); - this.goalSelector.addGoal(6, new Drowned.DrownedSwimUpGoal(this, 1.0D, this.level().getSeaLevel())); + this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0)); +@@ -79,10 +132,23 @@ public class Drowned extends Zombie implements RangedAttackMob { + this.goalSelector.addGoal(2, new Drowned.DrownedAttackGoal(this, 1.0, false)); + this.goalSelector.addGoal(5, new Drowned.DrownedGoToBeachGoal(this, 1.0)); + this.goalSelector.addGoal(6, new Drowned.DrownedSwimUpGoal(this, 1.0, this.level().getSeaLevel())); + if (level().purpurConfig.drownedBreakDoors) this.goalSelector.addGoal(6, new net.minecraft.world.entity.ai.goal.MoveThroughVillageGoal(this, 1.0D, true, 4, this::canBreakDoors)); - this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D)); - this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Drowned.class})).setAlertOthers(ZombifiedPiglin.class)); - this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget)); -- if (this.level().spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper - Check drowned for villager aggression config + this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0)); + this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Drowned.class).setAlertOthers(ZombifiedPiglin.class)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (target, world) -> this.okTarget(target))); +- if (this.level().spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper - Check drowned for villager aggression config + // Purpur start + if (this.level().spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false) { // Paper - Check drowned for villager aggression config + @Override @@ -8939,54 +8799,44 @@ index cff1b5e0e3fd32d82157d5f13d83d4abdfad7378..94de51bf9acb32421838ffe54602310f this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Axolotl.class, true, false)); this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); -@@ -115,7 +181,7 @@ public class Drowned extends Zombie implements RangedAttackMob { - - @Override - public boolean supportsBreakDoorGoal() { -- return false; -+ return level().purpurConfig.drownedBreakDoors ? true : false; - } - - @Override -@@ -262,8 +328,7 @@ public class Drowned extends Zombie implements RangedAttackMob { - this.searchingForLand = targetingUnderwater; +@@ -396,7 +462,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + } } -- private static class DrownedMoveControl extends MoveControl { -- -+ private static class DrownedMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur +- static class DrownedMoveControl extends MoveControl { ++ static class DrownedMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur private final Drowned drowned; public DrownedMoveControl(Drowned drowned) { -@@ -272,7 +337,7 @@ public class Drowned extends Zombie implements RangedAttackMob { +@@ -405,7 +471,7 @@ public class Drowned extends Zombie implements RangedAttackMob { } @Override - public void tick() { + public void vanillaTick() { // Purpur - LivingEntity entityliving = this.drowned.getTarget(); - + LivingEntity livingEntity = this.drowned.getTarget(); if (this.drowned.wantsToSwim() && this.drowned.isInWater()) { -@@ -295,7 +360,7 @@ public class Drowned extends Zombie implements RangedAttackMob { - - this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), f, 90.0F)); + if (livingEntity != null && livingEntity.getY() > this.drowned.getY() || this.drowned.searchingForLand) { +@@ -425,7 +491,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + float h = (float)(Mth.atan2(f, d) * 180.0F / (float)Math.PI) - 90.0F; + this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), h, 90.0F)); this.drowned.yBodyRot = this.drowned.getYRot(); -- float f1 = (float) (this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); -+ float f1 = (float) (this.getSpeedModifier() * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur - float f2 = Mth.lerp(0.125F, this.drowned.getSpeed(), f1); - - this.drowned.setSpeed(f2); -@@ -305,7 +370,7 @@ public class Drowned extends Zombie implements RangedAttackMob { - this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, -0.008D, 0.0D)); +- float i = (float)(this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float i = (float)(this.getSpeedModifier() * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur + float j = Mth.lerp(0.125F, this.drowned.getSpeed(), i); + this.drowned.setSpeed(j); + this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add((double)j * d * 0.005, (double)j * e * 0.1, (double)j * f * 0.005)); +@@ -434,7 +500,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0, -0.008, 0.0)); } - super.tick(); + super.vanillaTick(); // Purpur } - } + } diff --git a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java -index fd995b1f29c47884e9db2cb92f1dd615d62ae032..9c9c8b83b3f793045b487891512e4de3430ef5a3 100644 +index 378694a38115c012978e1fea59d049d1ebd04110..a000304e3ac4c34b020f7457aa2589c87f140d8c 100644 --- a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +++ b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java @@ -33,6 +33,34 @@ public class ElderGuardian extends Guardian { @@ -9025,7 +8875,7 @@ index fd995b1f29c47884e9db2cb92f1dd615d62ae032..9c9c8b83b3f793045b487891512e4de3 return Guardian.createAttributes().add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 8.0D).add(Attributes.MAX_HEALTH, 80.0D); } diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index 7b05ef99702af0e8a7d2a652984c4f8c15eefed8..144b7f4133091285e7b044daf64aaf634595fbed 100644 +index 35ffcd82df6af65a9c1b9a1a6acdd8b7567b8645..ebc2a461a9b41a28388362c777f53a0ee7f839f3 100644 --- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java @@ -92,12 +92,41 @@ public class EnderMan extends Monster implements NeutralMob { @@ -9079,20 +8929,20 @@ index 7b05ef99702af0e8a7d2a652984c4f8c15eefed8..144b7f4133091285e7b044daf64aaf63 this.targetSelector.addGoal(1, new EnderMan.EndermanLookForPlayerGoal(this, this::isAngryAt)); this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); - this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Endermite.class, true, false)); -+ this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Endermite.class, 10, true, false, (entityliving) -> entityliving.level().purpurConfig.endermanAggroEndermites && entityliving instanceof Endermite endermite && (!entityliving.level().purpurConfig.endermanAggroEndermitesOnlyIfPlayerSpawned || endermite.isPlayerSpawned()))); // Purpur ++ this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Endermite.class, 10, true, false, (entityliving, ignored) -> entityliving.level().purpurConfig.endermanAggroEndermites && entityliving instanceof Endermite endermite && (!entityliving.level().purpurConfig.endermanAggroEndermitesOnlyIfPlayerSpawned || endermite.isPlayerSpawned()))); // Purpur this.targetSelector.addGoal(4, new ResetUniversalAngerTargetGoal<>(this, false)); } -@@ -244,7 +274,7 @@ public class EnderMan extends Monster implements NeutralMob { - // Paper end - EndermanAttackPlayerEvent - ItemStack itemstack = (ItemStack) player.getInventory().armor.get(3); +@@ -235,7 +265,7 @@ public class EnderMan extends Monster implements NeutralMob { -- if (itemstack.is(Blocks.CARVED_PUMPKIN.asItem())) { -+ if (this.level().purpurConfig.endermanDisableStareAggro || itemstack.is(Blocks.CARVED_PUMPKIN.asItem()) || (this.level().purpurConfig.endermanIgnorePlayerDragonHead && itemstack.is(net.minecraft.world.item.Items.DRAGON_HEAD))) { // Purpur - return false; - } else { - Vec3 vec3d = player.getViewVector(1.0F).normalize(); -@@ -276,12 +306,12 @@ public class EnderMan extends Monster implements NeutralMob { + boolean isBeingStaredBy(Player player) { + // Paper start - EndermanAttackPlayerEvent +- boolean shouldAttack = isBeingStaredBy0(player); ++ boolean shouldAttack = !this.level().purpurConfig.endermanDisableStareAggro && isBeingStaredBy0(player); // Purpur + com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity()); + event.setCancelled(!shouldAttack); + return event.callEvent(); +@@ -263,12 +293,12 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean isSensitiveToWater() { @@ -9101,30 +8951,30 @@ index 7b05ef99702af0e8a7d2a652984c4f8c15eefed8..144b7f4133091285e7b044daf64aaf63 } @Override - protected void customServerAiStep() { -- if (this.level().isDay() && this.tickCount >= this.targetChangeTime + 600) { -+ if ((getRider() == null || !this.isControllable()) && this.level().isDay() && this.tickCount >= this.targetChangeTime + 600) { // Purpur - no random teleporting + protected void customServerAiStep(ServerLevel world) { +- if (world.isDay() && this.tickCount >= this.targetChangeTime + 600) { ++ if ((getRider() == null || !this.isControllable()) && world.isDay() && this.tickCount >= this.targetChangeTime + 600) { // Purpur - no random teleporting float f = this.getLightLevelDependentMagicValue(); - if (f > 0.5F && this.level().canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - EndermanEscapeEvent -@@ -402,6 +432,8 @@ public class EnderMan extends Monster implements NeutralMob { - public boolean hurt(DamageSource source, float amount) { - if (this.isInvulnerableTo(source)) { + if (f > 0.5F && world.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - EndermanEscapeEvent +@@ -390,6 +420,8 @@ public class EnderMan extends Monster implements NeutralMob { + public boolean hurtServer(ServerLevel world, DamageSource source, float amount) { + if (this.isInvulnerableTo(world, source)) { return false; -+ } else if (getRider() != null && this.isControllable()) { return super.hurt(source, amount); // Purpur - no teleporting on damage ++ } else if (getRider() != null && this.isControllable()) { return super.hurtServer(world, source, amount); // Purpur - no teleporting on damage + } else if (org.purpurmc.purpur.PurpurConfig.endermanShortHeight && source.is(net.minecraft.world.damagesource.DamageTypes.IN_WALL)) { return false; // Purpur - no suffocation damage if short height } else { boolean flag = source.getDirectEntity() instanceof ThrownPotion; boolean flag1; -@@ -416,6 +448,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -404,6 +436,7 @@ public class EnderMan extends Monster implements NeutralMob { } else { - flag1 = flag && this.hurtWithCleanWater(source, (ThrownPotion) source.getDirectEntity(), amount); + flag1 = flag && this.hurtWithCleanWater(world, source, (ThrownPotion) source.getDirectEntity(), amount); -+ if (!flag1 && this.level().purpurConfig.endermanIgnoreProjectiles) return super.hurt(source, amount); // Purpur ++ if (!flag1 && world.purpurConfig.endermanIgnoreProjectiles) return super.hurtServer(world, source, amount); // Purpur if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - EndermanEscapeEvent for (int i = 0; i < 64; ++i) { if (this.teleport()) { -@@ -460,7 +493,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -448,7 +481,7 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean requiresCustomPersistence() { @@ -9133,17 +8983,17 @@ index 7b05ef99702af0e8a7d2a652984c4f8c15eefed8..144b7f4133091285e7b044daf64aaf63 } private static class EndermanFreezeWhenLookedAt extends Goal { -@@ -507,7 +540,16 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -495,7 +528,16 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean canUse() { -- return this.enderman.getCarriedBlock() == null ? false : (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0); +- return this.enderman.getCarriedBlock() == null ? false : (!getServerLevel((Entity) this.enderman).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0); + if (!enderman.level().purpurConfig.endermanAllowGriefing) return false; // Purpur + // Purpur start + if (this.enderman.getCarriedBlock() == null) { + return false; + } -+ if (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !this.enderman.level().purpurConfig.endermanBypassMobGriefing) { ++ if (!getServerLevel((Entity) this.enderman).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) == !this.enderman.level().purpurConfig.endermanBypassMobGriefing) { + return false; + } + return this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0; @@ -9151,17 +9001,17 @@ index 7b05ef99702af0e8a7d2a652984c4f8c15eefed8..144b7f4133091285e7b044daf64aaf63 } @Override -@@ -552,7 +594,16 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -540,7 +582,16 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean canUse() { -- return this.enderman.getCarriedBlock() != null ? false : (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0); +- return this.enderman.getCarriedBlock() != null ? false : (!getServerLevel((Entity) this.enderman).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0); + if (!enderman.level().purpurConfig.endermanAllowGriefing) return false; // Purpur + // Purpur start + if (this.enderman.getCarriedBlock() != null) { + return false; + } -+ if (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !this.enderman.level().purpurConfig.endermanBypassMobGriefing) { ++ if (!getServerLevel((Entity) this.enderman).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) == !this.enderman.level().purpurConfig.endermanBypassMobGriefing) { + return false; + } + return this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0; @@ -9170,7 +9020,7 @@ index 7b05ef99702af0e8a7d2a652984c4f8c15eefed8..144b7f4133091285e7b044daf64aaf63 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Endermite.java b/src/main/java/net/minecraft/world/entity/monster/Endermite.java -index 9c78905762d9a484878fa9cf03a2ca3850e7e613..f5b4623e3f4862cb6bf1ce7f345378c4c32f02cd 100644 +index 534e98dd7291e09dee1d0f77cbf221b15708590f..f8373fc9839fccb31e3dd090de70e2cd7c9e6cfc 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Endermite.java +++ b/src/main/java/net/minecraft/world/entity/monster/Endermite.java @@ -32,20 +32,64 @@ public class Endermite extends Monster { @@ -9254,10 +9104,10 @@ index 9c78905762d9a484878fa9cf03a2ca3850e7e613..f5b4623e3f4862cb6bf1ce7f345378c4 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Evoker.java b/src/main/java/net/minecraft/world/entity/monster/Evoker.java -index 627cf7ba8f512285228121e46208fff51f22b563..2c14df92b7b725584887d3f41c35659b2805a9ef 100644 +index 6592baa53ecb4e364d1c1b6f64178fc86c59a982..e231bb33b7e6a00d7c1a6c3540b4b48cfd4c15e3 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Evoker.java +++ b/src/main/java/net/minecraft/world/entity/monster/Evoker.java -@@ -52,10 +52,44 @@ public class Evoker extends SpellcasterIllager { +@@ -53,10 +53,44 @@ public class Evoker extends SpellcasterIllager { this.xpReward = 10; } @@ -9301,8 +9151,8 @@ index 627cf7ba8f512285228121e46208fff51f22b563..2c14df92b7b725584887d3f41c35659b + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur this.goalSelector.addGoal(1, new Evoker.EvokerCastingSpellGoal()); this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 0.6D, 1.0D)); - this.goalSelector.addGoal(4, new Evoker.EvokerSummonSpellGoal()); -@@ -64,6 +98,7 @@ public class Evoker extends SpellcasterIllager { + this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Creaking.class, 8.0F, 1.0D, 1.2D)); +@@ -66,6 +100,7 @@ public class Evoker extends SpellcasterIllager { this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); @@ -9310,20 +9160,20 @@ index 627cf7ba8f512285228121e46208fff51f22b563..2c14df92b7b725584887d3f41c35659b this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); -@@ -340,7 +375,7 @@ public class Evoker extends SpellcasterIllager { - return false; - } else if (Evoker.this.tickCount < this.nextAttackTickCount) { - return false; -- } else if (!Evoker.this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ } else if (!Evoker.this.level().purpurConfig.evokerBypassMobGriefing && !Evoker.this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur - return false; +@@ -342,7 +377,7 @@ public class Evoker extends SpellcasterIllager { } else { - List list = Evoker.this.level().getNearbyEntities(Sheep.class, this.wololoTargeting, Evoker.this, Evoker.this.getBoundingBox().inflate(16.0D, 4.0D, 16.0D)); + ServerLevel worldserver = getServerLevel(Evoker.this.level()); + +- if (!worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (!worldserver.purpurConfig.evokerBypassMobGriefing == !worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur + return false; + } else { + List list = worldserver.getNearbyEntities(Sheep.class, this.wololoTargeting, Evoker.this, Evoker.this.getBoundingBox().inflate(16.0D, 4.0D, 16.0D)); diff --git a/src/main/java/net/minecraft/world/entity/monster/Ghast.java b/src/main/java/net/minecraft/world/entity/monster/Ghast.java -index a836a902bebf318ceabaed4e98fab1141b46a28b..395904d83a72888cdbc018311da6e93c626e8210 100644 +index a8c8c03e972aa6352843cf4c3e4aebfb8f493125..173b10fa553db30c321bfd9eabe13915b63cf920 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Ghast.java +++ b/src/main/java/net/minecraft/world/entity/monster/Ghast.java -@@ -43,11 +43,47 @@ public class Ghast extends FlyingMob implements Enemy { +@@ -44,11 +44,47 @@ public class Ghast extends FlyingMob implements Enemy { this.moveControl = new Ghast.GhastMoveControl(this); } @@ -9368,10 +9218,10 @@ index a836a902bebf318ceabaed4e98fab1141b46a28b..395904d83a72888cdbc018311da6e93c this.goalSelector.addGoal(7, new Ghast.GhastLookGoal(this)); this.goalSelector.addGoal(7, new Ghast.GhastShootFireballGoal(this)); + this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving, worldserver) -> { return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; })); -@@ -95,6 +131,22 @@ public class Ghast extends FlyingMob implements Enemy { +@@ -96,6 +132,22 @@ public class Ghast extends FlyingMob implements Enemy { } } @@ -9394,7 +9244,7 @@ index a836a902bebf318ceabaed4e98fab1141b46a28b..395904d83a72888cdbc018311da6e93c @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); -@@ -102,7 +154,7 @@ public class Ghast extends FlyingMob implements Enemy { +@@ -103,7 +155,7 @@ public class Ghast extends FlyingMob implements Enemy { } public static AttributeSupplier.Builder createAttributes() { @@ -9403,7 +9253,7 @@ index a836a902bebf318ceabaed4e98fab1141b46a28b..395904d83a72888cdbc018311da6e93c } @Override -@@ -154,7 +206,7 @@ public class Ghast extends FlyingMob implements Enemy { +@@ -155,7 +207,7 @@ public class Ghast extends FlyingMob implements Enemy { } @@ -9412,7 +9262,7 @@ index a836a902bebf318ceabaed4e98fab1141b46a28b..395904d83a72888cdbc018311da6e93c private final Ghast ghast; private int floatDuration; -@@ -165,7 +217,7 @@ public class Ghast extends FlyingMob implements Enemy { +@@ -166,7 +218,7 @@ public class Ghast extends FlyingMob implements Enemy { } @Override @@ -9422,7 +9272,7 @@ index a836a902bebf318ceabaed4e98fab1141b46a28b..395904d83a72888cdbc018311da6e93c if (this.floatDuration-- <= 0) { this.floatDuration += this.ghast.getRandom().nextInt(5) + 2; diff --git a/src/main/java/net/minecraft/world/entity/monster/Giant.java b/src/main/java/net/minecraft/world/entity/monster/Giant.java -index 118521ae54254b0a73bb7cba7b2871c9c26f89fc..d2e1510e1bc9bbfa8bf21e1b74dda4bef18c6c50 100644 +index 118521ae54254b0a73bb7cba7b2871c9c26f89fc..859d316825658c11f58dd92912edbee75eaeabb9 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Giant.java +++ b/src/main/java/net/minecraft/world/entity/monster/Giant.java @@ -12,12 +12,95 @@ public class Giant extends Monster { @@ -9491,7 +9341,7 @@ index 118521ae54254b0a73bb7cba7b2871c9c26f89fc..d2e1510e1bc9bbfa8bf21e1b74dda4be } + @Override -+ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.MobSpawnType spawnReason, @javax.annotation.Nullable net.minecraft.world.entity.SpawnGroupData entityData) { ++ public net.minecraft.world.entity.SpawnGroupData finalizeSpawn(net.minecraft.world.level.ServerLevelAccessor world, net.minecraft.world.DifficultyInstance difficulty, net.minecraft.world.entity.EntitySpawnReason spawnReason, @org.jetbrains.annotations.Nullable net.minecraft.world.entity.SpawnGroupData entityData) { + net.minecraft.world.entity.SpawnGroupData groupData = super.finalizeSpawn(world, difficulty, spawnReason, entityData); + if (groupData == null) { + populateDefaultEquipmentSlots(this.random, difficulty); @@ -9523,10 +9373,10 @@ index 118521ae54254b0a73bb7cba7b2871c9c26f89fc..d2e1510e1bc9bbfa8bf21e1b74dda4be } } diff --git a/src/main/java/net/minecraft/world/entity/monster/Guardian.java b/src/main/java/net/minecraft/world/entity/monster/Guardian.java -index 5df07b59ff6e39687e361d89d7764381ca3ce9ca..d4de9b066004ec17696f547d8f4067a1f2c0443a 100644 +index 951f46684623582980901c1ebc1870aa5bcf25a1..da833bf35342f771ecccd5dcac4fe87f72d047b0 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Guardian.java +++ b/src/main/java/net/minecraft/world/entity/monster/Guardian.java -@@ -66,15 +66,52 @@ public class Guardian extends Monster { +@@ -67,15 +67,52 @@ public class Guardian extends Monster { this.xpReward = 10; this.setPathfindingMalus(PathType.WATER, 0.0F); this.moveControl = new Guardian.GuardianMoveControl(this); @@ -9579,7 +9429,7 @@ index 5df07b59ff6e39687e361d89d7764381ca3ce9ca..d4de9b066004ec17696f547d8f4067a1 this.goalSelector.addGoal(4, this.guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field this.goalSelector.addGoal(5, pathfindergoalmovetowardsrestriction); this.goalSelector.addGoal(7, this.randomStrollGoal); -@@ -83,6 +120,7 @@ public class Guardian extends Monster { +@@ -84,6 +121,7 @@ public class Guardian extends Monster { this.goalSelector.addGoal(9, new RandomLookAroundGoal(this)); this.randomStrollGoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); pathfindergoalmovetowardsrestriction.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); @@ -9587,7 +9437,7 @@ index 5df07b59ff6e39687e361d89d7764381ca3ce9ca..d4de9b066004ec17696f547d8f4067a1 this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 10, true, false, new Guardian.GuardianAttackSelector(this))); } -@@ -333,7 +371,7 @@ public class Guardian extends Monster { +@@ -330,7 +368,7 @@ public class Guardian extends Monster { @Override public void travel(Vec3 movementInput) { if (this.isControlledByLocalInstance() && this.isInWater()) { @@ -9596,7 +9446,7 @@ index 5df07b59ff6e39687e361d89d7764381ca3ce9ca..d4de9b066004ec17696f547d8f4067a1 this.move(MoverType.SELF, this.getDeltaMovement()); this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); if (!this.isMoving() && this.getTarget() == null) { -@@ -345,7 +383,7 @@ public class Guardian extends Monster { +@@ -342,7 +380,7 @@ public class Guardian extends Monster { } @@ -9605,7 +9455,7 @@ index 5df07b59ff6e39687e361d89d7764381ca3ce9ca..d4de9b066004ec17696f547d8f4067a1 private final Guardian guardian; -@@ -354,8 +392,17 @@ public class Guardian extends Monster { +@@ -351,8 +389,17 @@ public class Guardian extends Monster { this.guardian = guardian; } @@ -9624,7 +9474,7 @@ index 5df07b59ff6e39687e361d89d7764381ca3ce9ca..d4de9b066004ec17696f547d8f4067a1 if (this.operation == MoveControl.Operation.MOVE_TO && !this.guardian.getNavigation().isDone()) { Vec3 vec3d = new Vec3(this.wantedX - this.guardian.getX(), this.wantedY - this.guardian.getY(), this.wantedZ - this.guardian.getZ()); double d0 = vec3d.length(); -@@ -366,7 +413,7 @@ public class Guardian extends Monster { +@@ -363,7 +410,7 @@ public class Guardian extends Monster { this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), f, 90.0F)); this.guardian.yBodyRot = this.guardian.getYRot(); @@ -9634,10 +9484,10 @@ index 5df07b59ff6e39687e361d89d7764381ca3ce9ca..d4de9b066004ec17696f547d8f4067a1 this.guardian.setSpeed(f2); diff --git a/src/main/java/net/minecraft/world/entity/monster/Husk.java b/src/main/java/net/minecraft/world/entity/monster/Husk.java -index c34c8483a026f61fe20935697d321d7ef5d8dfbc..a9285aac811067313c5609d2d5708783736e6cb5 100644 +index 184fa759db065fb345f3623752229430816d8ad3..7c8ec5cd88fb2083f458a945e716b6f118555db8 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Husk.java +++ b/src/main/java/net/minecraft/world/entity/monster/Husk.java -@@ -20,6 +20,59 @@ public class Husk extends Zombie { +@@ -21,6 +21,59 @@ public class Husk extends Zombie { public Husk(EntityType type, Level world) { super(type, world); @@ -9696,8 +9546,8 @@ index c34c8483a026f61fe20935697d321d7ef5d8dfbc..a9285aac811067313c5609d2d5708783 + return this.level().purpurConfig.huskAlwaysDropExp; } - public static boolean checkHuskSpawnRules(EntityType type, ServerLevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { -@@ -28,7 +81,7 @@ public class Husk extends Zombie { + public static boolean checkHuskSpawnRules(EntityType type, ServerLevelAccessor world, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random) { +@@ -29,7 +82,7 @@ public class Husk extends Zombie { @Override public boolean isSunSensitive() { @@ -9707,10 +9557,10 @@ index c34c8483a026f61fe20935697d321d7ef5d8dfbc..a9285aac811067313c5609d2d5708783 @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java -index c858556ea457931aa14e338e20672cb50cb19f0e..f6450648b500733edfcee4564d382e8535d50fe2 100644 +index db3aac9ba711dcd18ffc35c4a745ecaec89d0166..2ca241344efc6320d2018bdc772f74470080eeed 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java -@@ -57,10 +57,46 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { +@@ -59,10 +59,46 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { } @@ -9755,9 +9605,9 @@ index c858556ea457931aa14e338e20672cb50cb19f0e..f6450648b500733edfcee4564d382e85 this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur this.goalSelector.addGoal(1, new SpellcasterIllager.SpellcasterCastingSpellGoal()); + this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Creaking.class, 8.0F, 1.0D, 1.2D)); this.goalSelector.addGoal(4, new Illusioner.IllusionerMirrorSpellGoal()); - this.goalSelector.addGoal(5, new Illusioner.IllusionerBlindnessSpellGoal()); -@@ -68,6 +104,7 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { +@@ -71,6 +107,7 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); @@ -9766,7 +9616,7 @@ index c858556ea457931aa14e338e20672cb50cb19f0e..f6450648b500733edfcee4564d382e85 this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); diff --git a/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java b/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java -index d85a1587a11e735b97107c53ac540cdbe2923ed0..e749050be1e2e7b0e5babb86bbcf88db9c47603c 100644 +index ae710c3fffc7840a9ff2cbc5cdacef8a2e248253..63caf20256a3deae98b9cd9f54650def172f0e57 100644 --- a/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java +++ b/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java @@ -24,6 +24,58 @@ public class MagmaCube extends Slime { @@ -9828,7 +9678,7 @@ index d85a1587a11e735b97107c53ac540cdbe2923ed0..e749050be1e2e7b0e5babb86bbcf88db public static AttributeSupplier.Builder createAttributes() { return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.2F); } -@@ -69,6 +121,7 @@ public class MagmaCube extends Slime { +@@ -71,6 +123,7 @@ public class MagmaCube extends Slime { float f = (float)this.getSize() * 0.1F; this.setDeltaMovement(vec3.x, (double)(this.getJumpPower() + f), vec3.z); this.hasImpulse = true; @@ -9837,10 +9687,10 @@ index d85a1587a11e735b97107c53ac540cdbe2923ed0..e749050be1e2e7b0e5babb86bbcf88db @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/Monster.java b/src/main/java/net/minecraft/world/entity/monster/Monster.java -index e7bfce0534c7ef3a1480a1082ae8514caf78778b..6511b8c737a57fbc72122dd04e2b544987a49b92 100644 +index e2de074bbe7bab0e5a7aecc1fae4c5914a203dd4..c2061f575c731ecc6071384b007517c08e0cf983 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Monster.java +++ b/src/main/java/net/minecraft/world/entity/monster/Monster.java -@@ -87,6 +87,14 @@ public abstract class Monster extends PathfinderMob implements Enemy { +@@ -88,6 +88,14 @@ public abstract class Monster extends PathfinderMob implements Enemy { } public static boolean isDarkEnoughToSpawn(ServerLevelAccessor world, BlockPos pos, RandomSource random) { @@ -9856,10 +9706,10 @@ index e7bfce0534c7ef3a1480a1082ae8514caf78778b..6511b8c737a57fbc72122dd04e2b5449 return false; } else { diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab6408fad8 100644 +index 150fd890ac65097b5434fd88e8d2b24a89dca79a..cda6cb5b10b895bab48d2212f259ba4ca40e1ed6 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java +++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -48,6 +48,8 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -49,6 +49,8 @@ public class Phantom extends FlyingMob implements Enemy { Vec3 moveTargetPoint; public BlockPos anchorPoint; Phantom.AttackPhase attackPhase; @@ -9868,7 +9718,7 @@ index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab public Phantom(EntityType type, Level world) { super(type, world); -@@ -57,6 +59,92 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -58,6 +60,92 @@ public class Phantom extends FlyingMob implements Enemy { this.xpReward = 5; this.moveControl = new Phantom.PhantomMoveControl(this); this.lookControl = new Phantom.PhantomLookControl(this, this); @@ -9933,15 +9783,15 @@ index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab + } + + @Override -+ protected void dropFromLootTable(DamageSource damageSource, boolean causedByPlayer) { ++ protected void dropFromLootTable(ServerLevel world, DamageSource damageSource, boolean causedByPlayer) { + boolean dropped = false; + if (lastHurtByPlayer == null && damageSource.getEntity() instanceof net.minecraft.world.entity.boss.enderdragon.EndCrystal) { + if (random.nextInt(5) < 1) { -+ dropped = spawnAtLocation(new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.PHANTOM_MEMBRANE)) != null; ++ dropped = spawnAtLocation(world, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.PHANTOM_MEMBRANE)) != null; + } + } + if (!dropped) { -+ super.dropFromLootTable(damageSource, causedByPlayer); ++ super.dropFromLootTable(world, damageSource, causedByPlayer); + } + } + @@ -9961,7 +9811,7 @@ index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab } @Override -@@ -71,9 +159,17 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -72,9 +160,17 @@ public class Phantom extends FlyingMob implements Enemy { @Override protected void registerGoals() { @@ -9982,7 +9832,7 @@ index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab this.targetSelector.addGoal(1, new Phantom.PhantomAttackPlayerTargetGoal()); } -@@ -89,7 +185,10 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -90,7 +186,10 @@ public class Phantom extends FlyingMob implements Enemy { private void updatePhantomSizeInfo() { this.refreshDimensions(); @@ -9994,7 +9844,7 @@ index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab } public int getPhantomSize() { -@@ -114,6 +213,21 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -115,6 +214,21 @@ public class Phantom extends FlyingMob implements Enemy { return true; } @@ -10016,7 +9866,7 @@ index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab @Override public void tick() { super.tick(); -@@ -134,14 +248,12 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -135,21 +249,23 @@ public class Phantom extends FlyingMob implements Enemy { this.level().addParticle(ParticleTypes.MYCELIUM, this.getX() - (double) f3, this.getY() + (double) f5, this.getZ() - (double) f4, 0.0D, 0.0D, 0.0D); } @@ -10033,9 +9883,8 @@ index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab super.aiStep(); } -@@ -153,7 +265,11 @@ public class Phantom extends FlyingMob implements Enemy { @Override - public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData) { + public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, EntitySpawnReason spawnReason, @Nullable SpawnGroupData entityData) { this.anchorPoint = this.blockPosition().above(5); - this.setPhantomSize(0); + // Purpur start @@ -10046,7 +9895,7 @@ index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab return super.finalizeSpawn(world, difficulty, spawnReason, entityData); } -@@ -169,7 +285,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -165,7 +281,7 @@ public class Phantom extends FlyingMob implements Enemy { if (nbt.hasUUID("Paper.SpawningEntity")) { this.spawningEntity = nbt.getUUID("Paper.SpawningEntity"); } @@ -10055,7 +9904,7 @@ index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay"); } // Paper end -@@ -186,7 +302,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -182,7 +298,7 @@ public class Phantom extends FlyingMob implements Enemy { if (this.spawningEntity != null) { nbt.putUUID("Paper.SpawningEntity", this.spawningEntity); } @@ -10265,19 +10114,19 @@ index c277dac448a64809e93dd7a447ee3dc2a86c860e..493e9ee0585ae419caffaa163f4975ab } else { if (entityliving instanceof Player) { Player entityhuman = (Player) entityliving; -@@ -548,6 +811,7 @@ public class Phantom extends FlyingMob implements Enemy { - this.nextScanTick = reducedTickDelay(60); - List list = Phantom.this.level().getNearbyPlayers(this.attackTargeting, Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); +@@ -549,6 +812,7 @@ public class Phantom extends FlyingMob implements Enemy { + ServerLevel worldserver = getServerLevel(Phantom.this.level()); + List list = worldserver.getNearbyPlayers(this.attackTargeting, Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); + if (level().purpurConfig.phantomIgnorePlayersWithTorch) list.removeIf(human -> TORCH.test(human.getItemInHand(net.minecraft.world.InteractionHand.MAIN_HAND)) || TORCH.test(human.getItemInHand(net.minecraft.world.InteractionHand.OFF_HAND)));// Purpur if (!list.isEmpty()) { list.sort(Comparator.comparing((Entity e) -> { return e.getY(); }).reversed()); // CraftBukkit - decompile error Iterator iterator = list.iterator(); diff --git a/src/main/java/net/minecraft/world/entity/monster/Pillager.java b/src/main/java/net/minecraft/world/entity/monster/Pillager.java -index 4b4dcee6abe7a6db43638d04665125eec560496e..6f5d28f55ba3b9d7cd2415ee86359303e5cde478 100644 +index 3e8631c7bd1e7591051ca21c6ae7acd87d3c7529..85d5c84a8861905e4546901aa6707078571eb402 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Pillager.java +++ b/src/main/java/net/minecraft/world/entity/monster/Pillager.java -@@ -62,15 +62,50 @@ public class Pillager extends AbstractIllager implements CrossbowAttackMob, Inve +@@ -64,16 +64,51 @@ public class Pillager extends AbstractIllager implements CrossbowAttackMob, Inve super(type, world); } @@ -10319,6 +10168,7 @@ index 4b4dcee6abe7a6db43638d04665125eec560496e..6f5d28f55ba3b9d7cd2415ee86359303 super.registerGoals(); this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Creaking.class, 8.0F, 1.0D, 1.2D)); this.goalSelector.addGoal(2, new Raider.HoldGroundAttackGoal(this, 10.0F)); // Paper - decomp fix this.goalSelector.addGoal(3, new RangedCrossbowAttackGoal<>(this, 1.0D, 8.0F)); this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); @@ -10329,10 +10179,10 @@ index 4b4dcee6abe7a6db43638d04665125eec560496e..6f5d28f55ba3b9d7cd2415ee86359303 this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java -index 212d341425c0f93bba0376de69bea61ffcf4dbd6..4f10d4686f12a81a77f5fc103139aa03069b398c 100644 +index c96fbfe448b3e7b722a8db0e1688276776abd94e..98c1934b4895a86cd8748edf906aaa721a87a123 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java +++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java -@@ -69,14 +69,56 @@ public class Ravager extends Raider { +@@ -77,15 +77,57 @@ public class Ravager extends Raider { this.setPathfindingMalus(PathType.LEAVES, 0.0F); } @@ -10380,6 +10230,7 @@ index 212d341425c0f93bba0376de69bea61ffcf4dbd6..4f10d4686f12a81a77f5fc103139aa03 super.registerGoals(); this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Creaking.class, 8.0F, 1.0D, 1.2D)); + if (level().purpurConfig.ravagerAvoidRabbits) this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.AvoidEntityGoal<>(this, net.minecraft.world.entity.animal.Rabbit.class, 6.0F, 1.0D, 1.2D)); // Purpur this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, true)); this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4D)); @@ -10388,8 +10239,8 @@ index 212d341425c0f93bba0376de69bea61ffcf4dbd6..4f10d4686f12a81a77f5fc103139aa03 + this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur this.targetSelector.addGoal(2, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true)); - this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, (entityliving) -> { -@@ -129,7 +171,7 @@ public class Ravager extends Raider { + this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, (entityliving, worldserver) -> { +@@ -138,7 +180,7 @@ public class Ravager extends Raider { @Override public void aiStep() { super.aiStep(); @@ -10398,29 +10249,29 @@ index 212d341425c0f93bba0376de69bea61ffcf4dbd6..4f10d4686f12a81a77f5fc103139aa03 if (this.isImmobile()) { this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0D); } else { -@@ -139,7 +181,7 @@ public class Ravager extends Raider { - this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(Mth.lerp(0.1D, d1, d0)); - } - -- if (this.horizontalCollision && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ if (this.horizontalCollision && (this.level().purpurConfig.ravagerBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // Purpur - boolean flag = false; - AABB axisalignedbb = this.getBoundingBox().inflate(0.2D); - Iterator iterator = BlockPos.betweenClosed(Mth.floor(axisalignedbb.minX), Mth.floor(axisalignedbb.minY), Mth.floor(axisalignedbb.minZ), Mth.floor(axisalignedbb.maxX), Mth.floor(axisalignedbb.maxY), Mth.floor(axisalignedbb.maxZ)).iterator(); -@@ -149,7 +191,7 @@ public class Ravager extends Raider { - BlockState iblockdata = this.level().getBlockState(blockposition); - Block block = iblockdata.getBlock(); +@@ -153,7 +195,7 @@ public class Ravager extends Raider { + if (world instanceof ServerLevel) { + ServerLevel worldserver = (ServerLevel) world; -- if (block instanceof LeavesBlock) { -+ if (this.level().purpurConfig.ravagerGriefableBlocks.contains(block)) { // Purpur - // CraftBukkit start - if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, iblockdata.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state - continue; +- if (this.horizontalCollision && worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (this.horizontalCollision && (worldserver.purpurConfig.ravagerBypassMobGriefing ^ worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // Purpur + boolean flag = false; + AABB axisalignedbb = this.getBoundingBox().inflate(0.2D); + Iterator iterator = BlockPos.betweenClosed(Mth.floor(axisalignedbb.minX), Mth.floor(axisalignedbb.minY), Mth.floor(axisalignedbb.minZ), Mth.floor(axisalignedbb.maxX), Mth.floor(axisalignedbb.maxY), Mth.floor(axisalignedbb.maxZ)).iterator(); +@@ -163,7 +205,7 @@ public class Ravager extends Raider { + BlockState iblockdata = worldserver.getBlockState(blockposition); + Block block = iblockdata.getBlock(); + +- if (block instanceof LeavesBlock) { ++ if (this.level().purpurConfig.ravagerGriefableBlocks.contains(block)) { // Purpur + // CraftBukkit start + if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, iblockdata.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state + continue; diff --git a/src/main/java/net/minecraft/world/entity/monster/Shulker.java b/src/main/java/net/minecraft/world/entity/monster/Shulker.java -index 920c7a92643e83598f39bf984cca430d9deed2cd..76d37a649bfa1f504c969f92a34fcce0629cb347 100644 +index 6e0f2f6573ed6be9b91de960d55c269417ad8907..e3fefd52c83079fe3eab1a96dd81a183f718192b 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Shulker.java +++ b/src/main/java/net/minecraft/world/entity/monster/Shulker.java -@@ -83,7 +83,7 @@ public class Shulker extends AbstractGolem implements VariantHolder variant) { -@@ -598,7 +655,7 @@ public class Shulker extends AbstractGolem implements VariantHolder getVariant() { @@ -10535,7 +10386,7 @@ index 920c7a92643e83598f39bf984cca430d9deed2cd..76d37a649bfa1f504c969f92a34fcce0 } @Nullable -@@ -608,7 +665,7 @@ public class Shulker extends AbstractGolem implements VariantHolder(this, Player.class, true)); } -@@ -167,7 +204,7 @@ public class Silverfish extends Monster { +@@ -165,12 +202,12 @@ public class Silverfish extends Monster { + + if (block instanceof InfestedBlock) { + // CraftBukkit start +- BlockState afterState = getServerLevel(world).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? iblockdata.getFluidState().createLegacyBlock() : ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)); // Paper - fix wrong block state ++ BlockState afterState = (getServerLevel(world).purpurConfig.silverfishBypassMobGriefing ^ getServerLevel(world).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) ? iblockdata.getFluidState().createLegacyBlock() : ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)); // Paper - fix wrong block state + if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, afterState)) { // Paper - fix wrong block state continue; } // CraftBukkit end -- if (world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ if (world.purpurConfig.silverfishBypassMobGriefing || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur +- if (getServerLevel(world).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ if (getServerLevel(world).purpurConfig.silverfishBypassMobGriefing ^ getServerLevel(world).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur world.destroyBlock(blockposition1, true, this.silverfish); } else { world.setBlock(blockposition1, ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)), 3); -@@ -205,7 +242,7 @@ public class Silverfish extends Monster { +@@ -208,7 +245,7 @@ public class Silverfish extends Monster { } else { RandomSource randomsource = this.mob.getRandom(); -- if (this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && randomsource.nextInt(reducedTickDelay(10)) == 0) { -+ if ((this.mob.level().purpurConfig.silverfishBypassMobGriefing || this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && randomsource.nextInt(reducedTickDelay(10)) == 0) { // Purpur +- if (getServerLevel((Entity) this.mob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && randomsource.nextInt(reducedTickDelay(10)) == 0) { ++ if (getServerLevel((Entity) this.mob).purpurConfig.silverfishBypassMobGriefing ^ getServerLevel((Entity) this.mob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && randomsource.nextInt(reducedTickDelay(10)) == 0) { // Purpur this.selectedDirection = Direction.getRandom(randomsource); BlockPos blockposition = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); BlockState iblockdata = this.mob.level().getBlockState(blockposition); diff --git a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java -index cee42ae2b75c29c89e7fc5b1c77d3b45ce40e9ba..cb714f78ad73f709967d7449c411c5b1385a9440 100644 +index 3972e2ed0554e2550519e994888e068df0a151e5..3cbe4c1ed514936a00e0181cb1e647fbb58032bb 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java +++ b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java -@@ -15,6 +15,16 @@ import net.minecraft.world.item.Items; +@@ -17,6 +17,16 @@ import net.minecraft.world.item.Items; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.Level; @@ -10639,7 +10496,7 @@ index cee42ae2b75c29c89e7fc5b1c77d3b45ce40e9ba..cb714f78ad73f709967d7449c411c5b1 public class Skeleton extends AbstractSkeleton { private static final int TOTAL_CONVERSION_TIME = 300; -@@ -27,6 +37,40 @@ public class Skeleton extends AbstractSkeleton { +@@ -29,6 +39,40 @@ public class Skeleton extends AbstractSkeleton { super(type, world); } @@ -10680,7 +10537,7 @@ index cee42ae2b75c29c89e7fc5b1c77d3b45ce40e9ba..cb714f78ad73f709967d7449c411c5b1 @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); -@@ -141,4 +185,63 @@ public class Skeleton extends AbstractSkeleton { +@@ -147,4 +191,63 @@ public class Skeleton extends AbstractSkeleton { } } @@ -10707,7 +10564,7 @@ index cee42ae2b75c29c89e7fc5b1c77d3b45ce40e9ba..cb714f78ad73f709967d7449c411c5b1 + return InteractionResult.CONSUME; + } + -+ WitherSkeleton skeleton = EntityType.WITHER_SKELETON.create(level()); ++ WitherSkeleton skeleton = EntityType.WITHER_SKELETON.create(level(), net.minecraft.world.entity.EntitySpawnReason.CONVERSION); + if (skeleton == null) { + return InteractionResult.PASS; + } @@ -10745,10 +10602,10 @@ index cee42ae2b75c29c89e7fc5b1c77d3b45ce40e9ba..cb714f78ad73f709967d7449c411c5b1 + // Purpur end } diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java -index adebb66e550f805f444bec22e9a4dd575a642b43..40c00f73502be66f2a0f3cdb36b963fb25c60704 100644 +index 72346a7e5269c91e3143933ac37e65ad9639b791..dad4ef9c672eb4247142de5d045678795951164c 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Slime.java +++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java -@@ -63,6 +63,7 @@ public class Slime extends Mob implements Enemy { +@@ -65,6 +65,7 @@ public class Slime extends Mob implements Enemy { public float squish; public float oSquish; private boolean wasOnGround; @@ -10756,7 +10613,7 @@ index adebb66e550f805f444bec22e9a4dd575a642b43..40c00f73502be66f2a0f3cdb36b963fb public Slime(EntityType type, Level world) { super(type, world); -@@ -70,12 +71,89 @@ public class Slime extends Mob implements Enemy { +@@ -72,12 +73,89 @@ public class Slime extends Mob implements Enemy { this.moveControl = new Slime.SlimeMoveControl(this); } @@ -10843,10 +10700,10 @@ index adebb66e550f805f444bec22e9a4dd575a642b43..40c00f73502be66f2a0f3cdb36b963fb this.goalSelector.addGoal(3, new Slime.SlimeRandomDirectionGoal(this)); this.goalSelector.addGoal(5, new Slime.SlimeKeepOnJumpingGoal(this)); + this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving, worldserver) -> { return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; })); -@@ -100,9 +178,9 @@ public class Slime extends Mob implements Enemy { +@@ -102,9 +180,9 @@ public class Slime extends Mob implements Enemy { this.entityData.set(Slime.ID_SIZE, j); this.reapplyPosition(); this.refreshDimensions(); @@ -10858,7 +10715,7 @@ index adebb66e550f805f444bec22e9a4dd575a642b43..40c00f73502be66f2a0f3cdb36b963fb if (heal) { this.setHealth(this.getMaxHealth()); } -@@ -395,6 +473,7 @@ public class Slime extends Mob implements Enemy { +@@ -386,6 +464,7 @@ public class Slime extends Mob implements Enemy { this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); this.hasImpulse = true; @@ -10866,7 +10723,7 @@ index adebb66e550f805f444bec22e9a4dd575a642b43..40c00f73502be66f2a0f3cdb36b963fb } @Nullable -@@ -428,7 +507,7 @@ public class Slime extends Mob implements Enemy { +@@ -419,7 +498,7 @@ public class Slime extends Mob implements Enemy { return super.getDefaultDimensions(pose).scale((float) this.getSize()); } @@ -10875,7 +10732,7 @@ index adebb66e550f805f444bec22e9a4dd575a642b43..40c00f73502be66f2a0f3cdb36b963fb private float yRot; private int jumpDelay; -@@ -447,21 +526,33 @@ public class Slime extends Mob implements Enemy { +@@ -438,21 +517,33 @@ public class Slime extends Mob implements Enemy { } public void setWantedMovement(double speed) { @@ -10912,7 +10769,7 @@ index adebb66e550f805f444bec22e9a4dd575a642b43..40c00f73502be66f2a0f3cdb36b963fb if (this.jumpDelay-- <= 0) { this.jumpDelay = this.slime.getJumpDelay(); if (this.isAggressive) { -@@ -478,7 +569,7 @@ public class Slime extends Mob implements Enemy { +@@ -469,7 +560,7 @@ public class Slime extends Mob implements Enemy { this.mob.setSpeed(0.0F); } } else { @@ -10922,7 +10779,7 @@ index adebb66e550f805f444bec22e9a4dd575a642b43..40c00f73502be66f2a0f3cdb36b963fb } diff --git a/src/main/java/net/minecraft/world/entity/monster/Spider.java b/src/main/java/net/minecraft/world/entity/monster/Spider.java -index a30fb47559eb74b7fe634678e63a85e7e2cad9a4..5f1e8817f959cc39f7df75df2b5bae7014dc35d1 100644 +index 91e521414c3ea5722aac7506b7589fbb399e9636..1669acbcf97bee0fa6b0ee91cf53217c53cf55d8 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Spider.java +++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java @@ -51,9 +51,43 @@ public class Spider extends Monster { @@ -10978,7 +10835,7 @@ index a30fb47559eb74b7fe634678e63a85e7e2cad9a4..5f1e8817f959cc39f7df75df2b5bae70 this.targetSelector.addGoal(2, new Spider.SpiderTargetGoal<>(this, Player.class)); this.targetSelector.addGoal(3, new Spider.SpiderTargetGoal<>(this, IronGolem.class)); diff --git a/src/main/java/net/minecraft/world/entity/monster/Stray.java b/src/main/java/net/minecraft/world/entity/monster/Stray.java -index 1b8ab3f1090ea78bdba97265e05576c9a3e2deb3..588c8cefefde335cc9c02f77d0d050ee13bbb8d2 100644 +index baaf17107584b253d7e268749849bf5b0d0c88ab..bb6984d82e6c0a83f456e725b20e0f21e0cac602 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Stray.java +++ b/src/main/java/net/minecraft/world/entity/monster/Stray.java @@ -22,6 +22,38 @@ public class Stray extends AbstractSkeleton { @@ -11017,11 +10874,11 @@ index 1b8ab3f1090ea78bdba97265e05576c9a3e2deb3..588c8cefefde335cc9c02f77d0d050ee + return this.level().purpurConfig.strayAlwaysDropExp; + } + - public static boolean checkStraySpawnRules(EntityType type, ServerLevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { - BlockPos blockPos = pos; - + public static boolean checkStraySpawnRules( + EntityType type, ServerLevelAccessor world, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random + ) { diff --git a/src/main/java/net/minecraft/world/entity/monster/Strider.java b/src/main/java/net/minecraft/world/entity/monster/Strider.java -index 2c5bfad3c1ae9a19b4762831a3abdd5e89ba24b3..70650cc6f76bed79a31a9e8c86205910994a920f 100644 +index 711b7eb8e9fdedbc87965828e573fe8d5c357d53..c3b5b34a54de945071692293645b8a8865aed961 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Strider.java +++ b/src/main/java/net/minecraft/world/entity/monster/Strider.java @@ -91,12 +91,45 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { @@ -11068,7 +10925,7 @@ index 2c5bfad3c1ae9a19b4762831a3abdd5e89ba24b3..70650cc6f76bed79a31a9e8c86205910 + return this.level().purpurConfig.striderAlwaysDropExp; + } + - public static boolean checkStriderSpawnRules(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) { + public static boolean checkStriderSpawnRules(EntityType type, LevelAccessor world, EntitySpawnReason spawnReason, BlockPos pos, RandomSource random) { BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); @@ -158,6 +191,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { @@ -11079,7 +10936,7 @@ index 2c5bfad3c1ae9a19b4762831a3abdd5e89ba24b3..70650cc6f76bed79a31a9e8c86205910 this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); this.temptGoal = new TemptGoal(this, 1.4D, (itemstack) -> { return itemstack.is(ItemTags.STRIDER_TEMPT_ITEMS); -@@ -414,7 +448,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { +@@ -412,7 +446,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { @Override public boolean isSensitiveToWater() { @@ -11088,7 +10945,7 @@ index 2c5bfad3c1ae9a19b4762831a3abdd5e89ba24b3..70650cc6f76bed79a31a9e8c86205910 } @Override -@@ -456,6 +490,19 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { +@@ -454,6 +488,19 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { public InteractionResult mobInteract(Player player, InteractionHand hand) { boolean flag = this.isFood(player.getItemInHand(hand)); @@ -11108,20 +10965,20 @@ index 2c5bfad3c1ae9a19b4762831a3abdd5e89ba24b3..70650cc6f76bed79a31a9e8c86205910 if (!flag && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { if (!this.level().isClientSide) { player.startRiding(this); -@@ -468,7 +515,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { +@@ -466,7 +513,7 @@ public class Strider extends Animal implements ItemSteerable, Saddleable { if (!enuminteractionresult.consumesAction()) { ItemStack itemstack = player.getItemInHand(hand); -- return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : InteractionResult.PASS; -+ return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : tryRide(player, hand); // Purpur +- return (InteractionResult) (itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : InteractionResult.PASS); ++ return (InteractionResult) (itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : tryRide(player, hand)); // Purpur } else { if (flag && !this.isSilent()) { this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.STRIDER_EAT, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java -index 2985296a9a034e535157f55e322fc8c107827752..f413815e65ffc4addb4ac75b96d5d0333507466b 100644 +index 183a33b7d666d652b455baa7e8339e9c4a870a58..fe19c0cf6a2c81b547158179518bf26be388cc7a 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Vex.java +++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java -@@ -60,6 +60,66 @@ public class Vex extends Monster implements TraceableEntity { +@@ -59,6 +59,66 @@ public class Vex extends Monster implements TraceableEntity { this.xpReward = 3; } @@ -11158,7 +11015,7 @@ index 2985296a9a034e535157f55e322fc8c107827752..f413815e65ffc4addb4ac75b96d5d033 + } + setSpeed(speed); + Vec3 mot = getDeltaMovement(); -+ move(MoverType.SELF, mot.multiply(speed, 1.0, speed)); ++ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 1.0, speed)); + setDeltaMovement(mot.scale(0.9D)); + } + } @@ -11188,7 +11045,7 @@ index 2985296a9a034e535157f55e322fc8c107827752..f413815e65ffc4addb4ac75b96d5d033 @Override public boolean isFlapping() { return this.tickCount % Vex.TICKS_PER_FLAP == 0; -@@ -73,7 +133,7 @@ public class Vex extends Monster implements TraceableEntity { +@@ -71,7 +131,7 @@ public class Vex extends Monster implements TraceableEntity { @Override public void tick() { @@ -11197,7 +11054,7 @@ index 2985296a9a034e535157f55e322fc8c107827752..f413815e65ffc4addb4ac75b96d5d033 super.tick(); this.noPhysics = false; this.setNoGravity(true); -@@ -88,17 +148,19 @@ public class Vex extends Monster implements TraceableEntity { +@@ -86,17 +146,19 @@ public class Vex extends Monster implements TraceableEntity { protected void registerGoals() { super.registerGoals(); this.goalSelector.addGoal(0, new FloatGoal(this)); @@ -11218,7 +11075,7 @@ index 2985296a9a034e535157f55e322fc8c107827752..f413815e65ffc4addb4ac75b96d5d033 } @Override -@@ -230,14 +292,14 @@ public class Vex extends Monster implements TraceableEntity { +@@ -228,14 +290,14 @@ public class Vex extends Monster implements TraceableEntity { this.setDropChance(EquipmentSlot.MAINHAND, 0.0F); } @@ -11235,7 +11092,7 @@ index 2985296a9a034e535157f55e322fc8c107827752..f413815e65ffc4addb4ac75b96d5d033 if (this.operation == MoveControl.Operation.MOVE_TO) { Vec3 vec3d = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ()); double d0 = vec3d.length(); -@@ -246,7 +308,7 @@ public class Vex extends Monster implements TraceableEntity { +@@ -244,7 +306,7 @@ public class Vex extends Monster implements TraceableEntity { this.operation = MoveControl.Operation.WAIT; Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5D)); } else { @@ -11245,10 +11102,10 @@ index 2985296a9a034e535157f55e322fc8c107827752..f413815e65ffc4addb4ac75b96d5d033 Vec3 vec3d1 = Vex.this.getDeltaMovement(); diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -index 0615bb305d70f660a6baa7f78078990d6db227d3..d7d4c2fa1e3a9105b7accf742448e62161506695 100644 +index 96b105697c91314148fd1b783501389214b1a3f0..a2c81d2a1077b2977f1595fd592044baf3e81bab 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java -@@ -53,14 +53,49 @@ public class Vindicator extends AbstractIllager { +@@ -55,15 +55,50 @@ public class Vindicator extends AbstractIllager { super(type, world); } @@ -11290,15 +11147,16 @@ index 0615bb305d70f660a6baa7f78078990d6db227d3..d7d4c2fa1e3a9105b7accf742448e621 super.registerGoals(); this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new Vindicator.VindicatorBreakDoorGoal(this)); - this.goalSelector.addGoal(2, new AbstractIllager.RaiderOpenDoorGoal(this)); - this.goalSelector.addGoal(3, new Raider.HoldGroundAttackGoal(this, 10.0F)); - this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, false)); + this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Creaking.class, 8.0F, 1.0, 1.2)); + this.goalSelector.addGoal(2, new Vindicator.VindicatorBreakDoorGoal(this)); + this.goalSelector.addGoal(3, new AbstractIllager.RaiderOpenDoorGoal(this)); + this.goalSelector.addGoal(4, new Raider.HoldGroundAttackGoal(this, 10.0F)); + this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0, false)); + this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class).setAlertOthers()); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true)); -@@ -127,6 +162,11 @@ public class Vindicator extends AbstractIllager { +@@ -132,6 +167,11 @@ public class Vindicator extends AbstractIllager { RandomSource randomSource = world.getRandom(); this.populateDefaultEquipmentSlots(randomSource, difficulty); this.populateDefaultEquipmentEnchantments(world, randomSource, difficulty); @@ -11311,10 +11169,10 @@ index 0615bb305d70f660a6baa7f78078990d6db227d3..d7d4c2fa1e3a9105b7accf742448e621 } diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java -index b8ff1e3d280171378fe383bcc7c6a855d20ae5d1..dd4f10fa5c8d580598bb55d859e70583026b16b3 100644 +index a03fa8a3e648532a7ffaaf523ca87c13e8af4c0a..313228811d1eff478887511f99b49706efc49774 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Witch.java +++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java -@@ -56,6 +56,39 @@ public class Witch extends Raider implements RangedAttackMob { +@@ -57,6 +57,39 @@ public class Witch extends Raider implements RangedAttackMob { super(type, world); } @@ -11354,9 +11212,9 @@ index b8ff1e3d280171378fe383bcc7c6a855d20ae5d1..dd4f10fa5c8d580598bb55d859e70583 @Override protected void registerGoals() { super.registerGoals(); -@@ -64,10 +97,12 @@ public class Witch extends Raider implements RangedAttackMob { +@@ -65,10 +98,12 @@ public class Witch extends Raider implements RangedAttackMob { }); - this.attackPlayersGoal = new NearestAttackableWitchTargetGoal<>(this, Player.class, 10, true, false, (Predicate) null); + this.attackPlayersGoal = new NearestAttackableWitchTargetGoal<>(this, Player.class, 10, true, false, (TargetingConditions.Selector) null); this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0D, 60, 10.0F)); @@ -11368,7 +11226,7 @@ index b8ff1e3d280171378fe383bcc7c6a855d20ae5d1..dd4f10fa5c8d580598bb55d859e70583 this.targetSelector.addGoal(2, this.healRaidersGoal); this.targetSelector.addGoal(3, this.attackPlayersGoal); diff --git a/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java -index bb2e7cee612dc1fafa042674a0b0d07d7165b54c..1abef17858b9549fe01d213d057cc1101df37b55 100644 +index 37d3acda84a984bf4f1c44b3d27e2102839d3e8e..23fc36780a3e15260f8cb1001c8d676464a9df3a 100644 --- a/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java +++ b/src/main/java/net/minecraft/world/entity/monster/WitherSkeleton.java @@ -33,6 +33,39 @@ public class WitherSkeleton extends AbstractSkeleton { @@ -11412,10 +11270,10 @@ index bb2e7cee612dc1fafa042674a0b0d07d7165b54c..1abef17858b9549fe01d213d057cc110 protected void registerGoals() { this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractPiglin.class, true)); diff --git a/src/main/java/net/minecraft/world/entity/monster/Zoglin.java b/src/main/java/net/minecraft/world/entity/monster/Zoglin.java -index 0d447c8a141a7d7fcaf9218571bf0513dd28269e..fdc57a81cbd7a02a3ade0da8ff84d7df5361c783 100644 +index 50b559a92b54c0be7624b1aebc70537573c58666..3f388ea39d2760df946cc027a4ae63704dcaa03a 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zoglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zoglin.java -@@ -79,6 +79,39 @@ public class Zoglin extends Monster implements Enemy, HoglinBase { +@@ -83,6 +83,39 @@ public class Zoglin extends Monster implements HoglinBase { this.xpReward = 5; } @@ -11455,19 +11313,19 @@ index 0d447c8a141a7d7fcaf9218571bf0513dd28269e..fdc57a81cbd7a02a3ade0da8ff84d7df @Override protected Brain.Provider brainProvider() { return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); -@@ -233,6 +266,7 @@ public class Zoglin extends Monster implements Enemy, HoglinBase { +@@ -246,6 +279,7 @@ public class Zoglin extends Monster implements HoglinBase { @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel)this.level(), this); + this.getBrain().tick(world, this); this.updateActivity(); } diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 2b43337ac63d051718a2074fcc46e128a1d65129..479232d8dfaabdb3da5b825969d377aa437ea7d3 100644 +index a12461907278cfbfa3b1c0aa74b9f07a31768b8a..85b03e0bf7436cb846df13c575ad78ac6a17a151 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -97,22 +97,70 @@ public class Zombie extends Monster { +@@ -99,22 +99,70 @@ public class Zombie extends Monster { private int inWaterTime; public int conversionTime; // private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field // Paper - remove anti tick skipping measures / wall time @@ -11539,7 +11397,7 @@ index 2b43337ac63d051718a2074fcc46e128a1d65129..479232d8dfaabdb3da5b825969d377aa this.addBehaviourGoals(); } -@@ -122,7 +170,19 @@ public class Zombie extends Monster { +@@ -124,7 +172,19 @@ public class Zombie extends Monster { this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers(ZombifiedPiglin.class)); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); @@ -11560,7 +11418,7 @@ index 2b43337ac63d051718a2074fcc46e128a1d65129..479232d8dfaabdb3da5b825969d377aa this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); } -@@ -241,32 +301,7 @@ public class Zombie extends Monster { +@@ -239,32 +299,7 @@ public class Zombie extends Monster { @Override public void aiStep() { @@ -11594,15 +11452,15 @@ index 2b43337ac63d051718a2074fcc46e128a1d65129..479232d8dfaabdb3da5b825969d377aa super.aiStep(); } -@@ -304,6 +339,7 @@ public class Zombie extends Monster { - +@@ -324,6 +359,7 @@ public class Zombie extends Monster { + // CraftBukkit end } + public boolean shouldBurnInDay() { return this.isSunSensitive(); } // Purpur - for ABI compatibility - API for any mob to burn daylight public boolean isSunSensitive() { return this.shouldBurnInDay; // Paper - Add more Zombie API } -@@ -432,7 +468,7 @@ public class Zombie extends Monster { +@@ -462,7 +498,7 @@ public class Zombie extends Monster { nbt.putBoolean("CanBreakDoors", this.canBreakDoors()); nbt.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); nbt.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); @@ -11611,7 +11469,7 @@ index 2b43337ac63d051718a2074fcc46e128a1d65129..479232d8dfaabdb3da5b825969d377aa } @Override -@@ -445,7 +481,7 @@ public class Zombie extends Monster { +@@ -475,7 +511,7 @@ public class Zombie extends Monster { this.startUnderWaterConversion(nbt.getInt("DrownedConversionTime")); } // Paper start - Add more Zombie API @@ -11620,7 +11478,7 @@ index 2b43337ac63d051718a2074fcc46e128a1d65129..479232d8dfaabdb3da5b825969d377aa this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay"); } // Paper end - Add more Zombie API -@@ -517,19 +553,20 @@ public class Zombie extends Monster { +@@ -528,19 +564,20 @@ public class Zombie extends Monster { } if (object instanceof Zombie.ZombieGroupData entityzombie_groupdatazombie) { @@ -11644,10 +11502,10 @@ index 2b43337ac63d051718a2074fcc46e128a1d65129..479232d8dfaabdb3da5b825969d377aa - } - } else if ((double) randomsource.nextFloat() < 0.05D) { + } else { // Purpur - Chicken entitychicken1 = (Chicken) EntityType.CHICKEN.create(this.level()); + Chicken entitychicken1 = (Chicken) EntityType.CHICKEN.create(this.level(), EntitySpawnReason.JOCKEY); if (entitychicken1 != null) { -@@ -539,6 +576,7 @@ public class Zombie extends Monster { +@@ -550,6 +587,7 @@ public class Zombie extends Monster { this.startRiding(entitychicken1); world.addFreshEntity(entitychicken1, CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit } @@ -11655,7 +11513,7 @@ index 2b43337ac63d051718a2074fcc46e128a1d65129..479232d8dfaabdb3da5b825969d377aa } } } -@@ -549,11 +587,7 @@ public class Zombie extends Monster { +@@ -562,11 +600,7 @@ public class Zombie extends Monster { } if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { @@ -11668,7 +11526,7 @@ index 2b43337ac63d051718a2074fcc46e128a1d65129..479232d8dfaabdb3da5b825969d377aa this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(randomsource.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; } -@@ -585,7 +619,7 @@ public class Zombie extends Monster { +@@ -608,7 +642,7 @@ public class Zombie extends Monster { } protected void randomizeReinforcementsChance() { @@ -11678,10 +11536,10 @@ index 2b43337ac63d051718a2074fcc46e128a1d65129..479232d8dfaabdb3da5b825969d377aa @Override diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java -index e0dabbf6d7a87b8722769c78ef0d2ba4353ed2cb..5ead916772c21d8db98e389984d531aae7f59700 100644 +index 18c19e4b675000aacb74344909fc104964231008..6f6b32bf7f68d05e4173c31f2e631a409b858a05 100644 --- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java +++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java -@@ -83,6 +83,58 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { +@@ -85,6 +85,58 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { }); } @@ -11740,7 +11598,7 @@ index e0dabbf6d7a87b8722769c78ef0d2ba4353ed2cb..5ead916772c21d8db98e389984d531aa @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); -@@ -175,10 +227,10 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { +@@ -177,10 +229,10 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.is(Items.GOLDEN_APPLE)) { @@ -11752,9 +11610,9 @@ index e0dabbf6d7a87b8722769c78ef0d2ba4353ed2cb..5ead916772c21d8db98e389984d531aa + this.startConverting(player.getUUID(), this.random.nextInt(level().purpurConfig.zombieVillagerCuringTimeMax - level().purpurConfig.zombieVillagerCuringTimeMin + 1) + level().purpurConfig.zombieVillagerCuringTimeMin); // Purpur } - return InteractionResult.SUCCESS; + return InteractionResult.SUCCESS_SERVER; diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java -index 10388cf33f6f33070aa84b3b2d7bd14fc50ceea8..1c04fbea0dce4167a0902b92b95d470f562825c2 100644 +index 03e3cbe73119ca76417d4dd192e1560bdfc373ec..8c3271dcc8c9aa58e2e007eba282c11e42b4e0c9 100644 --- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java @@ -63,6 +63,54 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { @@ -11839,11 +11697,95 @@ index 10388cf33f6f33070aa84b3b2d7bd14fc50ceea8..1c04fbea0dce4167a0902b92b95d470f } @Nullable +diff --git a/src/main/java/net/minecraft/world/entity/monster/creaking/Creaking.java b/src/main/java/net/minecraft/world/entity/monster/creaking/Creaking.java +index 444e67eb9fa1fabff2304896bdd71772747dc437..b48b0124014f1cc9d206d343daf7170691d04b3f 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/creaking/Creaking.java ++++ b/src/main/java/net/minecraft/world/entity/monster/creaking/Creaking.java +@@ -61,6 +61,29 @@ public class Creaking extends Monster { + this.xpReward = 0; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level().purpurConfig.creakingRidable; ++ } ++ ++ @Override ++ public boolean dismountsUnderwater() { ++ return level().purpurConfig.useDismountsUnderwaterTag ? super.dismountsUnderwater() : !level().purpurConfig.creakingRidableInWater; ++ } ++ ++ @Override ++ public boolean isControllable() { ++ return level().purpurConfig.creakingControllable; ++ } ++ ++ @Override ++ protected void registerGoals() { ++ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur ++ this.targetSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur ++ } ++ // Purpur end ++ + @Override + protected BodyRotationControl createBodyControl() { + return new Creaking.CreakingBodyRotationControl(this); +@@ -180,6 +203,14 @@ public class Creaking extends Monster { + return this.isActive() ? null : SoundEvents.CREAKING_AMBIENT; + } + ++ // Purpur start ++ @Override ++ public void initAttributes() { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.creakingMaxHealth); ++ this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.creakingScale); ++ } ++ // Purpur end ++ + @Override + protected SoundEvent getHurtSound(DamageSource source) { + return SoundEvents.CREAKING_SWAY; +@@ -291,28 +322,28 @@ public class Creaking extends Monster { + } + } + +- class CreakingLookControl extends LookControl { ++ class CreakingLookControl extends org.purpurmc.purpur.controller.LookControllerWASD { // Purpur + public CreakingLookControl(final Creaking creaking) { + super(creaking); + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (Creaking.this.canMove()) { +- super.tick(); ++ super.vanillaTick(); // Purpur + } + } + } + +- class CreakingMoveControl extends MoveControl { ++ class CreakingMoveControl extends org.purpurmc.purpur.controller.MoveControllerWASD { // Purpur + public CreakingMoveControl(final Creaking creaking) { + super(creaking); + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (Creaking.this.canMove()) { +- super.tick(); ++ super.vanillaTick(); // Purpur + } + } + } diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java -index 14878f825cc80296ffa09b5b2c0d8ed9a134491b..e9efb85fdcbb5d4a4ae4971536da2ffd205a3e4e 100644 +index 9802aa9a1e4822684ba4406d2cafa4af69fe2ec5..4930459f7fe91eddb5049be3503bf0f2e3821ec4 100644 --- a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java -@@ -90,6 +90,44 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { +@@ -69,11 +69,49 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { this.xpReward = 5; } @@ -11870,6 +11812,11 @@ index 14878f825cc80296ffa09b5b2c0d8ed9a134491b..e9efb85fdcbb5d4a4ae4971536da2ffd + } + // Purpur end + + @VisibleForTesting + public void setTimeInOverworld(int timeInOverworld) { + this.timeInOverworld = timeInOverworld; + } + + @Override + public int getPurpurBreedTime() { + return this.level().purpurConfig.hoglinBreedingTicks; @@ -11888,20 +11835,20 @@ index 14878f825cc80296ffa09b5b2c0d8ed9a134491b..e9efb85fdcbb5d4a4ae4971536da2ffd @Override public boolean canBeLeashed() { return true; -@@ -156,7 +194,7 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { +@@ -139,7 +177,7 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { private int behaviorTick; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { - if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish + if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel)this.level(), this); + this.getBrain().tick(world, this); HoglinAi.updateActivity(this); if (this.isConverting()) { diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java -index 6da1335186a6d31d8e78542f8b3bd11d214ef13c..5f16aebecd621471a05a8bb72a5aa408b78da05e 100644 +index aeedddd4b2ade905455c04ce475d35042c54e741..26d2ce3504efd8077a2d8c7d29a179f9ba47d63b 100644 --- a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java -@@ -93,6 +93,39 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento +@@ -94,6 +94,39 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento this.xpReward = 5; } @@ -11941,42 +11888,42 @@ index 6da1335186a6d31d8e78542f8b3bd11d214ef13c..5f16aebecd621471a05a8bb72a5aa408 @Override public void addAdditionalSaveData(CompoundTag nbt) { super.addAdditionalSaveData(nbt); -@@ -296,7 +329,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento +@@ -305,7 +338,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento private int behaviorTick; // Pufferfish @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { - if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish + if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel) this.level(), this); + this.getBrain().tick(world, this); PiglinAi.updateActivity(this); - super.customServerAiStep(); -@@ -388,7 +421,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento + super.customServerAiStep(world); +@@ -401,7 +434,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento @Override - public boolean wantsToPickUp(ItemStack stack) { -- return this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.canPickUpLoot() && PiglinAi.wantsToPickup(this, stack); -+ return (this.level().purpurConfig.piglinBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && this.canPickUpLoot() && PiglinAi.wantsToPickup(this, stack); + public boolean wantsToPickUp(ServerLevel world, ItemStack stack) { +- return world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.canPickUpLoot() && PiglinAi.wantsToPickup(this, stack); ++ return (world.purpurConfig.piglinBypassMobGriefing ^ world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && this.canPickUpLoot() && PiglinAi.wantsToPickup(this, stack); // Purpur } protected boolean canReplaceCurrentItem(ItemStack stack) { diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java -index b9810a1f6ac91ae9631dd1ebc225f009d91b7845..d6cac5ed7916040104f2a79ed38eb8b453ea3db6 100644 +index e283b1296c1e831376bfe9491cbf02ed4b3fffe4..27a6de70530c2a1cbe2f77a7fb493038121710ea 100644 --- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java +++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java -@@ -606,11 +606,18 @@ public class PiglinAi { - ItemStack itemstack = (ItemStack) iterator.next(); +@@ -605,11 +605,18 @@ public class PiglinAi { + } - item = itemstack.getItem(); -- } while (!(item instanceof ArmorItem) || !((ArmorItem) item).getMaterial().is(ArmorMaterials.GOLD)); -+ } while (!(item instanceof ArmorItem) || !((ArmorItem) item).getMaterial().is(ArmorMaterials.GOLD) && (!entity.level().purpurConfig.piglinIgnoresArmorWithGoldTrim || !isWearingGoldTrim(item))); // Purpur + itemstack = (ItemStack) iterator.next(); +- } while (!itemstack.is(ItemTags.PIGLIN_SAFE_ARMOR)); ++ } while (!itemstack.is(ItemTags.PIGLIN_SAFE_ARMOR) && (!entity.level().purpurConfig.piglinIgnoresArmorWithGoldTrim || !isWearingGoldTrim(itemstack.getItem()))); // Purpur return true; } + // Purpur start + private static boolean isWearingGoldTrim(Item itemstack) { -+ net.minecraft.world.item.armortrim.ArmorTrim armorTrim = itemstack.components().get(net.minecraft.core.component.DataComponents.TRIM); -+ return armorTrim != null && armorTrim.material().is(net.minecraft.world.item.armortrim.TrimMaterials.GOLD); ++ net.minecraft.world.item.equipment.trim.ArmorTrim armorTrim = itemstack.components().get(net.minecraft.core.component.DataComponents.TRIM); ++ return armorTrim != null && armorTrim.material().is(net.minecraft.world.item.equipment.trim.TrimMaterials.GOLD); + } + // Purpur end + @@ -11984,10 +11931,10 @@ index b9810a1f6ac91ae9631dd1ebc225f009d91b7845..d6cac5ed7916040104f2a79ed38eb8b4 piglin.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET); piglin.getNavigation().stop(); diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java -index 072c28e309d1d18cb3e3e719aec23d77dd966b47..b44bbeba8ed0b86afc8118d4b88026b0226e30a4 100644 +index 0cab5d5aa80f9ca8c34f982f0b81044328ba2d8f..e5e88d4b1d2a0ff043e75cf081eef60e774d3c0f 100644 --- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java +++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinBrute.java -@@ -62,6 +62,39 @@ public class PiglinBrute extends AbstractPiglin { +@@ -63,6 +63,39 @@ public class PiglinBrute extends AbstractPiglin { this.xpReward = 20; } @@ -12025,21 +11972,21 @@ index 072c28e309d1d18cb3e3e719aec23d77dd966b47..b44bbeba8ed0b86afc8118d4b88026b0 + } + public static AttributeSupplier.Builder createAttributes() { - return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 50.0).add(Attributes.MOVEMENT_SPEED, 0.35F).add(Attributes.ATTACK_DAMAGE, 7.0); - } -@@ -106,6 +139,7 @@ public class PiglinBrute extends AbstractPiglin { + return Monster.createMonsterAttributes() + .add(Attributes.MAX_HEALTH, 50.0) +@@ -113,6 +146,7 @@ public class PiglinBrute extends AbstractPiglin { @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + if (getRider() == null || this.isControllable()) // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel)this.level(), this); + this.getBrain().tick(world, this); PiglinBruteAi.updateActivity(this); PiglinBruteAi.maybePlayActivitySound(this); diff --git a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java -index 37e682452ecc30646faf1ae8da47f91779619d42..f929b9e623eaea0e949a7af1828b9eb198fc66b8 100644 +index 64f3204b4b6ac0c57d0eb833a959f666f5259c6b..d0f744597de323f6169e15cabe9b3a80dbdbf5bb 100644 --- a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java +++ b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java -@@ -124,8 +124,32 @@ public class Warden extends Monster implements VibrationSystem { +@@ -125,8 +125,32 @@ public class Warden extends Monster implements VibrationSystem { this.setPathfindingMalus(PathType.LAVA, 8.0F); this.setPathfindingMalus(PathType.DAMAGE_FIRE, 0.0F); this.setPathfindingMalus(PathType.DANGER_FIRE, 0.0F); @@ -12072,7 +12019,7 @@ index 37e682452ecc30646faf1ae8da47f91779619d42..f929b9e623eaea0e949a7af1828b9eb1 @Override public Packet getAddEntityPacket(ServerEntity entityTrackerEntry) { return new ClientboundAddEntityPacket(this, entityTrackerEntry, this.hasPose(Pose.EMERGING) ? 1 : 0); -@@ -393,17 +417,14 @@ public class Warden extends Monster implements VibrationSystem { +@@ -392,17 +416,14 @@ public class Warden extends Monster implements VibrationSystem { @Contract("null->false") public boolean canTargetEntity(@Nullable Entity entity) { @@ -12094,7 +12041,7 @@ index 37e682452ecc30646faf1ae8da47f91779619d42..f929b9e623eaea0e949a7af1828b9eb1 public static void applyDarknessAround(ServerLevel world, Vec3 pos, @Nullable Entity entity, int range) { diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index d28ebcae036168dd65a5f3236d12ee416308c23f..1534f3953bae2cc6ef945aacdf332fceac8940e2 100644 +index 5f656fc726a1dc5f42657095a2f2b7cf85b92d7c..6c74cf1dea99b3b967b8c3d76f405f823c881fb9 100644 --- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java @@ -48,6 +48,7 @@ import org.bukkit.event.entity.VillagerAcquireTradeEvent; @@ -12106,7 +12053,7 @@ index d28ebcae036168dd65a5f3236d12ee416308c23f..1534f3953bae2cc6ef945aacdf332fce // CraftBukkit start @Override diff --git a/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java b/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java -index e0e5046c84941a8d17e18c177f3daea9cb631940..d503d7a5837dbeb98e58dbe8f7e5de45f6d88990 100644 +index b0236c7bf9441aa84d3795ffed05dd6099f29636..796dcc0dcf9022b455b8847e045266b8802da0cf 100644 --- a/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java +++ b/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java @@ -27,7 +27,7 @@ public class CatSpawner implements CustomSpawner { @@ -12147,10 +12094,10 @@ index e0e5046c84941a8d17e18c177f3daea9cb631940..d503d7a5837dbeb98e58dbe8f7e5de45 } diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739fbba881a 100644 +index 99f1c604a2e67043cbc53092a50d84b745640069..4767cd3a59155f643d95211c71c19810e6569d85 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -143,6 +143,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -141,6 +141,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler }, MemoryModuleType.MEETING_POINT, (entityvillager, holder) -> { return holder.is(PoiTypes.MEETING); }); @@ -12159,13 +12106,10 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 public long nextGolemPanic = -1; // Pufferfish -@@ -157,6 +159,92 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - this.getNavigation().setCanFloat(true); - this.setCanPickUpLoot(true); +@@ -158,6 +160,93 @@ public class Villager extends AbstractVillager implements ReputationEventHandler this.setVillagerData(this.getVillagerData().setType(type).setProfession(VillagerProfession.NONE)); -+ if (level().purpurConfig.villagerFollowEmeraldBlock) this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.TemptGoal(this, 1.0D, TEMPT_ITEMS, false)); -+ } -+ + } + + // Purpur start + @Override + public boolean isRidable() { @@ -12185,6 +12129,7 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); ++ if (level().purpurConfig.villagerFollowEmeraldBlock) this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.TemptGoal(this, 1.0D, TEMPT_ITEMS, false)); + } + + @Override @@ -12197,6 +12142,7 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 + public void initAttributes() { + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.villagerMaxHealth); + this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.villagerScale); ++ this.getAttribute(Attributes.TEMPT_RANGE).setBaseValue(this.level().purpurConfig.villagerTemptRange); // Purpur + } + + @Override @@ -12249,10 +12195,12 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 + net.minecraft.world.level.block.Block top = level().getBlockState(pos.above()).getBlock(); + // only if both blocks have no collision + return !bottom.hasCollision && !top.hasCollision; - } - ++ } ++ @Override -@@ -193,7 +281,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + public Brain getBrain() { + return (Brain) super.getBrain(); // CraftBukkit - decompile error +@@ -192,7 +281,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler brain.addActivity(Activity.PLAY, VillagerGoalPackages.getPlayPackage(0.5F)); } else { brain.setSchedule(Schedule.VILLAGER_DEFAULT); @@ -12261,13 +12209,22 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 } brain.addActivity(Activity.CORE, VillagerGoalPackages.getCorePackage(villagerprofession, 0.5F)); -@@ -256,12 +344,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - // Paper start - this.customServerAiStep(false); +@@ -219,7 +308,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } -- protected void customServerAiStep(final boolean inactive) { -+ protected void customServerAiStep(boolean inactive) { // Purpur - not final - // Paper end + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.5D); ++ return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.5D).add(Attributes.TEMPT_RANGE, 10.0D); // Purpur - add TEMPT_RANGE + } + + public boolean assignProfessionWhenSpawned() { +@@ -253,10 +342,18 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + // Paper start - EAR 2 + this.customServerAiStep(world, false); + } +- protected void customServerAiStep(ServerLevel world, final boolean inactive) { ++ protected void customServerAiStep(ServerLevel world, boolean inactive) { // Purpur - not final + // Paper end - EAR 2 + // Purpur start + if (this.level().purpurConfig.villagerLobotomizeEnabled) { + // treat as inactive if lobotomized @@ -12278,23 +12235,20 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 + // Purpur end // Pufferfish start - if (!inactive && this.behaviorTick++ % this.activatedPriority == 0) { -+ if (!inactive && (getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) { // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel) this.level(), this); // Paper ++ if (!inactive && (getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) { // Purpur + this.getBrain().tick(world, this); // Paper } -+ else if (this.isLobotomized && shouldRestock()) restock(); // Purpur // Pufferfish end - if (this.assignProfessionWhenSpawned) { - this.assignProfessionWhenSpawned = false; -@@ -318,7 +415,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -315,7 +412,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler if (!itemstack.is(Items.VILLAGER_SPAWN_EGG) && this.isAlive() && !this.isTrading() && !this.isSleeping()) { if (this.isBaby()) { this.setUnhappy(); -- return InteractionResult.sidedSuccess(this.level().isClientSide); -+ return tryRide(player, hand, InteractionResult.sidedSuccess(this.level().isClientSide)); // Purpur +- return InteractionResult.SUCCESS; ++ return tryRide(player, hand, InteractionResult.SUCCESS); // Purpur } else { if (!this.level().isClientSide) { boolean flag = this.getOffers().isEmpty(); -@@ -332,9 +429,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -329,9 +426,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } if (flag) { @@ -12307,7 +12261,7 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 this.startTrading(player); } -@@ -504,7 +603,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -496,7 +595,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler while (iterator.hasNext()) { MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); @@ -12316,7 +12270,7 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 } } -@@ -746,7 +845,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -729,7 +828,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @Override public boolean canBreed() { @@ -12325,7 +12279,7 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 } private boolean hungry() { -@@ -960,6 +1059,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -931,6 +1030,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler public boolean hasFarmSeeds() { return this.getInventory().hasAnyMatching((itemstack) -> { @@ -12337,7 +12291,7 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 return itemstack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS); }); } -@@ -1017,6 +1121,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -988,6 +1092,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } public void spawnGolemIfNeeded(ServerLevel world, long time, int requiredCount) { @@ -12345,7 +12299,7 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 if (this.wantsToSpawnGolem(time)) { AABB axisalignedbb = this.getBoundingBox().inflate(10.0D, 10.0D, 10.0D); List list = world.getEntitiesOfClass(Villager.class, axisalignedbb); -@@ -1081,6 +1186,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -1052,6 +1157,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @Override public void startSleeping(BlockPos pos) { @@ -12359,7 +12313,7 @@ index e1fd6ad56c0fbaf59c9d9ac985ab5301d768f9ba..92e81a7092e594d1fbe2b239af363739 this.brain.setMemory(MemoryModuleType.LAST_SLEPT, this.level().getGameTime()); // CraftBukkit - decompile error this.brain.eraseMemory(MemoryModuleType.WALK_TARGET); diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java b/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java -index fa84a4b23a52e60a61c2ee32c1ea449f6dbe0d2b..67ede6b9d6ff2953f155f50c0e92c517ee02c65f 100644 +index 35c4638f5c46310c75b27548223fcaf5f8702113..4f3ce7ff387835b8a14eb36c90700fdb837a933c 100644 --- a/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java +++ b/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java @@ -31,7 +31,7 @@ public record VillagerProfession( @@ -12372,10 +12326,10 @@ index fa84a4b23a52e60a61c2ee32c1ea449f6dbe0d2b..67ede6b9d6ff2953f155f50c0e92c517 "farmer", PoiTypes.FARMER, diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -index 0af34e0f9c9696fbcb11b12fb27472ef17ad532a..360514d5afcafcf6dd83335938bfa09bb02e41d0 100644 +index 1e77cce428d9e53142aaa2cf780b7f862d536eca..42c91e52060fad4a7a598f9e9ef88fd0e0ff8475 100644 --- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -71,6 +71,43 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -72,6 +72,50 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set. } @@ -12404,8 +12358,15 @@ index 0af34e0f9c9696fbcb11b12fb27472ef17ad532a..360514d5afcafcf6dd83335938bfa09b + @Override + public void initAttributes() { + this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.wanderingTraderMaxHealth); ++ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.TEMPT_RANGE).setBaseValue(this.level().purpurConfig.wanderingTraderTemptRange); // Purpur + } + ++ // Purpur start ++ public static net.minecraft.world.entity.ai.attributes.AttributeSupplier.Builder createAttributes() { ++ return Mob.createMobAttributes().add(net.minecraft.world.entity.ai.attributes.Attributes.TEMPT_RANGE, 10.0D); ++ } ++ // Purpur end ++ + @Override + public boolean isSensitiveToWater() { + return this.level().purpurConfig.wanderingTraderTakeDamageFromWater; @@ -12419,7 +12380,7 @@ index 0af34e0f9c9696fbcb11b12fb27472ef17ad532a..360514d5afcafcf6dd83335938bfa09b @Override protected void registerGoals() { this.goalSelector.addGoal(0, new FloatGoal(this)); -@@ -78,7 +115,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -79,7 +123,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill return this.canDrinkPotion && this.level().isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API })); this.goalSelector.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { @@ -12428,7 +12389,7 @@ index 0af34e0f9c9696fbcb11b12fb27472ef17ad532a..360514d5afcafcf6dd83335938bfa09b })); this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this)); this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.class, 8.0F, 0.5D, 0.5D)); -@@ -91,6 +128,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -92,6 +136,7 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill this.goalSelector.addGoal(1, new PanicGoal(this, 0.5D)); this.goalSelector.addGoal(1, new LookAtTradingPlayerGoal(this)); this.goalSelector.addGoal(2, new WanderingTrader.WanderToPositionGoal(this, 2.0D, 0.35D)); @@ -12436,7 +12397,7 @@ index 0af34e0f9c9696fbcb11b12fb27472ef17ad532a..360514d5afcafcf6dd83335938bfa09b this.goalSelector.addGoal(4, new MoveTowardsRestrictionGoal(this, 0.35D)); this.goalSelector.addGoal(8, new WaterAvoidingRandomStrollGoal(this, 0.35D)); this.goalSelector.addGoal(9, new InteractGoal(this, Player.class, 3.0F, 1.0F)); -@@ -119,11 +157,13 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -120,11 +165,13 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill if (!this.level().isClientSide) { if (this.getOffers().isEmpty()) { @@ -12453,9 +12414,9 @@ index 0af34e0f9c9696fbcb11b12fb27472ef17ad532a..360514d5afcafcf6dd83335938bfa09b + } // Purpur } - return InteractionResult.sidedSuccess(this.level().isClientSide); + return InteractionResult.SUCCESS; diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -index c72b6ea5530e54fc373c701028e1c147cea34b59..96e9fce5f9084737d2fcf4deb83305733b480179 100644 +index a728dcbf956f108f01c966c7531449a506a14a87..4c1378132201c1e5d1bc01f8c0cbba91629bcffa 100644 --- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java @@ -160,7 +160,17 @@ public class WanderingTraderSpawner implements CustomSpawner { @@ -12478,7 +12439,7 @@ index c72b6ea5530e54fc373c701028e1c147cea34b59..96e9fce5f9084737d2fcf4deb8330573 if (spawnplacementtype.isSpawnPositionOk(world, blockposition2, EntityType.WANDERING_TRADER)) { blockposition1 = blockposition2; diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 65b0c70d729efec87fdc137b49fcf8774889703f..865c83af67fee690e4d3a62c7c145c308e619ed1 100644 +index 7187652d038a5ea7b3555f5ad6f3671263947375..3dc166fd669cecded3d40ef8722bed400f611d03 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java @@ -198,11 +198,21 @@ public abstract class Player extends LivingEntity { @@ -12536,24 +12497,25 @@ index 65b0c70d729efec87fdc137b49fcf8774889703f..865c83af67fee690e4d3a62c7c145c30 this.noPhysics = this.isSpectator(); if (this.isSpectator()) { this.setOnGround(false); -@@ -374,6 +403,16 @@ public abstract class Player extends LivingEntity { - this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TURTLE_HELMET); // CraftBukkit +@@ -340,6 +369,17 @@ public abstract class Player extends LivingEntity { + this.turtleHelmetTick(); } + // Purpur start + if (this.level().purpurConfig.playerNetheriteFireResistanceDuration > 0 && this.level().getGameTime() % 20 == 0) { -+ if (itemstack.is(Items.NETHERITE_HELMET) -+ && this.getItemBySlot(EquipmentSlot.CHEST).is(Items.NETHERITE_CHESTPLATE) -+ && this.getItemBySlot(EquipmentSlot.LEGS).is(Items.NETHERITE_LEGGINGS) -+ && this.getItemBySlot(EquipmentSlot.FEET).is(Items.NETHERITE_BOOTS)) { ++ if (this.getItemBySlot(EquipmentSlot.HEAD).is(Items.NETHERITE_HELMET) ++ && this.getItemBySlot(EquipmentSlot.CHEST).is(Items.NETHERITE_CHESTPLATE) ++ && this.getItemBySlot(EquipmentSlot.LEGS).is(Items.NETHERITE_LEGGINGS) ++ && this.getItemBySlot(EquipmentSlot.FEET).is(Items.NETHERITE_BOOTS)) { + this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, this.level().purpurConfig.playerNetheriteFireResistanceDuration, this.level().purpurConfig.playerNetheriteFireResistanceAmplifier, this.level().purpurConfig.playerNetheriteFireResistanceAmbient, this.level().purpurConfig.playerNetheriteFireResistanceShowParticles, this.level().purpurConfig.playerNetheriteFireResistanceShowIcon), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.NETHERITE_ARMOR); + } + } + // Purpur end - } - - protected ItemCooldowns createItemCooldowns() { -@@ -606,7 +645,7 @@ public abstract class Player extends LivingEntity { ++ + this.cooldowns.tick(); + this.updatePlayerPose(); + if (this.currentImpulseContextResetGraceTime > 0) { +@@ -630,7 +670,7 @@ public abstract class Player extends LivingEntity { while (iterator.hasNext()) { Entity entity = (Entity) iterator.next(); @@ -12562,7 +12524,7 @@ index 65b0c70d729efec87fdc137b49fcf8774889703f..865c83af67fee690e4d3a62c7c145c30 list1.add(entity); } else if (!entity.isRemoved()) { this.touch(entity); -@@ -1325,7 +1364,7 @@ public abstract class Player extends LivingEntity { +@@ -1282,7 +1322,7 @@ public abstract class Player extends LivingEntity { flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper - Toggleable player crits if (flag2) { damagesource = damagesource.critical(true); // Paper start - critical damage API @@ -12571,30 +12533,41 @@ index 65b0c70d729efec87fdc137b49fcf8774889703f..865c83af67fee690e4d3a62c7c145c30 } float f3 = f + f1; -@@ -1968,9 +2007,19 @@ public abstract class Player extends LivingEntity { +@@ -1648,7 +1688,7 @@ public abstract class Player extends LivingEntity { + } + @Override - protected int getBaseExperienceReward() { - if (!this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && !this.isSpectator()) { -- int i = this.experienceLevel * 7; -- -- return i > 100 ? 100 : i; -+ // Purpur start +- protected boolean canGlide() { ++ public boolean canGlide() { // Purpur + return !this.abilities.flying && super.canGlide(); + } + +@@ -1908,7 +1948,23 @@ public abstract class Player extends LivingEntity { + + @Override + protected int getBaseExperienceReward(ServerLevel world) { +- return !world.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && !this.isSpectator() ? Math.min(this.experienceLevel * 7, 100) : 0; ++ // Purpur start ++ if (!world.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && !this.isSpectator()) { + int toDrop; + try { + toDrop = Math.round(((Number) scriptEngine.eval("let expLevel = " + experienceLevel + "; " + -+ "let expTotal = " + totalExperience + "; " + -+ "let exp = " + experienceProgress + "; " + -+ level().purpurConfig.playerDeathExpDropEquation)).floatValue()); ++ "let expTotal = " + totalExperience + "; " + ++ "let exp = " + experienceProgress + "; " + ++ level().purpurConfig.playerDeathExpDropEquation)).floatValue()); + } catch (javax.script.ScriptException e) { + e.printStackTrace(); + toDrop = experienceLevel * 7; + } + return Math.min(toDrop, level().purpurConfig.playerDeathExpDropMax); -+ // Purpur end - } else { - return 0; - } -@@ -2051,6 +2100,13 @@ public abstract class Player extends LivingEntity { ++ } else { ++ return 0; ++ } ++ // Purpur end + } + + @Override +@@ -1986,6 +2042,13 @@ public abstract class Player extends LivingEntity { return slot != EquipmentSlot.BODY; } @@ -12608,17 +12581,8 @@ index 65b0c70d729efec87fdc137b49fcf8774889703f..865c83af67fee690e4d3a62c7c145c30 public boolean setEntityOnShoulder(CompoundTag entityNbt) { if (!this.isPassenger() && this.onGround() && !this.isInWater() && !this.isInPowderSnow) { if (this.getShoulderEntityLeft().isEmpty()) { -@@ -2348,7 +2404,7 @@ public abstract class Player extends LivingEntity { - public ItemStack eat(Level world, ItemStack stack, FoodProperties foodComponent) { - this.getFoodData().eat(stack, foodComponent); // CraftBukkit - this.awardStat(Stats.ITEM_USED.get(stack.getItem())); -- world.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); -+ // world.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); // Purpur - moved to tick() - if (this instanceof ServerPlayer) { - CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) this, stack); - } diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -index 6b652424786841f147f1c55617defd0e2a994b5f..95ba3fb31899125c6378c2d5e3789c41f9466f2b 100644 +index 6e313a45356ed2b043ef626c7ca191b294acaf70..5a6dc4366f8fb9f5d5df44c29597a1e174d95569 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java @@ -80,6 +80,7 @@ public abstract class AbstractArrow extends Projectile { @@ -12629,7 +12593,7 @@ index 6b652424786841f147f1c55617defd0e2a994b5f..95ba3fb31899125c6378c2d5e3789c41 // Spigot Start @Override -@@ -589,6 +590,12 @@ public abstract class AbstractArrow extends Projectile { +@@ -623,6 +624,12 @@ public abstract class AbstractArrow extends Projectile { return this.firedFromWeapon; } @@ -12643,35 +12607,36 @@ index 6b652424786841f147f1c55617defd0e2a994b5f..95ba3fb31899125c6378c2d5e3789c41 return SoundEvents.ARROW_HIT; } diff --git a/src/main/java/net/minecraft/world/entity/projectile/LargeFireball.java b/src/main/java/net/minecraft/world/entity/projectile/LargeFireball.java -index 28a65f2a9ef441ae96a7a635e0695b14ce2ee367..7b6c58a31d37896daccb5f570d3cb9247cea2cd6 100644 +index 2f00676f62478897ae4931ea06e047567c407535..55ea7f82fac9a3de6d7e0725a9b6ea08088bc85c 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/LargeFireball.java +++ b/src/main/java/net/minecraft/world/entity/projectile/LargeFireball.java -@@ -23,20 +23,20 @@ public class LargeFireball extends Fireball { +@@ -23,13 +23,13 @@ public class LargeFireball extends Fireball { public LargeFireball(EntityType type, Level world) { super(type, world); -- this.isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit -+ this.isIncendiary = this.level().purpurConfig.fireballsBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit // Purpur +- this.isIncendiary = (world instanceof ServerLevel worldserver) && worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit ++ this.isIncendiary = (world instanceof ServerLevel worldserver) && (worldserver.purpurConfig.fireballsBypassMobGriefing ^ worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)); // CraftBukkit // Purpur } public LargeFireball(Level world, LivingEntity owner, Vec3 velocity, int explosionPower) { super(EntityType.FIREBALL, owner, velocity, world); this.explosionPower = explosionPower; -- this.isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit -+ this.isIncendiary = this.level().purpurConfig.fireballsBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit // Purpur +- this.isIncendiary = (world instanceof ServerLevel worldserver) && worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // CraftBukkit ++ this.isIncendiary = (world instanceof ServerLevel worldserver) && (worldserver.purpurConfig.fireballsBypassMobGriefing ^ worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)); // CraftBukkit // Purpur } @Override - protected void onHit(HitResult hitResult) { - super.onHit(hitResult); - if (!this.level().isClientSide) { -- boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); -+ boolean flag = this.level().purpurConfig.fireballsBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Purpur +@@ -38,7 +38,7 @@ public class LargeFireball extends Fireball { + Level world = this.level(); + + if (world instanceof ServerLevel worldserver) { +- boolean flag = worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ boolean flag = worldserver.purpurConfig.fireballsBypassMobGriefing ^ worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Purpur // CraftBukkit start - fire ExplosionPrimeEvent ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity()); diff --git a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java -index 8575941fd238750c5d56843989a48bcbde2d8a88..b4ed2df8d0795409808df0205edce6da682c3981 100644 +index 958ea103cc80da7366cc33dc385b76d4f5c809f2..0b7f27a6cc6be58fa5b60002059c9fbb3b1b7b67 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java +++ b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java @@ -33,6 +33,12 @@ public class LlamaSpit extends Projectile { @@ -12688,33 +12653,33 @@ index 8575941fd238750c5d56843989a48bcbde2d8a88..b4ed2df8d0795409808df0205edce6da protected double getDefaultGravity() { return 0.06D; diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index 6f9590135dbad0d616781a87a403bd83ebfa9f78..0f143ed6b3448c8d40eb79dfe19b3d9e4e68d853 100644 +index 507a7f2116b020a5af4b8fff15b73dba9904874f..a7fe724fd2aec7a72781e7b3ab74ff317cec8fbf 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -403,7 +403,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { - public boolean mayInteract(Level world, BlockPos pos) { +@@ -519,7 +519,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { + public boolean mayInteract(ServerLevel world, BlockPos pos) { Entity entity = this.getOwner(); - return entity instanceof Player ? entity.mayInteract(world, pos) : entity == null || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); -+ return entity instanceof Player ? entity.mayInteract(world, pos) : entity == null || world.purpurConfig.projectilesBypassMobGriefing || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ return entity instanceof Player ? entity.mayInteract(world, pos) : entity == null || world.purpurConfig.projectilesBypassMobGriefing ^ world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); } - public boolean mayBreak(Level world) { + public boolean mayBreak(ServerLevel world) { diff --git a/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java b/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java -index 1711ad457e7d1233fd32edc3e9e3b9f1e3be9980..554d3c4db6ed07e3d12af23a9a18c28480bf77c0 100644 +index bb159ea4baf208aab6d6fcfbbddacd5b089b55c8..588b07ec4501924a49264183b414a7fd64bb6550 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java +++ b/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java @@ -30,7 +30,7 @@ public class SmallFireball extends Fireball { super(EntityType.SMALL_FIREBALL, owner, velocity, world); // CraftBukkit start if (this.getOwner() != null && this.getOwner() instanceof Mob) { -- this.isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); -+ this.isIncendiary = this.level().purpurConfig.fireballsBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Purpur +- this.isIncendiary = (world instanceof ServerLevel worldserver) && worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ this.isIncendiary = (world instanceof ServerLevel worldserver) && (worldserver.purpurConfig.fireballsBypassMobGriefing ^ worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)); // Purpur } // CraftBukkit end } diff --git a/src/main/java/net/minecraft/world/entity/projectile/Snowball.java b/src/main/java/net/minecraft/world/entity/projectile/Snowball.java -index 2b4d206c0d31ba38d7b2af654bd420e85145d441..1b9d0e28e518c501b4b93ae385ddd64aeade97d5 100644 +index 70961e151666a0ecf5b791853f4581eaebbdcc8b..0db58e7d63a5c1b43a2224c247979f23a1d3f899 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Snowball.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Snowball.java @@ -58,11 +58,41 @@ public class Snowball extends ThrowableItemProjectile { @@ -12761,33 +12726,33 @@ index 2b4d206c0d31ba38d7b2af654bd420e85145d441..1b9d0e28e518c501b4b93ae385ddd64a protected void onHit(HitResult hitResult) { super.onHit(hitResult); diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -index 1aa5e57a4e6a4be60514d8808a2e6c973d93e798..334fa781e94d195c13dd78cdbe8f43b4b126ebd0 100644 +index bd2684528157f928460f2143dd71a48e11983123..0720df603b4f89dd6aa346091b13033ad5d62907 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -@@ -77,10 +77,11 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { +@@ -152,10 +152,11 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { return; } // CraftBukkit end - if (this.random.nextFloat() < 0.05F && worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { -+ if (this.random.nextFloat() < this.level().purpurConfig.enderPearlEndermiteChance && worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { // Purpur - Endermite entityendermite = (Endermite) EntityType.ENDERMITE.create(worldserver); ++ if (this.random.nextFloat() < worldserver.purpurConfig.enderPearlEndermiteChance && worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { // Purpur + Endermite entityendermite = (Endermite) EntityType.ENDERMITE.create(worldserver, EntitySpawnReason.TRIGGERED); if (entityendermite != null) { + entityendermite.setPlayerSpawned(true); // Purpur entityendermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot()); worldserver.addFreshEntity(entityendermite, CreatureSpawnEvent.SpawnReason.ENDER_PEARL); } -@@ -89,7 +90,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { - // entity.changeDimension(new DimensionTransition(worldserver, this.position(), entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), DimensionTransition.DO_NOTHING)); // CraftBukkit - moved up - entity.resetFallDistance(); - entityplayer.resetCurrentImpulseContext(); -- entity.hurt(this.damageSources().fall().customEventDamager(this), 5.0F); // CraftBukkit // Paper - fix DamageSource API -+ entity.hurt(this.damageSources().fall().customEventDamager(this), this.level().purpurConfig.enderPearlDamage); // CraftBukkit // Paper - fix DamageSource API // Purpur - this.playSound(worldserver, this.position()); - } - } else { +@@ -170,7 +171,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { + if (entityplayer1 != null) { + entityplayer1.resetFallDistance(); + entityplayer1.resetCurrentImpulseContext(); +- entityplayer1.hurtServer(entityplayer.serverLevel(), this.damageSources().enderPearl().customEventDamager(this), 5.0F); // CraftBukkit // Paper - fix DamageSource API ++ entityplayer1.hurtServer(entityplayer.serverLevel(), this.damageSources().enderPearl().customEventDamager(this), this.level().purpurConfig.enderPearlDamage); // CraftBukkit // Paper - fix DamageSource API // Purpur + } + + this.playSound(worldserver, vec3d); diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java -index 44c733c5b2c3e9942f28e882ad72306a24459c2c..bebaa347ddcc9f54f888fa1bc20a77c6a64c90e3 100644 +index 322733266fdca8ce43434a8ffea304c51794bcbb..489c26423a7f5bc9da45d247de57ec989cc74119 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java @@ -69,7 +69,7 @@ public class ThrownTrident extends AbstractArrow { @@ -12797,10 +12762,10 @@ index 44c733c5b2c3e9942f28e882ad72306a24459c2c..bebaa347ddcc9f54f888fa1bc20a77c6 - if (b0 > 0 && (this.dealtDamage || this.isNoPhysics()) && entity != null) { + if (b0 > 0 && (this.dealtDamage || this.isNoPhysics() || (level().purpurConfig.tridentLoyaltyVoidReturnHeight < 0.0D && getY() < level().purpurConfig.tridentLoyaltyVoidReturnHeight)) && entity != null) { // Purpur if (!this.isAcceptibleReturnOwner()) { - if (!this.level().isClientSide && this.pickup == AbstractArrow.Pickup.ALLOWED) { - this.spawnAtLocation(this.getPickupItem(), 0.1F); + Level world = this.level(); + diff --git a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java -index 55fd997a4e894eeab24de269d59e486196ffbe8d..999453409c19abf7f5b5c2dc399699856e57329e 100644 +index 4c47b30867e30d84908abf93dbefc252bc8c3453..e63b408594b5d2673148e39c1deafc8510537bee 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java +++ b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java @@ -103,7 +103,7 @@ public class WitherSkull extends AbstractHurtingProjectile { @@ -12830,23 +12795,23 @@ index 55fd997a4e894eeab24de269d59e486196ffbe8d..999453409c19abf7f5b5c2dc39969985 + // Purpur end + @Override - public boolean hurt(DamageSource source, float amount) { - return false; + protected void defineSynchedData(SynchedEntityData.Builder builder) { + builder.define(WitherSkull.DATA_DANGEROUS, false); diff --git a/src/main/java/net/minecraft/world/entity/raid/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java -index bbf21ea433f9e3963aac0ede597ed8d3c8e50ed8..06487fc9ea416d8256e0c2cd1969d4e0283ffb05 100644 +index ab132041982df2a701e4baea8195873f31b4a5fb..722c1660cf6b93d0f9c05cafe587b1834c5c3a22 100644 --- a/src/main/java/net/minecraft/world/entity/raid/Raider.java +++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java -@@ -299,7 +299,7 @@ public abstract class Raider extends PatrollingMonster { - - @Override - public boolean canUse() { -- if (!this.mob.level().getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING) || !this.mob.canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items -+ if ((!this.mob.level().purpurConfig.pillagerBypassMobGriefing && !this.mob.level().getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING)) || !this.mob.canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items // Purpur - Raid raid = this.mob.getCurrentRaid(); +@@ -345,7 +345,7 @@ public abstract class Raider extends PatrollingMonster { + } - if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getLeaderBannerInstance(this.mob.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN)))) { + private boolean cannotPickUpBanner() { +- if (!getServerLevel(this.mob).getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING) || !this.mob.canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items ++ if ((!this.mob.level().purpurConfig.pillagerBypassMobGriefing == !getServerLevel(this.mob).getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING)) || !this.mob.canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items // Purpur + if (!this.mob.hasActiveRaid()) { + return true; + } else if (this.mob.getCurrentRaid().isOver()) { diff --git a/src/main/java/net/minecraft/world/entity/raid/Raids.java b/src/main/java/net/minecraft/world/entity/raid/Raids.java -index 8c60f71270d909c10e6617eb64b8fdb42deb73e9..eedce2a3d67d875d5174ee125e2679480d4d412c 100644 +index 439d61d8689fabe940006b9b317a6810175dccfb..6b30941a84054efb5fcccb5d9e6c80d713a23889 100644 --- a/src/main/java/net/minecraft/world/entity/raid/Raids.java +++ b/src/main/java/net/minecraft/world/entity/raid/Raids.java @@ -26,6 +26,7 @@ import net.minecraft.world.phys.Vec3; @@ -12889,41 +12854,80 @@ index 8c60f71270d909c10e6617eb64b8fdb42deb73e9..eedce2a3d67d875d5174ee125e267948 if (!raid.isStarted() && !this.raidMap.containsKey(raid.getId())) { this.raidMap.put(raid.getId(), raid); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractBoat.java +index 1fdbef16cd29c8fc74578ac3328f985eca61088d..56c265940208bc94f531a5af94f564b59f35ebf3 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractBoat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractBoat.java +@@ -499,6 +499,7 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { + + if (f > 0.0F) { + this.landFriction = f; ++ if (level().purpurConfig.boatEjectPlayersOnLand) ejectPassengers(); // Purpur + return AbstractBoat.Status.ON_LAND; + } else { + return AbstractBoat.Status.IN_AIR; +@@ -929,7 +930,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { + + @Override + public final ItemStack getPickResult() { +- return new ItemStack((ItemLike) this.dropItem.get()); ++ // Purpur start ++ final ItemStack boat = new ItemStack((ItemLike) this.dropItem.get()); ++ if (!this.level().purpurConfig.persistentDroppableEntityDisplayNames) { ++ boat.set(net.minecraft.core.component.DataComponents.CUSTOM_NAME, null); ++ } ++ return boat; ++ // Purpur end + } + + public static enum Status { diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index a38ce400550893f63640e3bb5bb801ab40f06266..8b1c00062a5272d1020bc85491d8627c4d5f46cb 100644 +index cdc8606ffe5c75ee19d92e9f86f26b2a502d765e..b31940441596079aae1cd2a38b9d22be18358448 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java -@@ -102,12 +102,14 @@ public abstract class AbstractMinecart extends VehicleEntity { +@@ -92,6 +92,10 @@ public abstract class AbstractMinecart extends VehicleEntity { private double flyingY = 0.95; private double flyingZ = 0.95; - public double maxSpeed = 0.4D; -+ public double storedMaxSpeed; // Purpur + public Double maxSpeed; ++ // Purpur start ++ public double storedMaxSpeed; ++ public boolean isNewBehavior; ++ // Purpur end // CraftBukkit end + public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API - protected AbstractMinecart(EntityType type, Level world) { - super(type, world); - this.targetDeltaMovement = Vec3.ZERO; +@@ -100,8 +104,13 @@ public abstract class AbstractMinecart extends VehicleEntity { this.blocksBuilding = true; -+ if (world != null) maxSpeed = storedMaxSpeed = world.purpurConfig.minecartMaxSpeed; // Purpur - } + if (AbstractMinecart.useExperimentalMovement(world)) { + this.behavior = new NewMinecartBehavior(this); ++ this.isNewBehavior = true; // Purpur + } else { + this.behavior = new OldMinecartBehavior(this); ++ // Purpur start ++ this.isNewBehavior = false; ++ maxSpeed = storedMaxSpeed = world.purpurConfig.minecartMaxSpeed; ++ // Purpur end + } - protected AbstractMinecart(EntityType type, Level world, double x, double y, double z) { -@@ -296,6 +298,12 @@ public abstract class AbstractMinecart extends VehicleEntity { + } +@@ -289,6 +298,14 @@ public abstract class AbstractMinecart extends VehicleEntity { @Override public void tick() { + // Purpur start -+ if (storedMaxSpeed != level().purpurConfig.minecartMaxSpeed) { -+ maxSpeed = storedMaxSpeed = level().purpurConfig.minecartMaxSpeed; ++ if (!this.isNewBehavior) { ++ if (storedMaxSpeed != level().purpurConfig.minecartMaxSpeed) { ++ maxSpeed = storedMaxSpeed = level().purpurConfig.minecartMaxSpeed; ++ } + } + // Purpur end + // CraftBukkit start double prevX = this.getX(); double prevY = this.getY(); -@@ -448,16 +456,62 @@ public abstract class AbstractMinecart extends VehicleEntity { - - public void activateMinecart(int x, int y, int z, boolean powered) {} +@@ -426,16 +443,62 @@ public abstract class AbstractMinecart extends VehicleEntity { + this.behavior.moveAlongTrack(world); + } + // Purpur start + private Double lastSpeed; @@ -12944,8 +12948,8 @@ index a38ce400550893f63640e3bb5bb801ab40f06266..8b1c00062a5272d1020bc85491d8627c + } + // Purpur end + - protected void comeOffTrack() { - double d0 = this.getMaxSpeed(); + protected void comeOffTrack(ServerLevel world) { + double d0 = this.getMaxSpeed(world); Vec3 vec3d = this.getDeltaMovement(); this.setDeltaMovement(Mth.clamp(vec3d.x, -d0, d0), vec3d.y, Mth.clamp(vec3d.z, -d0, d0)); @@ -12974,7 +12978,7 @@ index a38ce400550893f63640e3bb5bb801ab40f06266..8b1c00062a5272d1020bc85491d8627c + maxUpStep = 0.0F; + } + // Purpur end -+ ++ if (this.onGround()) { // CraftBukkit start - replace magic numbers with our variables this.setDeltaMovement(new Vec3(this.getDeltaMovement().x * this.derailedX, this.getDeltaMovement().y * this.derailedY, this.getDeltaMovement().z * this.derailedZ)); @@ -12984,71 +12988,74 @@ index a38ce400550893f63640e3bb5bb801ab40f06266..8b1c00062a5272d1020bc85491d8627c this.move(MoverType.SELF, this.getDeltaMovement()); if (!this.onGround()) { -@@ -629,7 +683,7 @@ public abstract class AbstractMinecart extends VehicleEntity { - if (d18 > 0.01D) { - double d20 = 0.06D; - -- this.setDeltaMovement(vec3d4.add(vec3d4.x / d18 * 0.06D, 0.0D, vec3d4.z / d18 * 0.06D)); -+ this.setDeltaMovement(vec3d4.add(vec3d4.x / d18 * this.level().purpurConfig.poweredRailBoostModifier, 0.0D, vec3d4.z / d18 * this.level().purpurConfig.poweredRailBoostModifier)); // Purpur +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/NewMinecartBehavior.java b/src/main/java/net/minecraft/world/entity/vehicle/NewMinecartBehavior.java +index f43439b31a14b9db4744512465d81134ebe5b3e1..0b9741dfebd0bb95e8c0e1f55ce18dfb353f693a 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/NewMinecartBehavior.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/NewMinecartBehavior.java +@@ -426,7 +426,7 @@ public class NewMinecartBehavior extends MinecartBehavior { + private Vec3 calculateBoostTrackSpeed(Vec3 velocity, BlockPos railPos, BlockState railState) { + if (railState.is(Blocks.POWERED_RAIL) && (Boolean) railState.getValue(PoweredRailBlock.POWERED)) { + if (velocity.length() > 0.01D) { +- return velocity.normalize().scale(velocity.length() + 0.06D); ++ return velocity.normalize().scale(velocity.length() + this.level().purpurConfig.poweredRailBoostModifier); // Purpur } else { - Vec3 vec3d5 = this.getDeltaMovement(); - double d21 = vec3d5.x; -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -index f1955afc8e367f80ead85bd5ad3b8d66c255565a..5f3d58099d83fef4a9230e680b5e199d00eb7c7b 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java -@@ -543,6 +543,7 @@ public class Boat extends VehicleEntity implements Leashable, VariantHolder 0.0F) { - this.landFriction = f; -+ if (level().purpurConfig.boatEjectPlayersOnLand) ejectPassengers(); // Purpur - return Boat.Status.ON_LAND; + Vec3 vec3d1 = this.minecart.getRedstoneDirection(railPos); + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/OldMinecartBehavior.java b/src/main/java/net/minecraft/world/entity/vehicle/OldMinecartBehavior.java +index 04a622f52353ebcc21f41c233f5a0fd67690cf4a..f10ce069ef427df16fd0ce0e60b85c805ca703f0 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/OldMinecartBehavior.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/OldMinecartBehavior.java +@@ -310,9 +310,9 @@ public class OldMinecartBehavior extends MinecartBehavior { + vec3d5 = this.getDeltaMovement(); + d17 = vec3d5.horizontalDistance(); + if (d17 > 0.01D) { +- double d19 = 0.06D; ++ double d19 = world.purpurConfig.poweredRailBoostModifier; // Purpur + +- this.setDeltaMovement(vec3d5.add(vec3d5.x / d17 * 0.06D, 0.0D, vec3d5.z / d17 * 0.06D)); ++ this.setDeltaMovement(vec3d5.add(vec3d5.x / d17 * world.purpurConfig.poweredRailBoostModifier, 0.0D, vec3d5.z / d17 * world.purpurConfig.poweredRailBoostModifier)); // Purpur } else { - return Boat.Status.IN_AIR; -@@ -1016,7 +1017,13 @@ public class Boat extends VehicleEntity implements Leashable, VariantHolder= this.starvationRate) { // CraftBukkit - add regen rate manipulation if (player.getHealth() > 10.0F || enumdifficulty == Difficulty.HARD || player.getHealth() > 1.0F && enumdifficulty == Difficulty.NORMAL) { -- player.hurt(player.damageSources().starve(), 1.0F); -+ player.hurt(player.damageSources().starve(), player.level().purpurConfig.hungerStarvationDamage); // Purpur +- player.hurtServer(worldserver, player.damageSources().starve(), 1.0F); ++ player.hurtServer(worldserver, player.damageSources().starve(), player.level().purpurConfig.hungerStarvationDamage); // Purpur } this.tickTimer = 0; +diff --git a/src/main/java/net/minecraft/world/food/FoodProperties.java b/src/main/java/net/minecraft/world/food/FoodProperties.java +index 882b72799ae532f4e181214d5756ec024af223e2..9a3f2a95debcf8b94f7deb375922ea09b30aabab 100644 +--- a/src/main/java/net/minecraft/world/food/FoodProperties.java ++++ b/src/main/java/net/minecraft/world/food/FoodProperties.java +@@ -33,7 +33,7 @@ public record FoodProperties(int nutrition, float saturation, boolean canAlwaysE + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), (SoundEvent) consumable.sound().value(), SoundSource.NEUTRAL, 1.0F, randomsource.triangle(1.0F, 0.4F)); + if (user instanceof Player entityhuman) { + entityhuman.getFoodData().eat(this, stack, (ServerPlayer) entityhuman); // CraftBukkit +- world.playSound((Player) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 0.5F, Mth.randomBetween(randomsource, 0.9F, 1.0F)); ++ //world.playSound((Player) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 0.5F, Mth.randomBetween(randomsource, 0.9F, 1.0F)); // Purpur - moved to Player#tick() + } + + } diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index dd4218e108f87f3305b76fbc8d88f488b447c609..ecfa807e78c16a24099d40becd0c7916f239aed1 100644 +index 4680f77a275d8d2b226018db89a571ac25998dd8..bfc90524bd739ed1d91fe9912e38093b3c28928f 100644 --- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -76,6 +76,7 @@ public abstract class AbstractContainerMenu { +@@ -80,6 +80,7 @@ public abstract class AbstractContainerMenu { @Nullable private ContainerSynchronizer synchronizer; private boolean suppressRemoteUpdates; @@ -13057,10 +13064,10 @@ index dd4218e108f87f3305b76fbc8d88f488b447c609..ecfa807e78c16a24099d40becd0c7916 // CraftBukkit start public boolean checkReachable = true; diff --git a/src/main/java/net/minecraft/world/inventory/AbstractFurnaceMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractFurnaceMenu.java -index 58a5338e73aedaa3744dced128ac3eb6f5f6f87e..f032a3e76e2af3ebd67d202066f3bcac8e52d29e 100644 +index 1240df9368855f836412b06cf564926a18bfe90d..e559eabed82d2f402908e5b80d1505076ccc53a2 100644 --- a/src/main/java/net/minecraft/world/inventory/AbstractFurnaceMenu.java +++ b/src/main/java/net/minecraft/world/inventory/AbstractFurnaceMenu.java -@@ -147,7 +147,13 @@ public abstract class AbstractFurnaceMenu extends RecipeBookMenu holder1 = (Holder) iterator1.next(); if (!holder1.equals(holder) && !Enchantment.areCompatible(holder, holder1)) { @@ -13182,7 +13189,7 @@ index 362278407679f245ebcea778f2199b357339e1fe..bd146be65c558dcd388359081e2625c4 i2 = enchantment.getMaxLevel(); } -@@ -262,6 +292,54 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -264,6 +294,54 @@ public class AnvilMenu extends ItemCombinerMenu { if (!this.itemName.equals(itemstack.getHoverName().getString())) { b0 = 1; i += b0; @@ -13237,8 +13244,8 @@ index 362278407679f245ebcea778f2199b357339e1fe..bd146be65c558dcd388359081e2625c4 itemstack1.set(DataComponents.CUSTOM_NAME, Component.literal(this.itemName)); } } else if (itemstack.has(DataComponents.CUSTOM_NAME)) { -@@ -281,6 +359,12 @@ public class AnvilMenu extends ItemCombinerMenu { - this.cost.set(this.maximumRepairCost - 1); // CraftBukkit +@@ -287,6 +365,12 @@ public class AnvilMenu extends ItemCombinerMenu { + this.onlyRenaming = true; } + // Purpur start - Anvil API @@ -13250,9 +13257,9 @@ index 362278407679f245ebcea778f2199b357339e1fe..bd146be65c558dcd388359081e2625c4 if (this.cost.get() >= this.maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit itemstack1 = ItemStack.EMPTY; } -@@ -302,6 +386,13 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -307,6 +391,13 @@ public class AnvilMenu extends ItemCombinerMenu { + org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), itemstack1); // CraftBukkit - this.sendAllDataToRemote(); // CraftBukkit - SPIGOT-6686: Always send completed inventory to stay in sync with client this.broadcastChanges(); + + // Purpur start - Anvil API @@ -13264,7 +13271,7 @@ index 362278407679f245ebcea778f2199b357339e1fe..bd146be65c558dcd388359081e2625c4 } else { org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareAnvilEvent(this.getBukkitView(), ItemStack.EMPTY); // CraftBukkit this.cost.set(AnvilMenu.DEFAULT_DENIED_COST); // CraftBukkit - use a variable for set a cost for denied item -@@ -309,7 +400,7 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -315,7 +406,7 @@ public class AnvilMenu extends ItemCombinerMenu { } public static int calculateIncreasedRepairCost(int cost) { @@ -13287,10 +13294,10 @@ index 6c0b6abb1698fac9bb902f695b725d4ab783ee90..091e3c3514fcb378b68098114106d09f } diff --git a/src/main/java/net/minecraft/world/inventory/ChestMenu.java b/src/main/java/net/minecraft/world/inventory/ChestMenu.java -index 0dbfd23bbfc6ad203f048142f8c90ef741849fe1..9a80427d2bb470b6b1638e59aba57216676dcbd2 100644 +index 48a6b6136ac3414ca735f93a14b1a8d76210603c..27321b07cd04814bc1ff720c65770d7755625bb6 100644 --- a/src/main/java/net/minecraft/world/inventory/ChestMenu.java +++ b/src/main/java/net/minecraft/world/inventory/ChestMenu.java -@@ -67,10 +67,30 @@ public class ChestMenu extends AbstractContainerMenu { +@@ -66,10 +66,30 @@ public class ChestMenu extends AbstractContainerMenu { return new ChestMenu(MenuType.GENERIC_9x6, syncId, playerInventory, 6); } @@ -13322,7 +13329,7 @@ index 0dbfd23bbfc6ad203f048142f8c90ef741849fe1..9a80427d2bb470b6b1638e59aba57216 return new ChestMenu(MenuType.GENERIC_9x6, syncId, playerInventory, inventory, 6); } diff --git a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java -index 9bc9b4218ffd966f43097c9e009b2926af58c810..e59a38d051179753fa9b29e8d746e25e162cac3e 100644 +index 50a735dd97daab4fb9579f922a4c63de60204f29..5b8ad051347f73553acb65c5ddc690d2b7eaa754 100644 --- a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java +++ b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java @@ -42,6 +42,12 @@ import org.bukkit.event.enchantment.PrepareItemEnchantEvent; @@ -13361,10 +13368,10 @@ index 9bc9b4218ffd966f43097c9e009b2926af58c810..e59a38d051179753fa9b29e8d746e25e }; this.random = RandomSource.create(); this.enchantmentSeed = DataSlot.standalone(); -@@ -101,6 +123,17 @@ public class EnchantmentMenu extends AbstractContainerMenu { +@@ -100,6 +122,16 @@ public class EnchantmentMenu extends AbstractContainerMenu { + return Pair.of(InventoryMenu.BLOCK_ATLAS, EnchantmentMenu.EMPTY_SLOT_LAPIS_LAZULI); } }); - + // Purpur start + access.execute((level, pos) -> { + if (level.purpurConfig.enchantmentTableLapisPersists) { @@ -13375,11 +13382,10 @@ index 9bc9b4218ffd966f43097c9e009b2926af58c810..e59a38d051179753fa9b29e8d746e25e + } + }); + // Purpur end -+ - int j; - - for (j = 0; j < 3; ++j) { -@@ -341,6 +374,7 @@ public class EnchantmentMenu extends AbstractContainerMenu { + this.addStandardInventorySlots(playerInventory, 8, 84); + this.addDataSlot(DataSlot.shared(this.costs, 0)); + this.addDataSlot(DataSlot.shared(this.costs, 1)); +@@ -329,6 +361,7 @@ public class EnchantmentMenu extends AbstractContainerMenu { public void removed(net.minecraft.world.entity.player.Player player) { super.removed(player); this.access.execute((world, blockposition) -> { @@ -13388,7 +13394,7 @@ index 9bc9b4218ffd966f43097c9e009b2926af58c810..e59a38d051179753fa9b29e8d746e25e }); } diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java -index 138f77d13dda574def523d74fa55bc71b5bfa01b..3ba9ff1b10f8d1a105eb821a9cc0603fe28b7387 100644 +index 5687f492fc76f699e2a388790ca5380d9b8c8d0a..111da7435f0abb5a57bd2c5fecead2380ac4347a 100644 --- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java @@ -96,12 +96,14 @@ public class GrindstoneMenu extends AbstractContainerMenu { @@ -13416,7 +13422,7 @@ index 138f77d13dda574def523d74fa55bc71b5bfa01b..3ba9ff1b10f8d1a105eb821a9cc0603f j += ((Enchantment) holder.value()).getMinCost(k); } } -@@ -234,7 +236,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { +@@ -222,7 +224,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { Entry> entry = (Entry) iterator.next(); Holder holder = (Holder) entry.getKey(); @@ -13425,7 +13431,7 @@ index 138f77d13dda574def523d74fa55bc71b5bfa01b..3ba9ff1b10f8d1a105eb821a9cc0603f itemenchantments_a.upgrade(holder, entry.getIntValue()); } } -@@ -242,10 +244,70 @@ public class GrindstoneMenu extends AbstractContainerMenu { +@@ -230,10 +232,70 @@ public class GrindstoneMenu extends AbstractContainerMenu { }); } @@ -13497,7 +13503,7 @@ index 138f77d13dda574def523d74fa55bc71b5bfa01b..3ba9ff1b10f8d1a105eb821a9cc0603f }); }); -@@ -260,6 +322,23 @@ public class GrindstoneMenu extends AbstractContainerMenu { +@@ -248,6 +310,23 @@ public class GrindstoneMenu extends AbstractContainerMenu { } item.set(DataComponents.REPAIR_COST, i); @@ -13521,7 +13527,7 @@ index 138f77d13dda574def523d74fa55bc71b5bfa01b..3ba9ff1b10f8d1a105eb821a9cc0603f return item; } -@@ -321,7 +400,9 @@ public class GrindstoneMenu extends AbstractContainerMenu { +@@ -309,7 +388,9 @@ public class GrindstoneMenu extends AbstractContainerMenu { return ItemStack.EMPTY; } @@ -13532,10 +13538,10 @@ index 138f77d13dda574def523d74fa55bc71b5bfa01b..3ba9ff1b10f8d1a105eb821a9cc0603f return itemstack; diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java -index 7de5e47f9a54263734eeef855a2dc07ef64d30ea..b3bd9bbd96efc4784b86c2be6bb857da4db919b8 100644 +index a5d53a656513ae81cc3f9fc506caf6adaba62a8e..ac9df238ef0f3d009f25976b95e0b750e963e952 100644 --- a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java +++ b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java -@@ -178,7 +178,9 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { +@@ -164,7 +164,9 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { return ItemStack.EMPTY; } @@ -13569,21 +13575,8 @@ index a15d5ff872dbd77f3c3145e0328f3d02e431ff8c..1dcf36d502990d32fc4cd3ea69c3ea33 public void setActiveChest(EnderChestBlockEntity blockEntity) { this.activeChest = blockEntity; } -diff --git a/src/main/java/net/minecraft/world/item/ArmorItem.java b/src/main/java/net/minecraft/world/item/ArmorItem.java -index 647a4601deace52f8d855f512a73671f82b4762a..d05b1e129eee07434d162e1b949fd5633418ef66 100644 ---- a/src/main/java/net/minecraft/world/item/ArmorItem.java -+++ b/src/main/java/net/minecraft/world/item/ArmorItem.java -@@ -60,7 +60,7 @@ public class ArmorItem extends Item implements Equipable { - return false; - } else { - LivingEntity entityliving = (LivingEntity) list.get(0); -- EquipmentSlot enumitemslot = entityliving.getEquipmentSlotForItem(armor); -+ EquipmentSlot enumitemslot = pointer.level().purpurConfig.dispenserApplyCursedArmor ? entityliving.getEquipmentSlotForItem(armor) : entityliving.getEquipmentSlotForDispenserItem(armor); if (enumitemslot == null) return false; // Purpur - Dispenser curse of binding protection - ItemStack itemstack1 = armor.copyWithCount(1); // Paper - shrink below and single item in event - // CraftBukkit start - Level world = pointer.level(); diff --git a/src/main/java/net/minecraft/world/item/ArmorStandItem.java b/src/main/java/net/minecraft/world/item/ArmorStandItem.java -index 066a6e5ed2632a55324ec0d10f2f8a6bf3f30a0f..1921ecf2c0a9f18c93d207692fb9c2db58c9358f 100644 +index cb4baebe22eeab17aed67a5ecc506b932fe2230b..c1a6734cc08de1c9fc413b1fa81a199ac9547ec2 100644 --- a/src/main/java/net/minecraft/world/item/ArmorStandItem.java +++ b/src/main/java/net/minecraft/world/item/ArmorStandItem.java @@ -59,6 +59,14 @@ public class ArmorStandItem extends Item { @@ -13602,10 +13595,10 @@ index 066a6e5ed2632a55324ec0d10f2f8a6bf3f30a0f..1921ecf2c0a9f18c93d207692fb9c2db world.playSound((Player) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F); entityarmorstand.gameEvent(GameEvent.ENTITY_PLACE, context.getPlayer()); diff --git a/src/main/java/net/minecraft/world/item/AxeItem.java b/src/main/java/net/minecraft/world/item/AxeItem.java -index f005ea92449cf5e249ff64f4791c3bc6b8635528..ade1a0dac14bb3adc26bb103fc0ce9629fe973c6 100644 +index abff08f2d61014944235ffe2f5494a718a28cc10..dc2c415ab227e1357533079ada4903e9f69d4f55 100644 --- a/src/main/java/net/minecraft/world/item/AxeItem.java +++ b/src/main/java/net/minecraft/world/item/AxeItem.java -@@ -60,13 +60,15 @@ public class AxeItem extends DiggerItem { +@@ -62,13 +62,15 @@ public class AxeItem extends DiggerItem { if (playerHasShieldUseIntent(context)) { return InteractionResult.PASS; } else { @@ -13623,7 +13616,7 @@ index f005ea92449cf5e249ff64f4791c3bc6b8635528..ade1a0dac14bb3adc26bb103fc0ce962 return InteractionResult.PASS; } // Paper end -@@ -74,13 +76,20 @@ public class AxeItem extends DiggerItem { +@@ -76,8 +78,15 @@ public class AxeItem extends DiggerItem { CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger((ServerPlayer)player, blockPos, itemStack); } @@ -13641,13 +13634,7 @@ index f005ea92449cf5e249ff64f4791c3bc6b8635528..ade1a0dac14bb3adc26bb103fc0ce962 if (player != null) { itemStack.hurtAndBreak(1, player, LivingEntity.getSlotForHand(context.getHand())); } - -- return InteractionResult.sidedSuccess(level.isClientSide); -+ return InteractionResult.SUCCESS; // Purpur - force arm swing - } - } - } -@@ -90,22 +99,24 @@ public class AxeItem extends DiggerItem { +@@ -92,22 +101,24 @@ public class AxeItem extends DiggerItem { return context.getHand().equals(InteractionHand.MAIN_HAND) && player.getOffhandItem().is(Items.SHIELD) && !player.isSecondaryUseActive(); } @@ -13681,10 +13668,10 @@ index f005ea92449cf5e249ff64f4791c3bc6b8635528..ade1a0dac14bb3adc26bb103fc0ce962 return optional3; } else { diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java -index 96fb69ec6db2e7c8c728435f0c537b076259b2fb..26c8846c9255eacdf134e494aa7084b57b240b3c 100644 +index c816c935ecc74a811ffdffbe6ded73c06e92324a..d58619d1d63a03598b8740dd789d4b6f2c93f8d0 100644 --- a/src/main/java/net/minecraft/world/item/BlockItem.java +++ b/src/main/java/net/minecraft/world/item/BlockItem.java -@@ -157,7 +157,16 @@ public class BlockItem extends Item { +@@ -151,7 +151,16 @@ public class BlockItem extends Item { } protected boolean updateCustomBlockEntityTag(BlockPos pos, Level world, @Nullable Player player, ItemStack stack, BlockState state) { @@ -13702,7 +13689,7 @@ index 96fb69ec6db2e7c8c728435f0c537b076259b2fb..26c8846c9255eacdf134e494aa7084b5 } @Nullable -@@ -219,6 +228,7 @@ public class BlockItem extends Item { +@@ -213,6 +222,7 @@ public class BlockItem extends Item { if (tileentity != null) { if (!world.isClientSide && tileentity.onlyOpCanSetNbt() && (player == null || !(player.canUseGameMasterBlocks() || (player.getAbilities().instabuild && player.getBukkitEntity().hasPermission("minecraft.nbt.place"))))) { // Spigot - add permission @@ -13710,7 +13697,7 @@ index 96fb69ec6db2e7c8c728435f0c537b076259b2fb..26c8846c9255eacdf134e494aa7084b5 return false; } -@@ -259,6 +269,7 @@ public class BlockItem extends Item { +@@ -248,6 +258,7 @@ public class BlockItem extends Item { ItemContainerContents itemcontainercontents = (ItemContainerContents) entity.getItem().set(DataComponents.CONTAINER, ItemContainerContents.EMPTY); if (itemcontainercontents != null) { @@ -13719,38 +13706,39 @@ index 96fb69ec6db2e7c8c728435f0c537b076259b2fb..26c8846c9255eacdf134e494aa7084b5 } diff --git a/src/main/java/net/minecraft/world/item/BoatItem.java b/src/main/java/net/minecraft/world/item/BoatItem.java -index eb74d45ad458b80cf8455297c3bc550186adaea3..ef01856c487e4ab982996e01537618233592ac32 100644 +index e51ffd6c5047ee907a58f3029f0ea7fc66aedfa7..78d41d57df9cb61b295f1f54db1e1d62c13db701 100644 --- a/src/main/java/net/minecraft/world/item/BoatItem.java +++ b/src/main/java/net/minecraft/world/item/BoatItem.java -@@ -72,6 +72,11 @@ public class BoatItem extends Item { - - entityboat.setVariant(this.type); - entityboat.setYRot(user.getYRot()); -+ // Purpur start -+ if (!world.purpurConfig.persistentDroppableEntityDisplayNames) { -+ entityboat.setCustomName(null); -+ } -+ // Purpur end - if (!world.noCollision(entityboat, entityboat.getBoundingBox())) { - return InteractionResultHolder.fail(itemstack); +@@ -71,6 +71,11 @@ public class BoatItem extends Item { + return InteractionResult.FAIL; } else { + abstractboat.setYRot(user.getYRot()); ++ // Purpur start ++ if (!world.purpurConfig.persistentDroppableEntityDisplayNames) { ++ abstractboat.setCustomName(null); ++ } ++ // Purpur end + if (!world.noCollision(abstractboat, abstractboat.getBoundingBox())) { + return InteractionResult.FAIL; + } else { diff --git a/src/main/java/net/minecraft/world/item/BowItem.java b/src/main/java/net/minecraft/world/item/BowItem.java -index 6eb5c0f23d9dc61e69ad5ad493c89602a9dcd4b5..fc534b1f214663eb8e4fe479fed12b1dd069105c 100644 +index bb593209c95c9cf1f9c5d52d52fab4a33ddbabcf..58fa528e4b2589d362eb976afd6221cd94f2623c 100644 --- a/src/main/java/net/minecraft/world/item/BowItem.java +++ b/src/main/java/net/minecraft/world/item/BowItem.java -@@ -26,13 +26,18 @@ public class BowItem extends ProjectileWeaponItem { - public void releaseUsing(ItemStack stack, Level world, LivingEntity user, int remainingUseTicks) { - if (user instanceof Player player) { +@@ -28,6 +28,11 @@ public class BowItem extends ProjectileWeaponItem { + return false; + } else { ItemStack itemStack = player.getProjectile(stack); + // Purpur start + if (world.purpurConfig.infinityWorksWithoutArrows && itemStack.isEmpty() && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.INFINITY, stack) > 0) { + itemStack = new ItemStack(Items.ARROW); + } + // Purpur end - if (!itemStack.isEmpty()) { - int i = this.getUseDuration(stack, user) - remainingUseTicks; - float f = getPowerForTime(i); - if (!((double)f < 0.1)) { + if (itemStack.isEmpty()) { + return false; + } else { +@@ -38,7 +43,7 @@ public class BowItem extends ProjectileWeaponItem { + } else { List list = draw(stack, itemStack, player); if (world instanceof ServerLevel serverLevel && !list.isEmpty()) { - this.shoot(serverLevel, player, player.getUsedItemHand(), stack, list, f * 3.0F, 1.0F, f == 1.0F, null); @@ -13758,17 +13746,17 @@ index 6eb5c0f23d9dc61e69ad5ad493c89602a9dcd4b5..fc534b1f214663eb8e4fe479fed12b1d } world.playSound( -@@ -82,7 +87,7 @@ public class BowItem extends ProjectileWeaponItem { - public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { +@@ -89,7 +94,7 @@ public class BowItem extends ProjectileWeaponItem { + public InteractionResult use(Level world, Player user, InteractionHand hand) { ItemStack itemStack = user.getItemInHand(hand); boolean bl = !user.getProjectile(itemStack).isEmpty(); - if (!user.hasInfiniteMaterials() && !bl) { + if (!user.hasInfiniteMaterials() && !bl && !(world.purpurConfig.infinityWorksWithoutArrows && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.INFINITY, itemStack) > 0)) { // Purpur - return InteractionResultHolder.fail(itemStack); + return InteractionResult.FAIL; } else { user.startUsingItem(hand); diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java -index 321188173918d0d60858a258400dfd682ccdb21c..af47074f3a61a8518697d7851e43d5436fec5d57 100644 +index 3bddfb6f7412ab86e0c090d0cbc6cf254b3f891c..6aa8ee091d3a7d2826d08ab9a03f970ef71a81ea 100644 --- a/src/main/java/net/minecraft/world/item/BucketItem.java +++ b/src/main/java/net/minecraft/world/item/BucketItem.java @@ -196,7 +196,7 @@ public class BucketItem extends Item implements DispensibleContainerItem { @@ -13790,7 +13778,7 @@ index 321188173918d0d60858a258400dfd682ccdb21c..af47074f3a61a8518697d7851e43d543 return true; diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java -index 1467e6f2df302e0b7992dcb6c136cb626ade3d2b..4e60c2102e3e838c68e4b9db41c8bca365d22923 100644 +index 52c40eafc77e50a6fd21b9a7a250cea501f11690..86204c2ab5bbd5d45ddb1d626f844d91ccae6b4f 100644 --- a/src/main/java/net/minecraft/world/item/CrossbowItem.java +++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java @@ -69,7 +69,7 @@ public class CrossbowItem extends ProjectileWeaponItem { @@ -13799,11 +13787,11 @@ index 1467e6f2df302e0b7992dcb6c136cb626ade3d2b..4e60c2102e3e838c68e4b9db41c8bca3 if (chargedProjectiles != null && !chargedProjectiles.isEmpty()) { - this.performShooting(world, user, hand, itemStack, getShootingPower(chargedProjectiles), 1.0F, null); + this.performShooting(world, user, hand, itemStack, getShootingPower(chargedProjectiles), (float) world.purpurConfig.crossbowProjectileOffset, null); // Purpur - return InteractionResultHolder.consume(itemStack); + return InteractionResult.CONSUME; } else if (!user.getProjectile(itemStack).isEmpty()) { this.startSoundPlayed = false; diff --git a/src/main/java/net/minecraft/world/item/DyeColor.java b/src/main/java/net/minecraft/world/item/DyeColor.java -index 0d04a0107bd1a8a2b9aeb4be55025cd554e8fb79..a050d76233e179a1456b83ccc02bb9a55d1cec84 100644 +index 79dc7cf5bfe92b4df21d164f39726dfe618331e4..6721432f9cdd11c9658c34f0ac407be217f9d276 100644 --- a/src/main/java/net/minecraft/world/item/DyeColor.java +++ b/src/main/java/net/minecraft/world/item/DyeColor.java @@ -103,4 +103,10 @@ public enum DyeColor implements StringRepresentable { @@ -13818,20 +13806,20 @@ index 0d04a0107bd1a8a2b9aeb4be55025cd554e8fb79..a050d76233e179a1456b83ccc02bb9a5 + // Purpur end } diff --git a/src/main/java/net/minecraft/world/item/EggItem.java b/src/main/java/net/minecraft/world/item/EggItem.java -index 4ebd634cff286b10868e26eeb3ecf34abdcab22e..7dc811335caa46870d1d895899a1e6c21980382d 100644 +index 3ddd34e5d05fa1355a2affd329d72dea216cd0e4..770bdb3fb2426083ff6785f1c38ffe9d11f898e5 100644 --- a/src/main/java/net/minecraft/world/item/EggItem.java +++ b/src/main/java/net/minecraft/world/item/EggItem.java @@ -27,7 +27,7 @@ public class EggItem extends Item implements ProjectileItem { - ThrownEgg entityegg = new ThrownEgg(world, user); - - entityegg.setItem(itemstack); -- entityegg.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F); -+ entityegg.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, (float) world.purpurConfig.eggProjectileOffset); // Purpur + if (world instanceof ServerLevel worldserver) { + // CraftBukkit start // Paper start - PlayerLaunchProjectileEvent - com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); - if (event.callEvent() && world.addFreshEntity(entityegg)) { +- final Projectile.Delayed thrownEgg = Projectile.spawnProjectileFromRotationDelayed(ThrownEgg::new, worldserver, itemstack, user, 0.0F, 1.5F, 1.0F); ++ final Projectile.Delayed thrownEgg = Projectile.spawnProjectileFromRotationDelayed(ThrownEgg::new, worldserver, itemstack, user, 0.0F, 1.5F, (float) worldserver.purpurConfig.eggProjectileOffset); // Purpur + com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) thrownEgg.projectile().getBukkitEntity()); + if (event.callEvent() && thrownEgg.attemptSpawn()) { + if (event.shouldConsume()) { diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java -index 50312825fade96ccc8c1231ca1eaf6c36d892746..ba33679991bed0c53adf17f173675380bdf1f755 100644 +index 9f92b9addaedb4bae06b32226a74c8e5ddc6c2a2..0a05fedc9108fa5cf5a5d9e3395bcbbd735fc87d 100644 --- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java +++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java @@ -27,7 +27,7 @@ public class EndCrystalItem extends Item { @@ -13844,51 +13832,54 @@ index 50312825fade96ccc8c1231ca1eaf6c36d892746..ba33679991bed0c53adf17f173675380 } else { BlockPos blockposition1 = blockposition.above(); final BlockPos aboveBlockPosition = blockposition1; // Paper - OBFHELPER diff --git a/src/main/java/net/minecraft/world/item/EnderpearlItem.java b/src/main/java/net/minecraft/world/item/EnderpearlItem.java -index 20a91d798d31a71b3c05efa2cc5bda55494e26cc..11b04455f09d8bfdf44499bb8359dc715c2daffd 100644 +index b232390d8ee8e449e61c0ea7f3af60df507abb97..4039d300debadf29e6c544e8b4c950b7121a02d1 100644 --- a/src/main/java/net/minecraft/world/item/EnderpearlItem.java +++ b/src/main/java/net/minecraft/world/item/EnderpearlItem.java @@ -24,7 +24,7 @@ public class EnderpearlItem extends Item { - ThrownEnderpearl entityenderpearl = new ThrownEnderpearl(world, user); - - entityenderpearl.setItem(itemstack); -- entityenderpearl.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F); -+ entityenderpearl.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, (float) world.purpurConfig.enderPearlProjectileOffset); // Purpur + if (world instanceof ServerLevel worldserver) { + // CraftBukkit start // Paper start - PlayerLaunchProjectileEvent - com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); - if (event.callEvent() && world.addFreshEntity(entityenderpearl)) { -@@ -36,7 +36,7 @@ public class EnderpearlItem extends Item { - - world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); +- final Projectile.Delayed thrownEnderpearl = Projectile.spawnProjectileFromRotationDelayed(ThrownEnderpearl::new, worldserver, itemstack, user, 0.0F, 1.5F, 1.0F); ++ final Projectile.Delayed thrownEnderpearl = Projectile.spawnProjectileFromRotationDelayed(ThrownEnderpearl::new, worldserver, itemstack, user, 0.0F, 1.5F, (float) worldserver.purpurConfig.enderPearlProjectileOffset); // Purpur + com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) thrownEnderpearl.projectile().getBukkitEntity()); + if (event.callEvent() && thrownEnderpearl.attemptSpawn()) { + if (event.shouldConsume()) { +@@ -35,6 +35,7 @@ public class EnderpearlItem extends Item { + + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); user.awardStat(Stats.ITEM_USED.get(this)); -- user.getCooldowns().addCooldown(this, 20); -+ user.getCooldowns().addCooldown(this, user.getAbilities().instabuild ? world.purpurConfig.enderPearlCooldownCreative : world.purpurConfig.enderPearlCooldown); // Purpur ++ user.getCooldowns().addCooldown(itemstack, user.getAbilities().instabuild ? world.purpurConfig.enderPearlCooldownCreative : world.purpurConfig.enderPearlCooldown); // Purpur } else { - // Paper end - PlayerLaunchProjectileEvent + // Paper end - PlayerLaunchProjectileEvent if (user instanceof net.minecraft.server.level.ServerPlayer) { diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -index 218f2f085309f04438f8b07bc41cf242583db2dc..ea8e49b42b9dde74784189430be66ed6978015dd 100644 +index 29a048a9b09166838616ac7ba1d31625d56b0bca..184e6d9bf393188fc1f1c7acd545b4ac6d31f6a4 100644 --- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java -@@ -65,6 +65,14 @@ public class FireworkRocketItem extends Item implements ProjectileItem { - com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Firework) fireworkRocketEntity.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand)); - if (event.callEvent() && world.addFreshEntity(fireworkRocketEntity)) { - user.awardStat(Stats.ITEM_USED.get(this)); +@@ -66,6 +66,18 @@ public class FireworkRocketItem extends Item implements ProjectileItem { + com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Firework) delayed.projectile().getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand)); + if (event.callEvent() && delayed.attemptSpawn()) { + user.awardStat(Stats.ITEM_USED.get(this)); // Moved up from below ++ + // Purpur start + if (world.purpurConfig.elytraDamagePerFireworkBoost > 0) { -+ ItemStack chestItem = user.getItemBySlot(net.minecraft.world.entity.EquipmentSlot.CHEST); -+ if (chestItem.getItem() == Items.ELYTRA) { -+ chestItem.hurtAndBreak(world.purpurConfig.elytraDamagePerFireworkBoost, user, net.minecraft.world.entity.EquipmentSlot.CHEST); ++ List list = net.minecraft.world.entity.EquipmentSlot.VALUES.stream().filter((enumitemslot) -> net.minecraft.world.entity.LivingEntity.canGlideUsing(user.getItemBySlot(enumitemslot), enumitemslot)).toList(); ++ net.minecraft.world.entity.EquipmentSlot enumitemslot = net.minecraft.Util.getRandom(list, user.random); ++ ++ ItemStack glideItem = user.getItemBySlot(enumitemslot); ++ if (user.canGlide()) { ++ glideItem.hurtAndBreak(world.purpurConfig.elytraDamagePerFireworkBoost, user, enumitemslot); + } + } + // Purpur end if (event.shouldConsume() && !user.hasInfiniteMaterials()) { - itemStack.shrink(1); + itemStack.shrink(1); // Moved up from below } else ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); diff --git a/src/main/java/net/minecraft/world/item/HangingEntityItem.java b/src/main/java/net/minecraft/world/item/HangingEntityItem.java -index d8a63ac5444eff8e3decb2f4addc2decb8a5d648..41cc9229108aa8e4f5655dfe590ff414a16b1444 100644 +index cdc17ad948d8ac5de62f14b1a561433d33211f32..44a7cee7df2927a923455e8cedaab59307b42506 100644 --- a/src/main/java/net/minecraft/world/item/HangingEntityItem.java +++ b/src/main/java/net/minecraft/world/item/HangingEntityItem.java -@@ -74,6 +74,11 @@ public class HangingEntityItem extends Item { +@@ -75,6 +75,11 @@ public class HangingEntityItem extends Item { if (!customdata.isEmpty()) { EntityType.updateCustomEntityTag(world, entityhuman, (Entity) object, customdata); @@ -13901,7 +13892,7 @@ index d8a63ac5444eff8e3decb2f4addc2decb8a5d648..41cc9229108aa8e4f5655dfe590ff414 if (((HangingEntity) object).survives()) { diff --git a/src/main/java/net/minecraft/world/item/HoeItem.java b/src/main/java/net/minecraft/world/item/HoeItem.java -index 06497b5141e611cc7a1b6030a7b9c54b5c4eda06..28df1b3230762e52b5458ac93a85c9a5d41eb6a6 100644 +index d2871bb4fd670ae4133d13f290b3256c9177d8e6..0936bdc945f73c7750c20a34276aead2921eeb61 100644 --- a/src/main/java/net/minecraft/world/item/HoeItem.java +++ b/src/main/java/net/minecraft/world/item/HoeItem.java @@ -46,15 +46,23 @@ public class HoeItem extends DiggerItem { @@ -13935,36 +13926,27 @@ index 06497b5141e611cc7a1b6030a7b9c54b5c4eda06..28df1b3230762e52b5458ac93a85c9a5 if (!level.isClientSide) { consumer.accept(context); if (player != null) { -@@ -62,7 +70,7 @@ public class HoeItem extends DiggerItem { - } - } - -- return InteractionResult.sidedSuccess(level.isClientSide); -+ return InteractionResult.SUCCESS; // Purpur - force arm swing - } else { - return InteractionResult.PASS; - } diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index d37c915a4173ef16f3cd26339825862950ce52dd..933b7519da5330ea8acd05c337201f52cab12c3c 100644 +index 9de79c7087d3ce55631f08191a9b7994567f1788..1029499ce8fb236a23beb9dae168b82039734e59 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -497,6 +497,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -503,6 +503,7 @@ public final class ItemStack implements DataComponentHolder { world.isBlockPlaceCancelled = true; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent - for (BlockState blockstate : blocks) { - blockstate.update(true, false); + for (BlockState blockstate : blocks) { + blockstate.update(true, false); + ((CraftBlock) blockstate.getBlock()).getNMS().getBlock().forgetPlacer(); // Purpur - } - world.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent - world.preventPoiUpdated = false; -@@ -529,6 +530,7 @@ public final class ItemStack implements DataComponentHolder { - if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically - block.onPlace(world, newblockposition, oldBlock, true, context); } + world.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent + world.preventPoiUpdated = false; +@@ -535,6 +536,7 @@ public final class ItemStack implements DataComponentHolder { + if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically + block.onPlace(world, newblockposition, oldBlock, true, context); + } + block.getBlock().forgetPlacer(); // Purpur - world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point - } -@@ -643,6 +645,26 @@ public final class ItemStack implements DataComponentHolder { + world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point + } +@@ -681,6 +683,26 @@ public final class ItemStack implements DataComponentHolder { return this.isDamageableItem() && this.getDamageValue() > 0; } @@ -13991,20 +13973,20 @@ index d37c915a4173ef16f3cd26339825862950ce52dd..933b7519da5330ea8acd05c337201f52 public int getDamageValue() { return Mth.clamp((Integer) this.getOrDefault(DataComponents.DAMAGE, 0), 0, this.getMaxDamage()); } -@@ -708,6 +730,12 @@ public final class ItemStack implements DataComponentHolder { - org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent(serverPlayer, this); // Paper - Add EntityDamageItemEvent - } - // CraftBukkit end -+ // Purpur start -+ if (item == Items.ELYTRA) { -+ setDamageValue(this.getMaxDamage() - 1); -+ return; -+ } -+ // Purpur end +@@ -761,6 +783,12 @@ public final class ItemStack implements DataComponentHolder { + org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent(serverPlayer, this); // Paper - Add EntityDamageItemEvent + } + // CraftBukkit end ++ // Purpur start ++ if (this.has(DataComponents.GLIDER)) { ++ setDamageValue(this.getMaxDamage() - 1); ++ return; ++ } ++ // Purpur end - this.shrink(1); - breakCallback.accept(item); -@@ -1229,6 +1257,12 @@ public final class ItemStack implements DataComponentHolder { + this.shrink(1); + breakCallback.accept(item); +@@ -1325,6 +1353,12 @@ public final class ItemStack implements DataComponentHolder { return !((ItemEnchantments) this.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY)).isEmpty(); } @@ -14018,32 +14000,32 @@ index d37c915a4173ef16f3cd26339825862950ce52dd..933b7519da5330ea8acd05c337201f52 return (ItemEnchantments) this.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY); } diff --git a/src/main/java/net/minecraft/world/item/Items.java b/src/main/java/net/minecraft/world/item/Items.java -index 07315232192f6e09910a028c4643d7f0544c62e3..6b2235281dca67a80cb651e9f8e9bf2556979276 100644 +index 5a70111cd39af50981cfd440c021340da1de5eab..580bd63fdbf9555f867362d3c1f39f41fd750089 100644 --- a/src/main/java/net/minecraft/world/item/Items.java +++ b/src/main/java/net/minecraft/world/item/Items.java -@@ -337,7 +337,7 @@ public class Items { +@@ -363,7 +363,7 @@ public class Items { public static final Item PURPUR_BLOCK = registerBlock(Blocks.PURPUR_BLOCK); public static final Item PURPUR_PILLAR = registerBlock(Blocks.PURPUR_PILLAR); public static final Item PURPUR_STAIRS = registerBlock(Blocks.PURPUR_STAIRS); - public static final Item SPAWNER = registerBlock(Blocks.SPAWNER); -+ public static final Item SPAWNER = registerBlock(new org.purpurmc.purpur.item.SpawnerItem(Blocks.SPAWNER, new Item.Properties().rarity(Rarity.EPIC))); // Purpur ++ public static final Item SPAWNER = registerBlock(Blocks.SPAWNER, org.purpurmc.purpur.item.SpawnerItem::new, new Item.Properties().rarity(Rarity.EPIC)); // Purpur + public static final Item CREAKING_HEART = registerBlock(Blocks.CREAKING_HEART); public static final Item CHEST = registerBlock(Blocks.CHEST, settings -> settings.component(DataComponents.CONTAINER, ItemContainerContents.EMPTY)); public static final Item CRAFTING_TABLE = registerBlock(Blocks.CRAFTING_TABLE); - public static final Item FARMLAND = registerBlock(Blocks.FARMLAND); -@@ -1919,7 +1919,7 @@ public class Items { - "sweet_berries", new ItemNameBlockItem(Blocks.SWEET_BERRY_BUSH, new Item.Properties().food(Foods.SWEET_BERRIES)) +@@ -2104,7 +2104,7 @@ public class Items { + "sweet_berries", createBlockItemWithCustomItemName(Blocks.SWEET_BERRY_BUSH), new Item.Properties().food(Foods.SWEET_BERRIES) ); public static final Item GLOW_BERRIES = registerItem( -- "glow_berries", new ItemNameBlockItem(Blocks.CAVE_VINES, new Item.Properties().food(Foods.GLOW_BERRIES)) -+ "glow_berries", new org.purpurmc.purpur.item.GlowBerryItem(Blocks.CAVE_VINES, new Item.Properties().food(Foods.GLOW_BERRIES)) // Purpur +- "glow_berries", createBlockItemWithCustomItemName(Blocks.CAVE_VINES), new Item.Properties().food(Foods.GLOW_BERRIES) ++ "glow_berries", settings -> new org.purpurmc.purpur.item.GlowBerryItem(Blocks.CAVE_VINES, settings.useItemDescriptionPrefix()), new Item.Properties().food(Foods.GLOW_BERRIES) // Purpur ); public static final Item CAMPFIRE = registerBlock(Blocks.CAMPFIRE, settings -> settings.component(DataComponents.CONTAINER, ItemContainerContents.EMPTY)); public static final Item SOUL_CAMPFIRE = registerBlock( diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java -index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..608390ed36710a419de1542b80340dd3fcc7299c 100644 +index 571f2540a1e9422025efe651167e26b44b437daa..c2f3c8b3d8eeb609b6d6067c4fb404aefbf94ec5 100644 --- a/src/main/java/net/minecraft/world/item/MapItem.java +++ b/src/main/java/net/minecraft/world/item/MapItem.java -@@ -195,6 +195,7 @@ public class MapItem extends ComplexItem { +@@ -194,6 +194,7 @@ public class MapItem extends Item { public static void renderBiomePreviewMap(ServerLevel world, ItemStack map) { MapItemSavedData mapItemSavedData = getSavedData(map, world); if (mapItemSavedData != null) { @@ -14051,46 +14033,32 @@ index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..608390ed36710a419de1542b80340dd3 if (world.dimension() == mapItemSavedData.dimension) { int i = 1 << mapItemSavedData.scale; int j = mapItemSavedData.centerX; -diff --git a/src/main/java/net/minecraft/world/item/MilkBucketItem.java b/src/main/java/net/minecraft/world/item/MilkBucketItem.java -index 43c9dea6b0db7f8d6070dedcb472883ab46d9eaf..15a1f9ffbf640bffadca97e28f72b6a5d43c65d7 100644 ---- a/src/main/java/net/minecraft/world/item/MilkBucketItem.java -+++ b/src/main/java/net/minecraft/world/item/MilkBucketItem.java -@@ -25,7 +25,9 @@ public class MilkBucketItem extends Item { - } - - if (!world.isClientSide) { -+ net.minecraft.world.effect.MobEffectInstance badOmen = user.getEffect(net.minecraft.world.effect.MobEffects.BAD_OMEN); // Purpur - user.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.MILK); // CraftBukkit -+ if (!world.purpurConfig.milkCuresBadOmen && badOmen != null) user.addEffect(badOmen); // Purpur - } - - if (user instanceof Player entityhuman) { diff --git a/src/main/java/net/minecraft/world/item/MinecartItem.java b/src/main/java/net/minecraft/world/item/MinecartItem.java -index d524fcc191cb95d6ec7f12ae7fceeb8077bb08fc..4b8cebb321eddc852b4ec7def7f51d781f67927b 100644 +index 7153d9ed12276a0f2d8b8a17c79734aa25ed1fa5..dc49ea6454e04ae8ec68af12c4bf2ff022540671 100644 --- a/src/main/java/net/minecraft/world/item/MinecartItem.java +++ b/src/main/java/net/minecraft/world/item/MinecartItem.java -@@ -120,8 +120,9 @@ public class MinecartItem extends Item { +@@ -35,8 +35,9 @@ public class MinecartItem extends Item { BlockState iblockdata = world.getBlockState(blockposition); if (!iblockdata.is(BlockTags.RAILS)) { - return InteractionResult.FAIL; - } else { -+ if (!world.purpurConfig.minecartPlaceAnywhere) return InteractionResult.FAIL; ++ if (!world.purpurConfig.minecartPlaceAnywhere) return InteractionResult.FAIL; // Purpur + if (iblockdata.isSolid()) blockposition = blockposition.relative(context.getClickedFace()); + } // else { // Purpur - place minecarts anywhere ItemStack itemstack = context.getItemInHand(); - - if (world instanceof ServerLevel) { -@@ -147,6 +148,6 @@ public class MinecartItem extends Item { - - itemstack.shrink(1); - return InteractionResult.sidedSuccess(world.isClientSide); + RailShape blockpropertytrackposition = iblockdata.getBlock() instanceof BaseRailBlock ? (RailShape) iblockdata.getValue(((BaseRailBlock) iblockdata.getBlock()).getShapeProperty()) : RailShape.NORTH_SOUTH; + double d0 = 0.0D; +@@ -80,6 +81,6 @@ public class MinecartItem extends Item { + itemstack.shrink(1); + return InteractionResult.SUCCESS; + } - } + // } // Purpur - place minecarts anywhere } } diff --git a/src/main/java/net/minecraft/world/item/NameTagItem.java b/src/main/java/net/minecraft/world/item/NameTagItem.java -index 774c982f28b4f127fc3f036c19dfb47fb9ae3264..d49b60e7e643498b49c03593dc0da2f8e4459902 100644 +index 000d1863bfba98b5132dfc6743362d687b2f54f3..20fece9908382f40b4082f7b1fb7d41914ae31be 100644 --- a/src/main/java/net/minecraft/world/item/NameTagItem.java +++ b/src/main/java/net/minecraft/world/item/NameTagItem.java @@ -23,6 +23,7 @@ public class NameTagItem extends Item { @@ -14102,10 +14070,10 @@ index 774c982f28b4f127fc3f036c19dfb47fb9ae3264..d49b60e7e643498b49c03593dc0da2f8 // Paper end - Add PlayerNameEntityEvent mob.setPersistenceRequired(); diff --git a/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java b/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java -index 32dd0b13a0819f597d8a93c6bc3a155781067544..9751eea2d8aa3a45da34f09377d2fc81fe9a90d8 100644 +index 78ba170a83f8c026bd110eae494c52577182ed61..c2ae50872cead7202246b9cce4db6e0a81e1cf5f 100644 --- a/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java +++ b/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java -@@ -110,6 +110,8 @@ public abstract class ProjectileWeaponItem extends Item { +@@ -105,6 +105,8 @@ public abstract class ProjectileWeaponItem extends Item { entityarrow.setCritArrow(true); } @@ -14115,7 +14083,7 @@ index 32dd0b13a0819f597d8a93c6bc3a155781067544..9751eea2d8aa3a45da34f09377d2fc81 } diff --git a/src/main/java/net/minecraft/world/item/ShovelItem.java b/src/main/java/net/minecraft/world/item/ShovelItem.java -index 24f6a158e4759aac3be8da4cf5e0d40bd295355b..6b7dbb570f8a698c87c6bce992d84d87b55176e6 100644 +index 55c18f182166f4905d623d6f5e909eefd5ed2483..d10c4705cc9e7faabd4a5619e1da107231bdb37e 100644 --- a/src/main/java/net/minecraft/world/item/ShovelItem.java +++ b/src/main/java/net/minecraft/world/item/ShovelItem.java @@ -47,9 +47,12 @@ public class ShovelItem extends DiggerItem { @@ -14134,33 +14102,24 @@ index 24f6a158e4759aac3be8da4cf5e0d40bd295355b..6b7dbb570f8a698c87c6bce992d84d87 } else if (blockState.getBlock() instanceof CampfireBlock && blockState.getValue(CampfireBlock.LIT)) { afterAction = () -> { // Paper if (!level.isClientSide()) { -@@ -76,7 +79,7 @@ public class ShovelItem extends DiggerItem { - } - } - -- return InteractionResult.sidedSuccess(level.isClientSide); -+ return InteractionResult.SUCCESS; // Purpur - force arm swing - } else { - return InteractionResult.PASS; - } diff --git a/src/main/java/net/minecraft/world/item/SnowballItem.java b/src/main/java/net/minecraft/world/item/SnowballItem.java -index 32b170551a2f5bdc88d29f4d03750bfe3974e71b..a41fb0dd26af367fc2470a7913a84d864bc505f7 100644 +index 57872ebef6beb8cdc03c9f8f19de94652ee19062..60a064c26de0566aaf9f8be886402e291c03ca3b 100644 --- a/src/main/java/net/minecraft/world/item/SnowballItem.java +++ b/src/main/java/net/minecraft/world/item/SnowballItem.java -@@ -28,7 +28,7 @@ public class SnowballItem extends Item implements ProjectileItem { - Snowball entitysnowball = new Snowball(world, user); - - entitysnowball.setItem(itemstack); -- entitysnowball.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F); -+ entitysnowball.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, (float) world.purpurConfig.snowballProjectileOffset); // Purpur +@@ -27,7 +27,7 @@ public class SnowballItem extends Item implements ProjectileItem { + // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + if (world instanceof ServerLevel worldserver) { // Paper start - PlayerLaunchProjectileEvent - com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); - if (event.callEvent() && world.addFreshEntity(entitysnowball)) { +- final Projectile.Delayed snowball = Projectile.spawnProjectileFromRotationDelayed(Snowball::new, worldserver, itemstack, user, 0.0F, 1.5F, 1.0F); ++ final Projectile.Delayed snowball = Projectile.spawnProjectileFromRotationDelayed(Snowball::new, worldserver, itemstack, user, 0.0F, 1.5F, (float) worldserver.purpurConfig.snowballProjectileOffset); // Purpur + com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) snowball.projectile().getBukkitEntity()); + if (event.callEvent() && snowball.attemptSpawn()) { + user.awardStat(Stats.ITEM_USED.get(this)); diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.java -index 9cea8da84f39bb3f687139ef213ccea358724dee..c513e3b414a1b87b1aa37bb5d51fc2dd0fae1c54 100644 +index 9956ed42df55daa6d97fd6e3ab5368dad91cfaf0..e0e746d6c78421b40777125ba49f0a04809f5415 100644 --- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java +++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java -@@ -74,6 +74,24 @@ public class SpawnEggItem extends Item { +@@ -73,6 +73,24 @@ public class SpawnEggItem extends Item { Spawner spawner = (Spawner) tileentity; entitytypes = this.getType(itemstack); @@ -14186,79 +14145,103 @@ index 9cea8da84f39bb3f687139ef213ccea358724dee..c513e3b414a1b87b1aa37bb5d51fc2dd world.sendBlockUpdated(blockposition, iblockdata, iblockdata, 3); world.gameEvent((Entity) context.getPlayer(), (Holder) GameEvent.BLOCK_CHANGE, blockposition); diff --git a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java -index 369955746f4b51f69fa01103e3771dd74fc6c8f0..e6edd3a0fa2578900cdbe8bd588219dc3fd3af5f 100644 +index fa9d2ae44fcdd06f8f33cd14ffca422b20a01451..ffbc71ca2a27800d7758e3db339bf06a39ef1f11 100644 --- a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java +++ b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java @@ -21,7 +21,7 @@ public class ThrowablePotionItem extends PotionItem implements ProjectileItem { - if (!world.isClientSide) { - ThrownPotion thrownPotion = new ThrownPotion(world, user); - thrownPotion.setItem(itemStack); -- thrownPotion.shootFromRotation(user, user.getXRot(), user.getYRot(), -20.0F, 0.5F, 1.0F); -+ thrownPotion.shootFromRotation(user, user.getXRot(), user.getYRot(), -20.0F, 0.5F, (float) world.purpurConfig.throwablePotionProjectileOffset); // Purpur + ItemStack itemStack = user.getItemInHand(hand); + if (world instanceof ServerLevel serverLevel) { // Paper start - PlayerLaunchProjectileEvent - com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) thrownPotion.getBukkitEntity()); - if (event.callEvent() && world.addFreshEntity(thrownPotion)) { +- final Projectile.Delayed thrownPotion = Projectile.spawnProjectileFromRotationDelayed(ThrownPotion::new, serverLevel, itemStack, user, -20.0F, 0.5F, 1.0F); ++ final Projectile.Delayed thrownPotion = Projectile.spawnProjectileFromRotationDelayed(ThrownPotion::new, serverLevel, itemStack, user, -20.0F, 0.5F, (float) serverLevel.purpurConfig.throwablePotionProjectileOffset); // Purpur + // Paper start - PlayerLaunchProjectileEvent + com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) thrownPotion.projectile().getBukkitEntity()); + if (event.callEvent() && thrownPotion.attemptSpawn()) { diff --git a/src/main/java/net/minecraft/world/item/TridentItem.java b/src/main/java/net/minecraft/world/item/TridentItem.java -index f1b2d388a1a40a1d909a2e726f32d6c15e1eb0eb..8cf0b69fee110af05b89afa8e3236575aa6850e2 100644 +index 8b9a93ef71164cce8a616735b71d96d37e83b1a8..23e04d0d68ffa0e07ab295e7121f8a4963f4914a 100644 --- a/src/main/java/net/minecraft/world/item/TridentItem.java +++ b/src/main/java/net/minecraft/world/item/TridentItem.java -@@ -81,11 +81,13 @@ public class TridentItem extends Item implements ProjectileItem { - if (f == 0.0F) { - ThrownTrident entitythrowntrident = new ThrownTrident(world, entityhuman, stack); - -- entitythrowntrident.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, 2.5F, 1.0F); -+ entitythrowntrident.shootFromRotation(entityhuman, entityhuman.getXRot(), entityhuman.getYRot(), 0.0F, 2.5F, (float) world.purpurConfig.tridentProjectileOffset); // Purpur - if (entityhuman.hasInfiniteMaterials()) { - entitythrowntrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY; - } - -+ entitythrowntrident.setActualEnchantments(stack.getEnchantments()); // Purpur - Add an option to fix MC-3304 projectile looting +@@ -88,7 +88,7 @@ public class TridentItem extends Item implements ProjectileItem { + // itemstack.hurtWithoutBreaking(1, entityhuman); // CraftBukkit - moved down + if (f == 0.0F) { + // Paper start - PlayerLaunchProjectileEvent +- Projectile.Delayed tridentDelayed = Projectile.spawnProjectileFromRotationDelayed(ThrownTrident::new, worldserver, stack, entityhuman, 0.0F, 2.5F, 1.0F); ++ Projectile.Delayed tridentDelayed = Projectile.spawnProjectileFromRotationDelayed(ThrownTrident::new, worldserver, stack, entityhuman, 0.0F, 2.5F, (float) worldserver.purpurConfig.tridentProjectileOffset); // Purpur + // Paper start - PlayerLaunchProjectileEvent + com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), (org.bukkit.entity.Projectile) tridentDelayed.projectile().getBukkitEntity()); + if (!event.callEvent() || !tridentDelayed.attemptSpawn()) { +@@ -100,6 +100,9 @@ public class TridentItem extends Item implements ProjectileItem { + return false; + } + ThrownTrident entitythrowntrident = tridentDelayed.projectile(); // Paper - PlayerLaunchProjectileEvent + - // CraftBukkit start - // Paper start - PlayerLaunchProjectileEvent - com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), (org.bukkit.entity.Projectile) entitythrowntrident.getBukkitEntity()); -@@ -127,6 +129,14 @@ public class TridentItem extends Item implements ProjectileItem { - f4 *= f / f6; - f5 *= f / f6; - org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerRiptideEvent(entityhuman, stack, f3, f4, f5); // CraftBukkit -+ -+ // Purpur start -+ ItemStack chestItem = entityhuman.getItemBySlot(EquipmentSlot.CHEST); -+ if (chestItem.getItem() == Items.ELYTRA && world.purpurConfig.elytraDamagePerTridentBoost > 0) { -+ chestItem.hurtAndBreak(world.purpurConfig.elytraDamagePerTridentBoost, entityhuman, EquipmentSlot.CHEST); ++ entitythrowntrident.setActualEnchantments(stack.getEnchantments()); // Purpur - Add an option to fix MC-3304 projectile looting ++ + if (event.shouldConsume()) stack.hurtWithoutBreaking(1, entityhuman); // Paper - PlayerLaunchProjectileEvent + entitythrowntrident.pickupItemStack = stack.copy(); // SPIGOT-4511 update since damage call moved + // CraftBukkit end +@@ -132,6 +135,18 @@ public class TridentItem extends Item implements ProjectileItem { + f4 *= f / f6; + f5 *= f / f6; + org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerRiptideEvent(entityhuman, stack, f3, f4, f5); // CraftBukkit ++ ++ // Purpur start ++ List list = EquipmentSlot.VALUES.stream().filter((enumitemslot) -> LivingEntity.canGlideUsing(entityhuman.getItemBySlot(enumitemslot), enumitemslot)).toList(); ++ if (!list.isEmpty()) { ++ EquipmentSlot enumitemslot = net.minecraft.Util.getRandom(list, entityhuman.random); ++ ItemStack glideItem = entityhuman.getItemBySlot(enumitemslot); ++ if (glideItem.has(net.minecraft.core.component.DataComponents.GLIDER) && world.purpurConfig.elytraDamagePerTridentBoost > 0) { ++ glideItem.hurtAndBreak(world.purpurConfig.elytraDamagePerTridentBoost, entityhuman, enumitemslot); + } -+ // Purpur end ++ } ++ // Purpur end + - entityhuman.push((double) f3, (double) f4, (double) f5); - entityhuman.startAutoSpinAttack(20, 8.0F, stack); - if (entityhuman.onGround()) { + entityhuman.push((double) f3, (double) f4, (double) f5); + entityhuman.startAutoSpinAttack(20, 8.0F, stack); + if (entityhuman.onGround()) { +diff --git a/src/main/java/net/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffect.java b/src/main/java/net/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffect.java +index 0651c2af040e3f248860cfb3c5effce91589380e..d884df481b4bbb978113a4ac7a1feac31cf2f951 100644 +--- a/src/main/java/net/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffect.java ++++ b/src/main/java/net/minecraft/world/item/consume_effects/ClearAllStatusEffectsConsumeEffect.java +@@ -24,6 +24,12 @@ public record ClearAllStatusEffectsConsumeEffect() implements ConsumeEffect { + @Override + // CraftBukkit start + public boolean apply(Level world, ItemStack itemstack, LivingEntity entityliving, EntityPotionEffectEvent.Cause cause) { ++ // Purpur start ++ net.minecraft.world.effect.MobEffectInstance badOmen = entityliving.getEffect(net.minecraft.world.effect.MobEffects.BAD_OMEN); ++ if (!world.purpurConfig.milkCuresBadOmen && itemstack.is(net.minecraft.world.item.Items.MILK_BUCKET) && badOmen != null) { ++ return entityliving.removeAllEffects(cause) && entityliving.addEffect(badOmen); ++ } ++ // Purpur end + return entityliving.removeAllEffects(cause); + // CraftBukkit end + } diff --git a/src/main/java/net/minecraft/world/item/crafting/Ingredient.java b/src/main/java/net/minecraft/world/item/crafting/Ingredient.java -index e314f36951e9ac15c57137e24fce8c410373130a..21dfb8e91c5427ac12133de2c05d923d87adf5ba 100644 +index 812f919a7a7e309c8513f44104f092496037608f..10730b307971915f52b3e41068a864b8ee1352b4 100644 --- a/src/main/java/net/minecraft/world/item/crafting/Ingredient.java +++ b/src/main/java/net/minecraft/world/item/crafting/Ingredient.java -@@ -41,6 +41,7 @@ public final class Ingredient implements Predicate { +@@ -45,6 +45,7 @@ public final class Ingredient implements Predicate { + // CraftBukkit start @Nullable - private IntList stackingIds; - public boolean exact; // CraftBukkit + private List itemStacks; + public Predicate predicate; // Purpur - public static final Codec CODEC = Ingredient.codec(true); - public static final Codec CODEC_NONEMPTY = Ingredient.codec(false); -@@ -72,6 +73,12 @@ public final class Ingredient implements Predicate { - } else if (this.isEmpty()) { - return itemstack.isEmpty(); - } else { -+ // Purpur start -+ if (predicate != null) { -+ return predicate.test(itemstack.asBukkitCopy()); -+ } -+ // Purpur end -+ - ItemStack[] aitemstack = this.getItems(); - int i = aitemstack.length; + public boolean isExact() { + return this.itemStacks != null; +@@ -100,6 +101,11 @@ public final class Ingredient implements Predicate { + + return false; + } ++ // Purpur start ++ if (predicate != null) { ++ return predicate.test(itemstack.asBukkitCopy()); ++ } ++ // Purpur end + // CraftBukkit end + List> list = this.items(); diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java -index 986d0151aeeb2ce0f752c424c526fb0cc6849308..332500cb937f4a3eecb14e8daac44b33a15f9115 100644 +index f99b87cf70df7eaac13d46f4e0234b1e6483d342..73241113e50dc8be89ef8850d49d95ec31fb194f 100644 --- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java @@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; @@ -14269,7 +14252,7 @@ index 986d0151aeeb2ce0f752c424c526fb0cc6849308..332500cb937f4a3eecb14e8daac44b33 import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Consumer; -@@ -559,4 +560,58 @@ public class EnchantmentHelper { +@@ -578,4 +579,58 @@ public class EnchantmentHelper { interface EnchantmentVisitor { void accept(Holder enchantment, int level); } @@ -14329,15 +14312,15 @@ index 986d0151aeeb2ce0f752c424c526fb0cc6849308..332500cb937f4a3eecb14e8daac44b33 + // Purpur end - Add option to mend the most damaged equipment first } diff --git a/src/main/java/net/minecraft/world/item/enchantment/ItemEnchantments.java b/src/main/java/net/minecraft/world/item/enchantment/ItemEnchantments.java -index 8ac485d82c2d2b32f4d54e02c18c2cb2c3df4fa4..9ebe6a5f31ceacd33d9c111966ad941b535b4e67 100644 +index cfc6a657cae92c68868a76c1b7b1febe2a16e9f4..a12c08da793139e39dc11c213c94796b83bd8240 100644 --- a/src/main/java/net/minecraft/world/item/enchantment/ItemEnchantments.java +++ b/src/main/java/net/minecraft/world/item/enchantment/ItemEnchantments.java @@ -35,7 +35,7 @@ public class ItemEnchantments implements TooltipProvider { private static final java.util.Comparator> ENCHANTMENT_ORDER = java.util.Comparator.comparing(Holder::getRegisteredName); public static final ItemEnchantments EMPTY = new ItemEnchantments(new Object2IntAVLTreeMap<>(ENCHANTMENT_ORDER), true); // Paper end -- private static final Codec LEVEL_CODEC = Codec.intRange(0, 255); -+ private static final Codec LEVEL_CODEC = Codec.intRange(0, (org.purpurmc.purpur.PurpurConfig.clampEnchantLevels ? 255 : 32767)); // Purpur +- private static final Codec LEVEL_CODEC = Codec.intRange(1, 255); ++ private static final Codec LEVEL_CODEC = Codec.intRange(1, (org.purpurmc.purpur.PurpurConfig.clampEnchantLevels ? 255 : 32767)); // Purpur private static final Codec>> LEVELS_CODEC = Codec.unboundedMap( Enchantment.CODEC, LEVEL_CODEC )// Paper start - sort enchantments @@ -14350,7 +14333,7 @@ index 8ac485d82c2d2b32f4d54e02c18c2cb2c3df4fa4..9ebe6a5f31ceacd33d9c111966ad941b throw new IllegalArgumentException("Enchantment " + entry.getKey() + " has invalid level " + i); } } -@@ -166,13 +166,13 @@ public class ItemEnchantments implements TooltipProvider { +@@ -164,13 +164,13 @@ public class ItemEnchantments implements TooltipProvider { if (level <= 0) { this.enchantments.removeInt(enchantment); } else { @@ -14385,7 +14368,7 @@ index 0efc8d997b34302c3e0a5d7ec73a11a940dbeefe..af157881d440b34cfe79fbc9b03cc9ef public ItemStack assemble() { diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java -index f57e1b78204dff661ad5d3ee93a88a00330af2dc..967af8771ff8564c715d89f4b4b69b16c25add59 100644 +index 7de66aa435dd36899b80f4ecc64480680e474d94..bb4411cfdf1bc7adc12c2f918d2eec830299f38b 100644 --- a/src/main/java/net/minecraft/world/level/BaseSpawner.java +++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java @@ -59,6 +59,7 @@ public abstract class BaseSpawner { @@ -14397,10 +14380,10 @@ index f57e1b78204dff661ad5d3ee93a88a00330af2dc..967af8771ff8564c715d89f4b4b69b16 } diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 141b748abe80402731cdaf14a3d36aa7cef4f4bd..d5d2a6467b48bcf8e5322dd5938f6e4fb37ca467 100644 +index 5d7a6e4b73f032db356e7ec369b150013e940ee6..6b2cda6d578a0983b2401ea20629275431018433 100644 --- a/src/main/java/net/minecraft/world/level/EntityGetter.java +++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -187,7 +187,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst +@@ -184,7 +184,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) { for (Player player : this.players()) { @@ -14409,52 +14392,8 @@ index 141b748abe80402731cdaf14a3d36aa7cef4f4bd..d5d2a6467b48bcf8e5322dd5938f6e4f double d = player.distanceToSqr(x, y, z); if (range < 0.0 || d < range * range) { return true; -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index df04f39d8e40eaab3a29ed33f253728d236c6957..72ec914d6653db200eb1dfadf28a27b608adc9f9 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -341,7 +341,7 @@ public class Explosion { - this.hitPlayers = Maps.newHashMap(); - this.level = world; - this.source = entity; -- this.radius = (float) Math.max(power, 0.0); // CraftBukkit - clamp bad values -+ this.radius = (float) (world == null || world.purpurConfig.explosionClampRadius ? Math.max(power, 0.0) : power); // CraftBukkit - clamp bad values // Purpur - this.x = x; - this.y = y; - this.z = z; -@@ -404,10 +404,29 @@ public class Explosion { - - public void explode() { - // CraftBukkit start -- if (this.radius < 0.1F) { -+ if ((this.level == null || this.level.purpurConfig.explosionClampRadius) && this.radius < 0.1F) { // Purpur - return; - } - // CraftBukkit end -+ -+ // Purpur start - add PreExplodeEvents -+ if(this.source != null){ -+ Location location = new Location(this.level.getWorld(), this.x, this.y, this.z); -+ if(!new org.purpurmc.purpur.event.entity.PreEntityExplodeEvent(this.source.getBukkitEntity(), location, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, org.bukkit.craftbukkit.CraftExplosionResult.toBukkit(getBlockInteraction())).callEvent()) { -+ this.wasCanceled = true; -+ return; -+ } -+ }else { -+ Location location = new Location(this.level.getWorld(), this.x, this.y, this.z); -+ org.bukkit.block.Block block = location.getBlock(); -+ org.bukkit.block.BlockState blockState = (this.damageSource.getDirectBlockState() != null) ? this.damageSource.getDirectBlockState() : block.getState(); -+ if(!new org.purpurmc.purpur.event.PreBlockExplodeEvent(location.getBlock(), this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, blockState, org.bukkit.craftbukkit.CraftExplosionResult.toBukkit(getBlockInteraction())).callEvent()) { -+ this.wasCanceled = true; -+ return; -+ } -+ } -+ //Purpur end -+ - this.level.gameEvent(this.source, (Holder) GameEvent.EXPLODE, new Vec3(this.x, this.y, this.z)); - - // Paper start - collision optimisations diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 6bdbe2982e418b91b2e569ac0702ac1b57f7224e..bb4b64b709e09b2b38cbbe4104622cb267fbb1a6 100644 +index dd4d40a14cef268fe992f2c5ba523748fb619bd9..c3b9a9904f7b34df3dbd0a25e52946ab45f0f4d6 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -178,6 +178,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @@ -14462,12 +14401,12 @@ index 6bdbe2982e418b91b2e569ac0702ac1b57f7224e..bb4b64b709e09b2b38cbbe4104622cb2 public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + public final org.purpurmc.purpur.PurpurWorldConfig purpurConfig; // Purpur - public final co.aikar.timings.WorldTimingsHandler timings; // Paper public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; -@@ -186,6 +187,49 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions - public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Faster redstone torch rapid clock removal; Move from Map in BlockRedstoneTorch to here + private org.spigotmc.TickLimiter tileLimiter; +@@ -187,6 +188,49 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + + public final ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom simpleRandom = new ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom(net.minecraft.world.level.levelgen.RandomSupport.generateUniqueSeed()); // Gale - Pufferfish - move random tick random + // Purpur start + private com.google.common.cache.Cache playerBreedingCooldowns; @@ -14515,7 +14454,7 @@ index 6bdbe2982e418b91b2e569ac0702ac1b57f7224e..bb4b64b709e09b2b38cbbe4104622cb2 public CraftWorld getWorld() { return this.world; } -@@ -699,6 +743,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -847,6 +891,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config this.galeConfig = galeWorldConfigCreator.apply(this.spigotConfig); // Gale - Gale configuration @@ -14524,10 +14463,11 @@ index 6bdbe2982e418b91b2e569ac0702ac1b57f7224e..bb4b64b709e09b2b38cbbe4104622cb2 this.generator = gen; this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); -@@ -2052,4 +2098,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - return null; +@@ -2040,4 +2086,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + return this.id; + } } - // Paper end - optimize redstone (Alternate Current) ++ + // Purpur start + public boolean isNether() { + return getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER; @@ -14539,10 +14479,10 @@ index 6bdbe2982e418b91b2e569ac0702ac1b57f7224e..bb4b64b709e09b2b38cbbe4104622cb2 + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index f636037bb443e35872fcd50483e88b3597b6ad67..7dd99267ad2071b7537c46de3d1dc234384f593a 100644 +index 2febef53fc1c2bbacab94feb5de4e6934e47038e..88b3715df673c6d12aea69fde075ad3caa8c51e8 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -250,7 +250,7 @@ public final class NaturalSpawner { +@@ -273,7 +273,7 @@ public final class NaturalSpawner { blockposition_mutableblockposition.set(l, i, i1); double d0 = (double) l + 0.5D; double d1 = (double) i1 + 0.5D; @@ -14551,8 +14491,50 @@ index f636037bb443e35872fcd50483e88b3597b6ad67..7dd99267ad2071b7537c46de3d1dc234 if (entityhuman != null) { double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); +diff --git a/src/main/java/net/minecraft/world/level/ServerExplosion.java b/src/main/java/net/minecraft/world/level/ServerExplosion.java +index 4de71492339c3d31a34f1fa2aa75e8b216485ef0..7b0a7bc89ae5a459a7db8d9ff728ddf5eb7e1024 100644 +--- a/src/main/java/net/minecraft/world/level/ServerExplosion.java ++++ b/src/main/java/net/minecraft/world/level/ServerExplosion.java +@@ -309,7 +309,7 @@ public class ServerExplosion implements Explosion { + public ServerExplosion(ServerLevel world, @Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator behavior, Vec3 pos, float power, boolean createFire, Explosion.BlockInteraction destructionType) { + this.level = world; + this.source = entity; +- this.radius = (float) Math.max(power, 0.0); // CraftBukkit - clamp bad values ++ this.radius = (float) (world == null || world.purpurConfig.explosionClampRadius ? Math.max(power, 0.0) : power); // CraftBukkit - clamp bad values // Purpur + this.center = pos; + this.fire = createFire; + this.blockInteraction = destructionType; +@@ -664,10 +664,27 @@ public class ServerExplosion implements Explosion { + + public void explode() { + // CraftBukkit start +- if (this.radius < 0.1F) { ++ if ((this.level == null || this.level.purpurConfig.explosionClampRadius) && this.radius < 0.1F) { // Purpur + return; + } + // CraftBukkit end ++ // Purpur start - add PreExplodeEvents ++ if (this.source != null) { ++ Location location = new Location(this.level.getWorld(), this.center.x, this.center.y, this.center.z); ++ if(!new org.purpurmc.purpur.event.entity.PreEntityExplodeEvent(this.source.getBukkitEntity(), location, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, org.bukkit.craftbukkit.CraftExplosionResult.toBukkit(getBlockInteraction())).callEvent()) { ++ this.wasCanceled = true; ++ return; ++ } ++ } else { ++ Location location = new Location(this.level.getWorld(), this.center.x, this.center.y, this.center.z); ++ org.bukkit.block.Block block = location.getBlock(); ++ org.bukkit.block.BlockState blockState = (this.damageSource.getDirectBlockState() != null) ? this.damageSource.getDirectBlockState() : block.getState(); ++ if(!new org.purpurmc.purpur.event.PreBlockExplodeEvent(location.getBlock(), this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, blockState, org.bukkit.craftbukkit.CraftExplosionResult.toBukkit(getBlockInteraction())).callEvent()) { ++ this.wasCanceled = true; ++ return; ++ } ++ } ++ // Purpur end + // Paper start - collision optimisations + this.blockCache = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(); + this.chunkPosCache = new long[CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH]; diff --git a/src/main/java/net/minecraft/world/level/block/AnvilBlock.java b/src/main/java/net/minecraft/world/level/block/AnvilBlock.java -index c77d4adbba79ec39ab78c2a6bac1e8f94ba7fd68..97f75aa767c90a244a094367b408e6899224c7b9 100644 +index 50c907c962f936d2035bb7550750cdbd220b29c2..f9a2d2d4f798efa0d691996ec5ff7fe00260b36c 100644 --- a/src/main/java/net/minecraft/world/level/block/AnvilBlock.java +++ b/src/main/java/net/minecraft/world/level/block/AnvilBlock.java @@ -59,6 +59,53 @@ public class AnvilBlock extends FallingBlock { @@ -14561,12 +14543,12 @@ index c77d4adbba79ec39ab78c2a6bac1e8f94ba7fd68..97f75aa767c90a244a094367b408e689 + // Purpur start - repairable/damageable anvils + @Override -+ protected net.minecraft.world.ItemInteractionResult useItemOn(final net.minecraft.world.item.ItemStack stack, final BlockState state, final Level world, final BlockPos pos, final Player player, final net.minecraft.world.InteractionHand hand, final BlockHitResult hit) { ++ protected net.minecraft.world.InteractionResult useItemOn(final net.minecraft.world.item.ItemStack stack, final BlockState state, final Level world, final BlockPos pos, final Player player, final net.minecraft.world.InteractionHand hand, final BlockHitResult hit) { + if (world.purpurConfig.anvilRepairIngotsAmount > 0 && stack.is(net.minecraft.world.item.Items.IRON_INGOT)) { + if (stack.getCount() < world.purpurConfig.anvilRepairIngotsAmount) { + // not enough iron ingots, play "error" sound and consume + world.playSound(null, pos, net.minecraft.sounds.SoundEvents.ANVIL_HIT, net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F); -+ return net.minecraft.world.ItemInteractionResult.CONSUME; ++ return net.minecraft.world.InteractionResult.CONSUME; + } + if (state.is(Blocks.DAMAGED_ANVIL)) { + world.setBlock(pos, Blocks.CHIPPED_ANVIL.defaultBlockState().setValue(FACING, state.getValue(FACING)), 3); @@ -14575,19 +14557,19 @@ index c77d4adbba79ec39ab78c2a6bac1e8f94ba7fd68..97f75aa767c90a244a094367b408e689 + } else if (state.is(Blocks.ANVIL)) { + // anvil is already fully repaired, play "error" sound and consume + world.playSound(null, pos, net.minecraft.sounds.SoundEvents.ANVIL_HIT, net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F); -+ return net.minecraft.world.ItemInteractionResult.CONSUME; ++ return net.minecraft.world.InteractionResult.CONSUME; + } + if (!player.getAbilities().instabuild) { + stack.shrink(world.purpurConfig.anvilRepairIngotsAmount); + } + world.playSound(null, pos, net.minecraft.sounds.SoundEvents.ANVIL_PLACE, net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F); -+ return net.minecraft.world.ItemInteractionResult.CONSUME; ++ return net.minecraft.world.InteractionResult.CONSUME; + } + if (world.purpurConfig.anvilDamageObsidianAmount > 0 && stack.is(net.minecraft.world.item.Items.OBSIDIAN)) { + if (stack.getCount() < world.purpurConfig.anvilDamageObsidianAmount) { + // not enough obsidian, play "error" sound and consume + world.playSound(null, pos, net.minecraft.sounds.SoundEvents.ANVIL_HIT, net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F); -+ return net.minecraft.world.ItemInteractionResult.CONSUME; ++ return net.minecraft.world.InteractionResult.CONSUME; + } + if (state.is(Blocks.DAMAGED_ANVIL)) { + world.destroyBlock(pos, false); @@ -14600,20 +14582,20 @@ index c77d4adbba79ec39ab78c2a6bac1e8f94ba7fd68..97f75aa767c90a244a094367b408e689 + stack.shrink(world.purpurConfig.anvilDamageObsidianAmount); + } + world.playSound(null, pos, net.minecraft.sounds.SoundEvents.ANVIL_LAND, net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F); -+ return net.minecraft.world.ItemInteractionResult.CONSUME; ++ return net.minecraft.world.InteractionResult.CONSUME; + } -+ return net.minecraft.world.ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; ++ return net.minecraft.world.InteractionResult.TRY_WITH_EMPTY_HAND; + } + // Purpur end + @Override protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) { - if (world.isClientSide) { + if (!world.isClientSide) { diff --git a/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java b/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java -index fad69dfc20574ab23634b14252b50929cca75b21..7082486f6b760bed2a61938f493d5124722b58e2 100644 +index affbbf6abc6bc09ecb652c1dee92aa297458bc39..febc05dc39741807127cba4a2a55aaad62b0800c 100644 --- a/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java +++ b/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java -@@ -49,6 +49,20 @@ public class AzaleaBlock extends BushBlock implements BonemealableBlock { +@@ -50,6 +50,20 @@ public class AzaleaBlock extends BushBlock implements BonemealableBlock { @Override public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { @@ -14635,10 +14617,10 @@ index fad69dfc20574ab23634b14252b50929cca75b21..7082486f6b760bed2a61938f493d5124 } diff --git a/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java b/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java -index ce9f189bdafec26360bfadd0f36a8bc2726e132b..d5465b48531fd4b4094874c135274abf985ee71a 100644 +index d7ca7a43d2d5f8cad416156fd40588cdd6634f52..231338adda19f57bf1a95379cc2e14341d4068d0 100644 --- a/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java -@@ -38,6 +38,7 @@ public abstract class BaseCoralPlantTypeBlock extends Block implements SimpleWat +@@ -39,6 +39,7 @@ public abstract class BaseCoralPlantTypeBlock extends Block implements SimpleWat } protected static boolean scanForWater(BlockState state, BlockGetter world, BlockPos pos) { @@ -14647,19 +14629,19 @@ index ce9f189bdafec26360bfadd0f36a8bc2726e132b..d5465b48531fd4b4094874c135274abf return true; } else { diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java -index 85d598c3354ee62f0fd1b26e485e0084967c0380..17c994a39a1b99cc7727e328ce7493d534247a21 100644 +index c02c4834ace843633b77fb43eeadd3ddc7b1f743..c130d316e87f1f896d33ab43831063a89e3bef2b 100644 --- a/src/main/java/net/minecraft/world/level/block/BedBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java -@@ -104,7 +104,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock +@@ -106,7 +106,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock Vec3 vec3d = pos.getCenter(); - world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); + if (world.purpurConfig.bedExplode) world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, (float) world.purpurConfig.bedExplosionPower, world.purpurConfig.bedExplosionFire, world.purpurConfig.bedExplosionEffect); // Purpur - return InteractionResult.SUCCESS; + return InteractionResult.SUCCESS_SERVER; } else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) { if (!BedBlock.canSetSpawn(world)) return this.explodeBed(state, world, pos); // Paper - check explode first -@@ -157,7 +157,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock +@@ -159,7 +159,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock Vec3 vec3d = blockposition.getCenter(); @@ -14668,7 +14650,7 @@ index 85d598c3354ee62f0fd1b26e485e0084967c0380..17c994a39a1b99cc7727e328ce7493d5 return InteractionResult.SUCCESS; } } -@@ -181,7 +181,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock +@@ -183,7 +183,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock @Override public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) { @@ -14678,10 +14660,10 @@ index 85d598c3354ee62f0fd1b26e485e0084967c0380..17c994a39a1b99cc7727e328ce7493d5 @Override diff --git a/src/main/java/net/minecraft/world/level/block/BigDripleafBlock.java b/src/main/java/net/minecraft/world/level/block/BigDripleafBlock.java -index 8240c32d676a88aa23dcd052ee0136767e54fb0d..372c4ab9d390d5afd98947f21c79aae06b15064d 100644 +index 9e3f1441d62128535112621bf259c24f1a90595b..2535e6d71b690f8dfde41a7d9cb76b6f010f5aa7 100644 --- a/src/main/java/net/minecraft/world/level/block/BigDripleafBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BigDripleafBlock.java -@@ -244,7 +244,7 @@ public class BigDripleafBlock extends HorizontalDirectionalBlock implements Bone +@@ -246,7 +246,7 @@ public class BigDripleafBlock extends HorizontalDirectionalBlock implements Bone BigDripleafBlock.playTiltSound(world, blockposition, soundeffect); } @@ -14691,7 +14673,7 @@ index 8240c32d676a88aa23dcd052ee0136767e54fb0d..372c4ab9d390d5afd98947f21c79aae0 if (i != -1) { world.scheduleTick(blockposition, (Block) this, i); diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index b807f4a5239f32e6b6080a58e055357b7341cf00..34d96e8bfebdee3bcc61071c6ec22b53baecec3f 100644 +index ef8d8990a8a98c0cbc3e7aa45d22c6008f0ff2bb..070a3dbd9b92053bfed11e1f8be6f9153dc47c29 100644 --- a/src/main/java/net/minecraft/world/level/block/Block.java +++ b/src/main/java/net/minecraft/world/level/block/Block.java @@ -88,6 +88,10 @@ public class Block extends BlockBehaviour implements ItemLike { @@ -14702,10 +14684,10 @@ index b807f4a5239f32e6b6080a58e055357b7341cf00..34d96e8bfebdee3bcc61071c6ec22b53 + public float fallDamageMultiplier = 1.0F; + public float fallDistanceMultiplier = 1.0F; + // Purpur end - // Paper start + // Paper start - Protect Bedrock and End Portal/Frames from being destroyed public final boolean isDestroyable() { return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits || -@@ -311,7 +315,7 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -303,7 +307,7 @@ public class Block extends BlockBehaviour implements ItemLike { public static void dropResources(BlockState state, LevelAccessor world, BlockPos pos, @Nullable BlockEntity blockEntity) { if (world instanceof ServerLevel) { Block.getDrops(state, (ServerLevel) world, pos, blockEntity).forEach((itemstack) -> { @@ -14714,7 +14696,7 @@ index b807f4a5239f32e6b6080a58e055357b7341cf00..34d96e8bfebdee3bcc61071c6ec22b53 }); state.spawnAfterBreak((ServerLevel) world, pos, ItemStack.EMPTY, true); } -@@ -330,7 +334,7 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -322,7 +326,7 @@ public class Block extends BlockBehaviour implements ItemLike { event.setExpToDrop(block.getExpDrop(state, serverLevel, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping event.callEvent(); for (org.bukkit.inventory.ItemStack drop : event.getDrops()) { @@ -14723,7 +14705,7 @@ index b807f4a5239f32e6b6080a58e055357b7341cf00..34d96e8bfebdee3bcc61071c6ec22b53 } state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping -@@ -347,13 +351,32 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -339,13 +343,32 @@ public class Block extends BlockBehaviour implements ItemLike { // Paper end - Properly handle xp dropping if (world instanceof ServerLevel) { Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, tool).forEach((itemstack1) -> { @@ -14757,7 +14739,7 @@ index b807f4a5239f32e6b6080a58e055357b7341cf00..34d96e8bfebdee3bcc61071c6ec22b53 public static void popResource(Level world, BlockPos pos, ItemStack stack) { double d0 = (double) EntityType.ITEM.getHeight() / 2.0D; double d1 = (double) pos.getX() + 0.5D + Mth.nextDouble(world.random, -0.25D, 0.25D); -@@ -437,7 +460,17 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -433,7 +456,17 @@ public class Block extends BlockBehaviour implements ItemLike { } // Paper - fix drops not preventing stats/food exhaustion } @@ -14776,7 +14758,7 @@ index b807f4a5239f32e6b6080a58e055357b7341cf00..34d96e8bfebdee3bcc61071c6ec22b53 public boolean isPossibleToRespawnInThis(BlockState state) { return !state.isSolid() && !state.liquid(); -@@ -456,7 +489,7 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -444,7 +477,7 @@ public class Block extends BlockBehaviour implements ItemLike { } public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) { @@ -14784,32 +14766,32 @@ index b807f4a5239f32e6b6080a58e055357b7341cf00..34d96e8bfebdee3bcc61071c6ec22b53 + entity.causeFallDamage(fallDistance * fallDistanceMultiplier, fallDamageMultiplier, entity.damageSources().fall()); // Purpur } - public void updateEntityAfterFallOn(BlockGetter world, Entity entity) { + public void updateEntityMovementAfterFallOn(BlockGetter world, Entity entity) { diff --git a/src/main/java/net/minecraft/world/level/block/Blocks.java b/src/main/java/net/minecraft/world/level/block/Blocks.java -index 223259e7a09ada681b6181c898f6857888594f85..7d58a95f7ae8983b466b275f4f82597d38762af0 100644 +index 66a07f7cbf1c1d6ecbe055cbf4f63eb07d93e90c..63d67d46d30ed8ed57cdc0e59b6cb6b75ab22c1f 100644 --- a/src/main/java/net/minecraft/world/level/block/Blocks.java +++ b/src/main/java/net/minecraft/world/level/block/Blocks.java -@@ -7361,6 +7361,7 @@ public class Blocks { - BlockBehaviour.Properties.of() - .mapColor(MapColor.PLANT) - .forceSolidOff() +@@ -6465,6 +6465,7 @@ public class Blocks { + BlockBehaviour.Properties.of() + .mapColor(MapColor.PLANT) + .forceSolidOff() + .randomTicks() // Purpur - .instabreak() - .sound(SoundType.AZALEA) - .noOcclusion() -@@ -7373,6 +7374,7 @@ public class Blocks { - BlockBehaviour.Properties.of() - .mapColor(MapColor.PLANT) - .forceSolidOff() + .instabreak() + .sound(SoundType.AZALEA) + .noOcclusion() +@@ -6476,6 +6477,7 @@ public class Blocks { + BlockBehaviour.Properties.of() + .mapColor(MapColor.PLANT) + .forceSolidOff() + .randomTicks() // Purpur - .instabreak() - .sound(SoundType.FLOWERING_AZALEA) - .noOcclusion() + .instabreak() + .sound(SoundType.FLOWERING_AZALEA) + .noOcclusion() diff --git a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java -index 4c1f20fafdbd86011959cc2d4983b6c2f8e87a5f..78679c2c26a36cf08cf3ffe78617d97d3439e14c 100644 +index 385da0585f409ee453f10d45f5837cdc09adc21b..c65016cba376a41c267fb4b6499ec0a263851558 100644 --- a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java -@@ -122,10 +122,10 @@ public class BubbleColumnBlock extends Block implements BucketPickup { +@@ -123,10 +123,10 @@ public class BubbleColumnBlock extends Block implements BucketPickup { if (state.is(Blocks.BUBBLE_COLUMN)) { return state; } else if (state.is(Blocks.SOUL_SAND)) { @@ -14823,10 +14805,10 @@ index 4c1f20fafdbd86011959cc2d4983b6c2f8e87a5f..78679c2c26a36cf08cf3ffe78617d97d } } diff --git a/src/main/java/net/minecraft/world/level/block/BushBlock.java b/src/main/java/net/minecraft/world/level/block/BushBlock.java -index a7b4b5600e3c889c69ac22294899713d50b5fe5c..a27e298ffdfa6956be9cde429d2cd45483a51fed 100644 +index eb324fda54ada3ed7941713a784ed2d686ec8c4b..09cc76f3fee4a767c9ec3fa592f2c3c6146344ec 100644 --- a/src/main/java/net/minecraft/world/level/block/BushBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java -@@ -52,4 +52,24 @@ public abstract class BushBlock extends Block { +@@ -55,4 +55,24 @@ public abstract class BushBlock extends Block { protected boolean isPathfindable(BlockState state, PathComputationType type) { return type == PathComputationType.AIR && !this.hasCollision ? true : super.isPathfindable(state, type); } @@ -14852,10 +14834,10 @@ index a7b4b5600e3c889c69ac22294899713d50b5fe5c..a27e298ffdfa6956be9cde429d2cd454 + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -index ff4dda48116a2969704b355ff96407ba869b466e..066181ed274a492762baebf05bf51ac7848878cc 100644 +index c045b1cccf0047dbef8c04d5a28d31d53389054f..9f163ed07f8e6a5370c4c355b4e910f7a49b6bcd 100644 --- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -@@ -23,7 +23,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; +@@ -24,7 +24,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit @@ -14864,7 +14846,7 @@ index ff4dda48116a2969704b355ff96407ba869b466e..066181ed274a492762baebf05bf51ac7 public static final MapCodec CODEC = simpleCodec(CactusBlock::new); public static final IntegerProperty AGE = BlockStateProperties.AGE_15; -@@ -114,7 +114,7 @@ public class CactusBlock extends Block { +@@ -115,7 +115,7 @@ public class CactusBlock extends Block { enumdirection = (Direction) iterator.next(); iblockdata1 = world.getBlockState(pos.relative(enumdirection)); @@ -14873,7 +14855,7 @@ index ff4dda48116a2969704b355ff96407ba869b466e..066181ed274a492762baebf05bf51ac7 return false; } -@@ -134,4 +134,34 @@ public class CactusBlock extends Block { +@@ -135,4 +135,34 @@ public class CactusBlock extends Block { protected boolean isPathfindable(BlockState state, PathComputationType type) { return false; } @@ -14908,11 +14890,23 @@ index ff4dda48116a2969704b355ff96407ba869b466e..066181ed274a492762baebf05bf51ac7 + } + // Purpur end } +diff --git a/src/main/java/net/minecraft/world/level/block/CakeBlock.java b/src/main/java/net/minecraft/world/level/block/CakeBlock.java +index 648c2510beb162e73aed236a3169d0bbb8fc5050..3563a241c0b697dc0167cf7b1aa73fef7d1e7934 100644 +--- a/src/main/java/net/minecraft/world/level/block/CakeBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CakeBlock.java +@@ -119,6 +119,7 @@ public class CakeBlock extends Block { + org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel); + + if (!event.isCancelled()) { ++ if (player.level().purpurConfig.playerBurpWhenFull && event.getFoodLevel() == 20 && oldFoodLevel < 20) player.burpDelay = player.level().purpurConfig.playerBurpDelay; // Purpur + player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F); + } + diff --git a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java -index 7f6058f4def83867971121751acd51c398583651..5a49daf7b6bf9e0ec3d50494287a620d41f8d85d 100644 +index 18d4020017d76303d3179fad8974574777ea6305..2ee2b1485f848ac5270bc3f7e1e5b1bc3029b0bb 100644 --- a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java -@@ -132,7 +132,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB +@@ -140,7 +140,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB BlockPos blockposition = ctx.getClickedPos(); boolean flag = world.getFluidState(blockposition).getType() == Fluids.WATER; @@ -14922,11 +14916,11 @@ index 7f6058f4def83867971121751acd51c398583651..5a49daf7b6bf9e0ec3d50494287a620d @Override diff --git a/src/main/java/net/minecraft/world/level/block/CarvedPumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/CarvedPumpkinBlock.java -index 655f51902e5d24643d41c4ec981743543c0890a5..e6a299eeda5d18274fa3b1fb542b217a074c1d83 100644 +index 22242d11e009acab4c9738a1c6ada8b9ba678a0c..828fa78a89f13ef81c53b4d6ea6ef86c7b53024e 100644 --- a/src/main/java/net/minecraft/world/level/block/CarvedPumpkinBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CarvedPumpkinBlock.java -@@ -71,7 +71,7 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { - SnowGolem entitysnowman = (SnowGolem) EntityType.SNOW_GOLEM.create(world); +@@ -72,7 +72,7 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { + SnowGolem entitysnowman = (SnowGolem) EntityType.SNOW_GOLEM.create(world, EntitySpawnReason.TRIGGERED); if (entitysnowman != null) { - CarvedPumpkinBlock.spawnGolemInWorld(world, shapedetector_shapedetectorcollection, entitysnowman, shapedetector_shapedetectorcollection.getBlock(0, 2, 0).getPos()); @@ -14934,7 +14928,7 @@ index 655f51902e5d24643d41c4ec981743543c0890a5..e6a299eeda5d18274fa3b1fb542b217a } } else { BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection1 = this.getOrCreateIronGolemFull().find(world, pos); -@@ -81,7 +81,7 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { +@@ -82,7 +82,7 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { if (entityirongolem != null) { entityirongolem.setPlayerCreated(true); @@ -14943,7 +14937,7 @@ index 655f51902e5d24643d41c4ec981743543c0890a5..e6a299eeda5d18274fa3b1fb542b217a } } } -@@ -89,6 +89,16 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { +@@ -90,6 +90,16 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock { } private static void spawnGolemInWorld(Level world, BlockPattern.BlockPatternMatch patternResult, Entity entity, BlockPos pos) { @@ -14974,10 +14968,10 @@ index c9968934f4ecaa8d81e545f279b3001c7b1ce545..03e4fce6f8226451365fc2831b5bf1e5 @Override diff --git a/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java b/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java -index 635fc086d832c641f840cf36d18cdc0fcc3beef3..e3ff7b8059da499cfde1106f6d51156931b292dc 100644 +index c4473c2a778116d48bc3e4796afd901f455070e6..e62217c0bfa6cc426c7d41154f3ccc34d8f242ca 100644 --- a/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java -@@ -94,4 +94,11 @@ public class CaveVinesBlock extends GrowingPlantHeadBlock implements Bonemealabl +@@ -94,4 +94,11 @@ public class CaveVinesBlock extends GrowingPlantHeadBlock implements CaveVines { public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) { world.setBlock(pos, state.setValue(BERRIES, Boolean.valueOf(true)), 2); } @@ -15003,10 +14997,10 @@ index daae7fd6e0148cfba8e359d990748a0c83a3376e..0e06b1bcd906e92c083dc74d56d6d0a2 return random.nextFloat() < f1 ? this.getNext(state) : Optional.empty(); } diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -index 0b27baf10770cb3077c4e75da55209689d614513..485ea9892f257c6843db23bca43f9fdcd8fa1503 100644 +index edef8fc62f8dba1b57214d8d7d805ff0d83f4114..663eb96b8227f000448957b5d8ea13ca78cee329 100644 --- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java +++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java -@@ -342,6 +342,7 @@ public class ChestBlock extends AbstractChestBlock implements +@@ -341,6 +341,7 @@ public class ChestBlock extends AbstractChestBlock implements } public static boolean isBlockedChestByBlock(BlockGetter world, BlockPos pos) { @@ -15015,10 +15009,10 @@ index 0b27baf10770cb3077c4e75da55209689d614513..485ea9892f257c6843db23bca43f9fdc return world.getBlockState(blockposition1).isRedstoneConductor(world, blockposition1); diff --git a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java -index 35059d9b575aee92865fd15a20c3db335a98fb76..735f008fb9265ad3abecafb74896efd428988c4e 100644 +index ceab17cdf519278393e41311488e6d7f99133ebe..c9c575c48965a31830cf97578911a69e889ed349 100644 --- a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java +++ b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java -@@ -237,18 +237,27 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { +@@ -241,18 +241,27 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { int i = (Integer) state.getValue(ComposterBlock.LEVEL); if (i < 8 && ComposterBlock.COMPOSTABLES.containsKey(stack.getItem())) { @@ -15026,7 +15020,7 @@ index 35059d9b575aee92865fd15a20c3db335a98fb76..735f008fb9265ad3abecafb74896efd4 - BlockState iblockdata1 = ComposterBlock.addItem(player, state, world, pos, stack); - // Paper start - handle cancelled events - if (iblockdata1 == null) { -- return ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION; +- return InteractionResult.PASS; - } - // Paper end - @@ -15036,7 +15030,7 @@ index 35059d9b575aee92865fd15a20c3db335a98fb76..735f008fb9265ad3abecafb74896efd4 + // Purpur start - sneak to bulk process composter + BlockState newState = process(i, player, state, world, pos, stack); + if (newState == null) { -+ return ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION; ++ return InteractionResult.PASS; } + if (world.purpurConfig.composterBulkProcess && player.isShiftKeyDown() && newState != state) { + BlockState oldState; @@ -15047,7 +15041,7 @@ index 35059d9b575aee92865fd15a20c3db335a98fb76..735f008fb9265ad3abecafb74896efd4 + oldLevel = oldState.getValue(ComposterBlock.LEVEL); + newState = process(oldLevel, player, oldState, world, pos, stack); + if (newState == null) { -+ return ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION; ++ return InteractionResult.PASS; + } + newCount = stack.getCount(); + newLevel = newState.getValue(ComposterBlock.LEVEL); @@ -15055,9 +15049,9 @@ index 35059d9b575aee92865fd15a20c3db335a98fb76..735f008fb9265ad3abecafb74896efd4 + } + // Purpur end - return ItemInteractionResult.sidedSuccess(world.isClientSide); + return InteractionResult.SUCCESS; } else { -@@ -256,6 +265,25 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { +@@ -260,6 +269,25 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { } } @@ -15084,10 +15078,10 @@ index 35059d9b575aee92865fd15a20c3db335a98fb76..735f008fb9265ad3abecafb74896efd4 protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) { int i = (Integer) state.getValue(ComposterBlock.LEVEL); diff --git a/src/main/java/net/minecraft/world/level/block/CoralBlock.java b/src/main/java/net/minecraft/world/level/block/CoralBlock.java -index 81fe0dea8e6e23c4a78f07fc2f9c0d68cd683f11..bff97b7d3909f2ec9e58a341b901b3741927543f 100644 +index a59b23f4062fa896836dec72cbd5097411774ad1..c526ea13a726624adaa654f09ff84c899c13ab98 100644 --- a/src/main/java/net/minecraft/world/level/block/CoralBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CoralBlock.java -@@ -59,6 +59,7 @@ public class CoralBlock extends Block { +@@ -60,6 +60,7 @@ public class CoralBlock extends Block { } protected boolean scanForWater(BlockGetter world, BlockPos pos) { @@ -15096,19 +15090,19 @@ index 81fe0dea8e6e23c4a78f07fc2f9c0d68cd683f11..bff97b7d3909f2ec9e58a341b901b374 int i = aenumdirection.length; diff --git a/src/main/java/net/minecraft/world/level/block/CropBlock.java b/src/main/java/net/minecraft/world/level/block/CropBlock.java -index 112d2feba5f75a2a873b595617780515945c10e4..5a190834baef60c7b61074393f8856a933902d81 100644 +index 1ada5ed825501666addacf527a513ab7bd4a3a58..33c27909290ff3ab483226cf65b1a1bc2e983cbc 100644 --- a/src/main/java/net/minecraft/world/level/block/CropBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CropBlock.java -@@ -179,7 +179,7 @@ public class CropBlock extends BushBlock implements BonemealableBlock { - @Override +@@ -180,7 +180,7 @@ public class CropBlock extends BushBlock implements BonemealableBlock { protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent -- if (entity instanceof Ravager && CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit -+ if (entity instanceof Ravager && world.purpurConfig.ravagerGriefableBlocks.contains(world.getBlockState(pos).getBlock()) && CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), (!world.purpurConfig.ravagerBypassMobGriefing && !world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)))) { // CraftBukkit // Purpur - world.destroyBlock(pos, true, entity); + if (world instanceof ServerLevel worldserver) { +- if (entity instanceof Ravager && CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit ++ if (entity instanceof Ravager && world.purpurConfig.ravagerGriefableBlocks.contains(world.getBlockState(pos).getBlock()) && CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !world.purpurConfig.ravagerBypassMobGriefing == !worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit // Purpur + worldserver.destroyBlock(pos, true, entity); + } } - -@@ -214,4 +214,15 @@ public class CropBlock extends BushBlock implements BonemealableBlock { +@@ -216,4 +216,15 @@ public class CropBlock extends BushBlock implements BonemealableBlock { protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(CropBlock.AGE); } @@ -15125,10 +15119,10 @@ index 112d2feba5f75a2a873b595617780515945c10e4..5a190834baef60c7b61074393f8856a9 + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/DoorBlock.java b/src/main/java/net/minecraft/world/level/block/DoorBlock.java -index 6dd75bc722f9c20b4869e6353115c3b02dd79f99..dfaf82f5b0180cf08c4125347867d37a2557fd24 100644 +index 077b99caf0ec0ee098786d23194d88e1dc4481ce..daf865c20cc193a12db0d98e3c0472eefdf635c2 100644 --- a/src/main/java/net/minecraft/world/level/block/DoorBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DoorBlock.java -@@ -198,6 +198,7 @@ public class DoorBlock extends Block { +@@ -200,6 +200,7 @@ public class DoorBlock extends Block { protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) { if (!this.type.canOpenByHand()) { return InteractionResult.PASS; @@ -15136,7 +15130,7 @@ index 6dd75bc722f9c20b4869e6353115c3b02dd79f99..dfaf82f5b0180cf08c4125347867d37a } else { state = (BlockState) state.cycle(DoorBlock.OPEN); world.setBlock(pos, state, 10); -@@ -299,4 +300,18 @@ public class DoorBlock extends Block { +@@ -301,4 +302,18 @@ public class DoorBlock extends Block { flag = false; return flag; } @@ -15156,7 +15150,7 @@ index 6dd75bc722f9c20b4869e6353115c3b02dd79f99..dfaf82f5b0180cf08c4125347867d37a + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/DragonEggBlock.java b/src/main/java/net/minecraft/world/level/block/DragonEggBlock.java -index fbe15cdd5b9bca2ab4b1e871abbbdbff49ade8a4..23d113842bf774bdc74e0dffcc97b642bc8684f1 100644 +index 30d15686b1a81de7ac28feb0c6188eb007c6f2fd..b6799db00e157892dd4339a01d2ca36092c8e491 100644 --- a/src/main/java/net/minecraft/world/level/block/DragonEggBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DragonEggBlock.java @@ -48,8 +48,8 @@ public class DragonEggBlock extends FallingBlock { @@ -15170,10 +15164,10 @@ index fbe15cdd5b9bca2ab4b1e871abbbdbff49ade8a4..23d113842bf774bdc74e0dffcc97b642 BlockPos blockposition1 = pos.offset(world.random.nextInt(16) - world.random.nextInt(16), world.random.nextInt(8) - world.random.nextInt(8), world.random.nextInt(16) - world.random.nextInt(16)); diff --git a/src/main/java/net/minecraft/world/level/block/EnchantingTableBlock.java b/src/main/java/net/minecraft/world/level/block/EnchantingTableBlock.java -index 151e856dda3aa262c846ce8793650ee582bfb749..be0ed8a14e5726d5fcea1864302b18fb75fde2b4 100644 +index a7fb500d950687743d1fc0b3ad3e6d10dcc6e31a..ce6a9e15ae0114623e79b5d8c244c2c490a3f74e 100644 --- a/src/main/java/net/minecraft/world/level/block/EnchantingTableBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EnchantingTableBlock.java -@@ -124,4 +124,18 @@ public class EnchantingTableBlock extends BaseEntityBlock { +@@ -123,4 +123,18 @@ public class EnchantingTableBlock extends BaseEntityBlock { protected boolean isPathfindable(BlockState state, PathComputationType type) { return false; } @@ -15193,10 +15187,10 @@ index 151e856dda3aa262c846ce8793650ee582bfb749..be0ed8a14e5726d5fcea1864302b18fb + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java b/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java -index 3f5bb5c9ceb5b31fcc9ef0a7a6157e1e1cb2a09f..9bd56c48119fe630f272427a2ec99ffe19eefdfb 100644 +index a7a21f071161fb7e73a046717d2462f871ab653c..abb75f9389167a1f51a2c50831664d50181749de 100644 --- a/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java -@@ -102,6 +102,13 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal { +@@ -104,6 +104,13 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal { TheEndGatewayBlockEntity tileentityendgateway = (TheEndGatewayBlockEntity) tileentity; if (!tileentityendgateway.isCoolingDown()) { @@ -15211,13 +15205,13 @@ index 3f5bb5c9ceb5b31fcc9ef0a7a6157e1e1cb2a09f..9bd56c48119fe630f272427a2ec99ffe TheEndGatewayBlockEntity.triggerCooldown(world, pos, state, tileentityendgateway); } diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -index a35a426cc7778a51523f26057b5d61b8a3e23d5d..28d8c8a879badc97cd1168e1847e2fafdc40e4bd 100644 +index 4aa14f975e1ceedf3d4a427e0daefb58b12fcafe..2dffc3990d9ae3d595d923239885e3a7d8ec04f3 100644 --- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -@@ -65,6 +65,13 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { +@@ -70,6 +70,13 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent - if (entity.canUsePortal(false) && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), state.getShape(world, pos), BooleanOp.AND)) { + if (entity.canUsePortal(false)) { + // Purpur start + if (world.purpurConfig.imposeTeleportRestrictionsOnEndPortals && (entity.isVehicle() || entity.isPassenger())) { + if (!new org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent(entity.getBukkitEntity(), entity.isPassenger() ? org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_PASSENGER : org.purpurmc.purpur.event.entity.EntityTeleportHinderedEvent.Reason.IS_VEHICLE, PlayerTeleportEvent.TeleportCause.END_PORTAL).callEvent()) { @@ -15229,19 +15223,19 @@ index a35a426cc7778a51523f26057b5d61b8a3e23d5d..28d8c8a879badc97cd1168e1847e2faf EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.ENDER); // Paper - add portal type world.getCraftServer().getPluginManager().callEvent(event); diff --git a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java -index 491a59336899179c79820cd61541d49f7337c0f6..492fda30f22c8d09271931229ec02bb6f98f5889 100644 +index 2a207fb2e1c26b562de42240e11c856bd2a23458..6ad4aa371607ab92616626285a7e71757c76a3db 100644 --- a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java -@@ -92,7 +92,7 @@ public class EnderChestBlock extends AbstractChestBlock i - playerEnderChestContainer.setActiveChest(enderChestBlockEntity); - // Paper start - Fix InventoryOpenEvent cancellation - if (player.openMenu( +@@ -89,7 +89,7 @@ public class EnderChestBlock extends AbstractChestBlock i + // Paper start - Fix InventoryOpenEvent cancellation - moved up; + playerEnderChestContainer.setActiveChest(enderChestBlockEntity); // Needs to happen before ChestMenu.threeRows as it is required for opening animations + if (world instanceof ServerLevel serverLevel && player.openMenu( - new SimpleMenuProvider((i, inventory, playerx) -> ChestMenu.threeRows(i, inventory, playerEnderChestContainer), CONTAINER_TITLE) + new SimpleMenuProvider((i, inventory, playerx) -> org.purpurmc.purpur.PurpurConfig.enderChestSixRows ? getEnderChestSixRows(i, inventory, player, playerEnderChestContainer) : ChestMenu.threeRows(i, inventory, playerEnderChestContainer), CONTAINER_TITLE) // Purpur ).isPresent()) { - player.awardStat(Stats.OPEN_ENDERCHEST); - PiglinAi.angerNearbyPiglins(player, true); -@@ -105,6 +105,35 @@ public class EnderChestBlock extends AbstractChestBlock i + // Paper end - Fix InventoryOpenEvent cancellation - moved up; + // Paper - Fix InventoryOpenEvent cancellation - moved up; +@@ -104,6 +104,35 @@ public class EnderChestBlock extends AbstractChestBlock i } } @@ -15278,21 +15272,21 @@ index 491a59336899179c79820cd61541d49f7337c0f6..492fda30f22c8d09271931229ec02bb6 public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new EnderChestBlockEntity(pos, state); diff --git a/src/main/java/net/minecraft/world/level/block/FarmBlock.java b/src/main/java/net/minecraft/world/level/block/FarmBlock.java -index d59e33e7326489c6d55d316d0130f22235f4c63c..d0ec0722496ed931b48c4e7076fddbb1ed36e111 100644 +index c3dba0c2c94f3804338f86621dc42405e380a6b3..eaac00e2534aca4eab92c7b9f9248e04b35b47df 100644 --- a/src/main/java/net/minecraft/world/level/block/FarmBlock.java +++ b/src/main/java/net/minecraft/world/level/block/FarmBlock.java -@@ -111,7 +111,7 @@ public class FarmBlock extends Block { - @Override +@@ -112,7 +112,7 @@ public class FarmBlock extends Block { public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) { super.fallOn(world, state, pos, entity, fallDistance); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage. -- if (!world.isClientSide && world.random.nextFloat() < fallDistance - 0.5F && entity instanceof LivingEntity && (entity instanceof Player || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { -+ if (!world.isClientSide && (world.purpurConfig.farmlandTrampleHeight >= 0D ? fallDistance >= world.purpurConfig.farmlandTrampleHeight : world.random.nextFloat() < fallDistance - 0.5F) && entity instanceof LivingEntity && (entity instanceof Player || world.purpurConfig.farmlandBypassMobGriefing || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { // Purpur - // CraftBukkit start - Interact soil - org.bukkit.event.Cancellable cancellable; - if (entity instanceof Player) { -@@ -125,6 +125,22 @@ public class FarmBlock extends Block { - return; - } + if (world instanceof ServerLevel worldserver) { +- if (world.random.nextFloat() < fallDistance - 0.5F && entity instanceof LivingEntity && (entity instanceof Player || worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { ++ if ((worldserver.purpurConfig.farmlandTrampleHeight >= 0D ? fallDistance >= worldserver.purpurConfig.farmlandTrampleHeight : world.random.nextFloat() < fallDistance - 0.5F) && entity instanceof LivingEntity && (entity instanceof Player || worldserver.purpurConfig.farmlandBypassMobGriefing ^ worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) { // Purpur + // CraftBukkit start - Interact soil + org.bukkit.event.Cancellable cancellable; + if (entity instanceof Player) { +@@ -126,6 +126,22 @@ public class FarmBlock extends Block { + return; + } + // Purpur start + if (world.purpurConfig.farmlandTramplingDisabled) return; @@ -15310,10 +15304,10 @@ index d59e33e7326489c6d55d316d0130f22235f4c63c..d0ec0722496ed931b48c4e7076fddbb1 + } + } + // Purpur end - if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.DIRT.defaultBlockState())) { - return; - } -@@ -172,7 +188,7 @@ public class FarmBlock extends Block { + if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.DIRT.defaultBlockState())) { + return; + } +@@ -174,7 +190,7 @@ public class FarmBlock extends Block { } } @@ -15323,15 +15317,15 @@ index d59e33e7326489c6d55d316d0130f22235f4c63c..d0ec0722496ed931b48c4e7076fddbb1 } diff --git a/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java b/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java -index cf05da1c86e3018db11dc079bf50317b6639e5cc..8e9903899ac91e9431f00675c1f5ac4a18e61593 100644 +index 9b424d7661fedf8ee1eb9f3167c62e563f04d4d1..2af311847a085a8073e9bcb26c762d1bbe1eae2c 100644 --- a/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java +++ b/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java @@ -34,12 +34,12 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements @Override - public BlockState getStateForPlacement(LevelAccessor world) { -- return (BlockState) this.defaultBlockState().setValue(GrowingPlantHeadBlock.AGE, world.getRandom().nextInt(25)); -+ return (BlockState) this.defaultBlockState().setValue(GrowingPlantHeadBlock.AGE, world.getRandom().nextInt(getMaxGrowthAge())); // Purpur + public BlockState getStateForPlacement(RandomSource random) { +- return (BlockState) this.defaultBlockState().setValue(GrowingPlantHeadBlock.AGE, random.nextInt(25)); ++ return (BlockState) this.defaultBlockState().setValue(GrowingPlantHeadBlock.AGE, random.nextInt(getMaxGrowthAge())); // Purpur } @Override @@ -15400,10 +15394,10 @@ index ef364aa171a48482a45bc18cfe730ec20c3f7be6..74971d90506aa253d5ee821b5390fb25 } } diff --git a/src/main/java/net/minecraft/world/level/block/IceBlock.java b/src/main/java/net/minecraft/world/level/block/IceBlock.java -index ac775afb265430ac202cfa3900a036d11a308b1e..87ce003dfeca975d8e6af26fd341f3abe66dc185 100644 +index a94762e65853ccad38cf90b0049ca256106c0c9f..38633e168a9b36e37feea00964d53e657926639e 100644 --- a/src/main/java/net/minecraft/world/level/block/IceBlock.java +++ b/src/main/java/net/minecraft/world/level/block/IceBlock.java -@@ -41,7 +41,7 @@ public class IceBlock extends HalfTransparentBlock { +@@ -42,7 +42,7 @@ public class IceBlock extends HalfTransparentBlock { public void afterDestroy(Level world, BlockPos pos, ItemStack tool) { // Paper end - Improve Block#breakNaturally API if (!EnchantmentHelper.hasTag(tool, EnchantmentTags.PREVENTS_ICE_MELTING)) { @@ -15412,7 +15406,7 @@ index ac775afb265430ac202cfa3900a036d11a308b1e..87ce003dfeca975d8e6af26fd341f3ab world.removeBlock(pos, false); return; } -@@ -69,7 +69,7 @@ public class IceBlock extends HalfTransparentBlock { +@@ -70,7 +70,7 @@ public class IceBlock extends HalfTransparentBlock { return; } // CraftBukkit end @@ -15438,10 +15432,10 @@ index 784b19bc78c8ad9476b6dac37b6778a409a7c675..d49dd8b20d3785cc9482ed2a34fbd7ae + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java -index 84623c632d8c2f0fa7ec939c711316d757117d23..1851035b9fdcc076442d0699567a3b020e6425d6 100644 +index a2d023ff011f71f80032f02430a53d6a08a23623..399441dd8388dcdec08768665d3cfa189aca0a95 100644 --- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java +++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java -@@ -137,7 +137,7 @@ public class LiquidBlock extends Block implements BucketPickup { +@@ -140,7 +140,7 @@ public class LiquidBlock extends Block implements BucketPickup { @Override protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { @@ -15450,29 +15444,29 @@ index 84623c632d8c2f0fa7ec939c711316d757117d23..1851035b9fdcc076442d0699567a3b02 world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper - Configurable speed for water flowing over lava } -@@ -165,7 +165,7 @@ public class LiquidBlock extends Block implements BucketPickup { +@@ -168,7 +168,7 @@ public class LiquidBlock extends Block implements BucketPickup { @Override - protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { + protected BlockState updateShape(BlockState state, LevelReader world, ScheduledTickAccess tickView, BlockPos pos, Direction direction, BlockPos neighborPos, BlockState neighborState, RandomSource random) { - if (state.getFluidState().isSource() || neighborState.getFluidState().isSource()) { -+ if (world.getMinecraftWorld().purpurConfig.tickFluids && state.getFluidState().isSource() || neighborState.getFluidState().isSource()) { // Purpur - world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world)); ++ if (world.getWorldBorder().world.purpurConfig.tickFluids && state.getFluidState().isSource() || neighborState.getFluidState().isSource()) { // Purpur + tickView.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world)); } -@@ -174,7 +174,7 @@ public class LiquidBlock extends Block implements BucketPickup { +@@ -177,7 +177,7 @@ public class LiquidBlock extends Block implements BucketPickup { @Override - protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) { + protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, @Nullable Orientation wireOrientation, boolean notify) { - if (this.shouldSpreadLiquid(world, pos, state)) { + if (world.purpurConfig.tickFluids && this.shouldSpreadLiquid(world, pos, state)) { // Purpur world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper - Configurable speed for water flowing over lava } diff --git a/src/main/java/net/minecraft/world/level/block/MagmaBlock.java b/src/main/java/net/minecraft/world/level/block/MagmaBlock.java -index 02d59789c09f58045fea302ea6f2ee3856114de3..8072713da7ed8b7a44b63c241050c3a9c16d7b27 100644 +index 7ffdcf18bf4bd8b5325c76945b2d80ca3fe52958..dfa931316fde0b2e80068a0edd1427ffd096b15b 100644 --- a/src/main/java/net/minecraft/world/level/block/MagmaBlock.java +++ b/src/main/java/net/minecraft/world/level/block/MagmaBlock.java -@@ -28,7 +28,7 @@ public class MagmaBlock extends Block { +@@ -29,7 +29,7 @@ public class MagmaBlock extends Block { @Override public void stepOn(Level world, BlockPos pos, BlockState state, Entity entity) { @@ -15482,10 +15476,10 @@ index 02d59789c09f58045fea302ea6f2ee3856114de3..8072713da7ed8b7a44b63c241050c3a9 } diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -index 0fdbcab175b51a8b77646e0e4a267d987b133a35..d579132d1afd5c2edb9356c5601584bca2357f8f 100644 +index 2b31bf586c1c0bd393d2aa8d0b6635dd9f22f21c..02bcba52e28f757b59e2f384d5744834962870f0 100644 --- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -@@ -77,7 +77,7 @@ public class NetherPortalBlock extends Block implements Portal { +@@ -78,7 +78,7 @@ public class NetherPortalBlock extends Block implements Portal { @Override protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { @@ -15494,7 +15488,7 @@ index 0fdbcab175b51a8b77646e0e4a267d987b133a35..d579132d1afd5c2edb9356c5601584bc while (world.getBlockState(pos).is((Block) this)) { pos = pos.below(); } -@@ -109,6 +109,13 @@ public class NetherPortalBlock extends Block implements Portal { +@@ -117,6 +117,13 @@ public class NetherPortalBlock extends Block implements Portal { protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent if (entity.canUsePortal(false)) { @@ -15508,12 +15502,12 @@ index 0fdbcab175b51a8b77646e0e4a267d987b133a35..d579132d1afd5c2edb9356c5601584bc // CraftBukkit start - Entity in portal EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.NETHER); // Paper - add portal type world.getCraftServer().getPluginManager().callEvent(event); -@@ -122,7 +129,7 @@ public class NetherPortalBlock extends Block implements Portal { +@@ -130,7 +137,7 @@ public class NetherPortalBlock extends Block implements Portal { @Override public int getPortalTransitionTime(ServerLevel world, Entity entity) { if (entity instanceof Player entityhuman) { -- return Math.max(1, world.getGameRules().getInt(entityhuman.getAbilities().invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY)); -+ return Math.max(1, entityhuman.canPortalInstant ? 1 : world.getGameRules().getInt(entityhuman.getAbilities().invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY)); // Purpur +- return Math.max(0, world.getGameRules().getInt(entityhuman.getAbilities().invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY)); ++ return Math.max(0, entityhuman.canPortalInstant ? 1 : world.getGameRules().getInt(entityhuman.getAbilities().invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY)); // Purpur } else { return 0; } @@ -15564,10 +15558,10 @@ index acbd60a2f162fe0e254e36d0e8e7face3fc8a7b3..b8355ea1de26c4b6905f477fb4e110f1 + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/NoteBlock.java b/src/main/java/net/minecraft/world/level/block/NoteBlock.java -index 1d82cfe7af0dc42f88901fb0c44896771fdf8a93..43dd972b374daa1072608f3a68e812e7fb733a2b 100644 +index 6582db84c5307257f16c321453491cf24e40c9c7..f9015d4e478efeec8a796b7a897638f76064db20 100644 --- a/src/main/java/net/minecraft/world/level/block/NoteBlock.java +++ b/src/main/java/net/minecraft/world/level/block/NoteBlock.java -@@ -95,7 +95,7 @@ public class NoteBlock extends Block { +@@ -97,7 +97,7 @@ public class NoteBlock extends Block { } private void playNote(@Nullable Entity entity, BlockState state, Level world, BlockPos pos) { @@ -15577,22 +15571,22 @@ index 1d82cfe7af0dc42f88901fb0c44896771fdf8a93..43dd972b374daa1072608f3a68e812e7 // org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE)); // if (event.isCancelled()) { diff --git a/src/main/java/net/minecraft/world/level/block/ObserverBlock.java b/src/main/java/net/minecraft/world/level/block/ObserverBlock.java -index b38fbe5121f293f425d7673a6ce49b11d0ced0d9..2a74f42672b92393b52a61c27c5b8af77c8c6070 100644 +index 93ed9406c34804831b86d006dbd6087db9948f08..26cb9990b91991e0a2eadc2dcbbf229e2e88fb2d 100644 --- a/src/main/java/net/minecraft/world/level/block/ObserverBlock.java +++ b/src/main/java/net/minecraft/world/level/block/ObserverBlock.java -@@ -71,6 +71,7 @@ public class ObserverBlock extends DirectionalBlock { +@@ -75,6 +75,7 @@ public class ObserverBlock extends DirectionalBlock { @Override - protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { + protected BlockState updateShape(BlockState state, LevelReader world, ScheduledTickAccess tickView, BlockPos pos, Direction direction, BlockPos neighborPos, BlockState neighborState, RandomSource random) { if (state.getValue(ObserverBlock.FACING) == direction && !(Boolean) state.getValue(ObserverBlock.POWERED)) { -+ if (!world.getMinecraftWorld().purpurConfig.disableObserverClocks || !(neighborState.getBlock() instanceof ObserverBlock) || neighborState.getValue(ObserverBlock.FACING).getOpposite() != direction) // Purpur - this.startSignal(world, pos); ++ if (!world.getWorldBorder().world.purpurConfig.disableObserverClocks || !(neighborState.getBlock() instanceof ObserverBlock) || neighborState.getValue(ObserverBlock.FACING).getOpposite() != direction) // Purpur + this.startSignal(world, tickView, pos); } diff --git a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java -index a2bd54dae4b0460d200f6d5300194a7ef5a28830..bf189a171530abfc9bba5db5a305feb391f2cbee 100644 +index 53cea36ec931de89e0060613acf87beb51dc16ec..fd5489993dca0f940da69e9163f78e5c2e6ee063 100644 --- a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java +++ b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java -@@ -190,7 +190,7 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate +@@ -194,7 +194,7 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate @VisibleForTesting public static void maybeTransferFluid(BlockState state, ServerLevel world, BlockPos pos, float dripChance) { @@ -15601,7 +15595,7 @@ index a2bd54dae4b0460d200f6d5300194a7ef5a28830..bf189a171530abfc9bba5db5a305feb3 if (PointedDripstoneBlock.isStalactiteStartPos(state, world, pos)) { Optional optional = PointedDripstoneBlock.getFluidAboveStalactite(world, pos, state); -@@ -199,13 +199,13 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate +@@ -203,13 +203,13 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate float f1; if (fluidtype == Fluids.WATER) { @@ -15618,20 +15612,20 @@ index a2bd54dae4b0460d200f6d5300194a7ef5a28830..bf189a171530abfc9bba5db5a305feb3 if (dripChance < f1) { diff --git a/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java b/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java -index a6e6545402904141ffc6218a0158b0e9c67217c8..5eac1a54398dfa5571b98fb6eefca9d2bf9b2793 100644 +index 53f1a7ed6b4bd6e2d8460531226aabf249994c02..3760c3c9ab45d7152661edd5a48893e1b583fb95 100644 --- a/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java +++ b/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java -@@ -80,7 +80,7 @@ public class PowderSnowBlock extends Block implements BucketPickup { - if (!world.isClientSide) { +@@ -76,7 +76,7 @@ public class PowderSnowBlock extends Block implements BucketPickup { + if (world instanceof ServerLevel worldserver) { // CraftBukkit start - if (entity.isOnFire() && entity.mayInteract(world, pos)) { -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) { -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !((world.purpurConfig.powderSnowBypassMobGriefing || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) || entity instanceof Player))) { + if (entity.isOnFire() && entity.mayInteract(worldserver, pos)) { +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !((worldserver.purpurConfig.powderSnowBypassMobGriefing ^ worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) || entity instanceof Player))) { // Purpur return; } // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java b/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java -index 9603d8c84ff483030dc08e82d3579b89e5c1f6e9..8fc65c32a3c6e6842a76b36f45e1b1c23abbc480 100644 +index b763361a8f0f1b46093d5dd9afe8dba0cadf9c78..bd14c08defe8afc5ceca59d16a5b1dbad178f594 100644 --- a/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java +++ b/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java @@ -30,7 +30,7 @@ public class PoweredRailBlock extends BaseRailBlock { @@ -15644,10 +15638,10 @@ index 9603d8c84ff483030dc08e82d3579b89e5c1f6e9..8fc65c32a3c6e6842a76b36f45e1b1c2 } else { int j = pos.getX(); diff --git a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java -index 94d067e9eeee73183de25165d8c97043fe256103..00b6941951e1af9993f8f6da5425d31b8eaa85e4 100644 +index 9117c035d5a6ff114b028fad3380ceb1fc2b9691..2c5e394156dbf76107adb4913a094dfd4a598dd7 100644 --- a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java +++ b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java -@@ -150,7 +150,7 @@ public class RespawnAnchorBlock extends Block { +@@ -149,7 +149,7 @@ public class RespawnAnchorBlock extends Block { }; Vec3 vec3d = explodedPos.getCenter(); @@ -15657,10 +15651,10 @@ index 94d067e9eeee73183de25165d8c97043fe256103..00b6941951e1af9993f8f6da5425d31b public static boolean canSetSpawn(Level world) { diff --git a/src/main/java/net/minecraft/world/level/block/SculkShriekerBlock.java b/src/main/java/net/minecraft/world/level/block/SculkShriekerBlock.java -index b6b367492ebe2af3e63381bef935c6077f6ddb27..09f34c30d9a03751ed826b26375ac5aee778cce4 100644 +index 0e05bfef55dcacb50766bba8328ffeb8a5394c31..e00fcea07e74de647c26ff9eb32bc682738c15b7 100644 --- a/src/main/java/net/minecraft/world/level/block/SculkShriekerBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SculkShriekerBlock.java -@@ -134,7 +134,7 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo +@@ -135,7 +135,7 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo @Nullable @Override public BlockState getStateForPlacement(BlockPlaceContext ctx) { @@ -15670,10 +15664,10 @@ index b6b367492ebe2af3e63381bef935c6077f6ddb27..09f34c30d9a03751ed826b26375ac5ae @Override diff --git a/src/main/java/net/minecraft/world/level/block/SlabBlock.java b/src/main/java/net/minecraft/world/level/block/SlabBlock.java -index fa29eb15934b3dad171d27c21d99b2451cfe553b..ba4aa69425d796d306791ea193f9c6b21a065f0b 100644 +index 9274fd639c22e305dda567b303f9b01068adb52c..4433e432ea0ee8d11045b87e68dac3ed43e8cf82 100644 --- a/src/main/java/net/minecraft/world/level/block/SlabBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SlabBlock.java -@@ -138,4 +138,25 @@ public class SlabBlock extends Block implements SimpleWaterloggedBlock { +@@ -150,4 +150,25 @@ public class SlabBlock extends Block implements SimpleWaterloggedBlock { return false; } } @@ -15700,7 +15694,7 @@ index fa29eb15934b3dad171d27c21d99b2451cfe553b..ba4aa69425d796d306791ea193f9c6b2 + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/SnowLayerBlock.java b/src/main/java/net/minecraft/world/level/block/SnowLayerBlock.java -index 93e8e5107ac047c1f2579b4fe6b0a202edb695f6..f82d275aac7bf3949d3dcc412c7e39e115c69458 100644 +index 9908a0b5b1fec5f9de518a733f7abbbff7e1a9f9..0ad444cf7f798f63e9140a42c5d5d8cab0fcf14f 100644 --- a/src/main/java/net/minecraft/world/level/block/SnowLayerBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SnowLayerBlock.java @@ -88,6 +88,12 @@ public class SnowLayerBlock extends Block { @@ -15787,10 +15781,10 @@ index 4f190a40b8474aa06a92c8afcc06d0044120ff7b..80ee7a6f010cc838625674007a3ea908 int i = 15 + worldserver.random.nextInt(15) + worldserver.random.nextInt(15); diff --git a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java -index 902825ec9ea05f4418b45f56a008d73f217bd178..6fe44572e34ad3e3a1851e73138bd8b778eb7849 100644 +index 59cf905b1b5686f6f4f2bad94730ffa69d3a2834..4c5bc71fef307d13b640e534ace0b4411f6e97e2 100644 --- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java -@@ -58,7 +58,7 @@ public class SpongeBlock extends Block { +@@ -61,7 +61,7 @@ public class SpongeBlock extends Block { private boolean removeWaterBreadthFirstSearch(Level world, BlockPos pos) { BlockStateListPopulator blockList = new BlockStateListPopulator(world); // CraftBukkit - Use BlockStateListPopulator @@ -15799,7 +15793,7 @@ index 902825ec9ea05f4418b45f56a008d73f217bd178..6fe44572e34ad3e3a1851e73138bd8b7 Direction[] aenumdirection = SpongeBlock.ALL_DIRECTIONS; int i = aenumdirection.length; -@@ -77,7 +77,7 @@ public class SpongeBlock extends Block { +@@ -80,7 +80,7 @@ public class SpongeBlock extends Block { FluidState fluid = blockList.getFluidState(blockposition1); // CraftBukkit end @@ -15808,7 +15802,7 @@ index 902825ec9ea05f4418b45f56a008d73f217bd178..6fe44572e34ad3e3a1851e73138bd8b7 return false; } else { Block block = iblockdata.getBlock(); -@@ -92,6 +92,10 @@ public class SpongeBlock extends Block { +@@ -95,6 +95,10 @@ public class SpongeBlock extends Block { if (iblockdata.getBlock() instanceof LiquidBlock) { blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); // CraftBukkit @@ -15820,10 +15814,10 @@ index 902825ec9ea05f4418b45f56a008d73f217bd178..6fe44572e34ad3e3a1851e73138bd8b7 if (!iblockdata.is(Blocks.KELP) && !iblockdata.is(Blocks.KELP_PLANT) && !iblockdata.is(Blocks.SEAGRASS) && !iblockdata.is(Blocks.TALL_SEAGRASS)) { return false; diff --git a/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java b/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java -index 59fd521cd1e1101e2adce9830c43784e05abccdd..ff04b4ed1f4e2e6ca2286243d4faaa9b8edcc7cc 100644 +index e61644241f24b42bb4f702d3eef5b590b4d107c8..0bf6503819b02e5ba2c346d9d563a93f2946d89b 100644 --- a/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java +++ b/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java -@@ -97,4 +97,14 @@ public class StonecutterBlock extends Block { +@@ -98,4 +98,14 @@ public class StonecutterBlock extends Block { protected boolean isPathfindable(BlockState state, PathComputationType type) { return false; } @@ -15839,7 +15833,7 @@ index 59fd521cd1e1101e2adce9830c43784e05abccdd..ff04b4ed1f4e2e6ca2286243d4faaa9b + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java -index c48c622e92cedeaa46b929c7adfedec98dd5a3fb..6449b5c424443b5f0ee7e3fce803449418fbed2a 100644 +index 547ea09ed84595286c97c128b3b96f6d387ae25f..d0f8a13f27132257ece6dadf736c2dc6b1e5720e 100644 --- a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java @@ -20,7 +20,7 @@ import net.minecraft.world.level.material.FluidState; @@ -15887,10 +15881,10 @@ index c48c622e92cedeaa46b929c7adfedec98dd5a3fb..6449b5c424443b5f0ee7e3fce8034494 + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java -index a6f408e56fa6c9de82fd93555fe21e1b11ce1022..08ba90f760abb9fb62311dddd7b5bdbd0d9518d7 100644 +index 953ddb2ea6fd48e57712e30a6addf23e188e5312..f1dfb23160ff70e0da4dd2af2d83e879527c6651 100644 --- a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java +++ b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java -@@ -170,7 +170,7 @@ public class TurtleEggBlock extends Block { +@@ -171,7 +171,7 @@ public class TurtleEggBlock extends Block { private boolean shouldUpdateHatchLevel(Level world) { float f = world.getTimeOfDay(1.0F); @@ -15899,10 +15893,10 @@ index a6f408e56fa6c9de82fd93555fe21e1b11ce1022..08ba90f760abb9fb62311dddd7b5bdbd } @Override -@@ -203,6 +203,31 @@ public class TurtleEggBlock extends Block { +@@ -204,6 +204,31 @@ public class TurtleEggBlock extends Block { } - private boolean canDestroyEgg(Level world, Entity entity) { + private boolean canDestroyEgg(ServerLevel world, Entity entity) { - return !(entity instanceof Turtle) && !(entity instanceof Bat) ? (!(entity instanceof LivingEntity) ? false : entity instanceof Player || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) : false; + // Purpur start + if (entity instanceof Turtle || entity instanceof Bat) { @@ -15928,7 +15922,7 @@ index a6f408e56fa6c9de82fd93555fe21e1b11ce1022..08ba90f760abb9fb62311dddd7b5bdbd + return true; + } + -+ return world.purpurConfig.turtleEggsBypassMobGriefing || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ return world.purpurConfig.turtleEggsBypassMobGriefing ^ world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); + // Purpur end } } @@ -15965,10 +15959,10 @@ index 3dec5a082606ee35a8c8d7f746480262d6a189c5..b2f6ccae9576c176263e51a232e17a08 + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/WitherSkullBlock.java b/src/main/java/net/minecraft/world/level/block/WitherSkullBlock.java -index bbf59b2577812e74ffd45f694b83a42e043273c0..5cb06959aeaceeb98cfee34b1df804e6642f305f 100644 +index 0fbe66cc02bd3d95c0a5dcd55380a1b4a2f17ca6..3a7126883f11ac5a647947eaf060df15536a6cb2 100644 --- a/src/main/java/net/minecraft/world/level/block/WitherSkullBlock.java +++ b/src/main/java/net/minecraft/world/level/block/WitherSkullBlock.java -@@ -79,6 +79,7 @@ public class WitherSkullBlock extends SkullBlock { +@@ -80,6 +80,7 @@ public class WitherSkullBlock extends SkullBlock { entitywither.moveTo((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.55D, (double) blockposition1.getZ() + 0.5D, shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F, 0.0F); entitywither.yBodyRot = shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F; entitywither.makeInvulnerable(); @@ -15977,33 +15971,10 @@ index bbf59b2577812e74ffd45f694b83a42e043273c0..5cb06959aeaceeb98cfee34b1df804e6 if (!world.addFreshEntity(entitywither, SpawnReason.BUILD_WITHER)) { return; diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 0d5c124ceffc5024240afa48cf900954977a1baf..cce1606a27ed3ac381b53e406caeb5a02c4b8965 100644 +index 43899f544cc22666f9ca496128650ce7751ec913..9cba9ebcaa3935778865e3af5211e0b0796cbe16 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -213,6 +213,22 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit - } - } - -+ // Purpur start -+ public static void addFuel(ItemStack itemStack, Integer burnTime) { -+ Map map = Maps.newLinkedHashMap(); -+ map.putAll(getFuel()); -+ map.put(itemStack.getItem(), burnTime); -+ AbstractFurnaceBlockEntity.fuelCache = com.google.common.collect.ImmutableMap.copyOf(map); -+ } -+ -+ public static void removeFuel(ItemStack itemStack) { -+ Map map = Maps.newLinkedHashMap(); -+ map.putAll(getFuel()); -+ map.remove(itemStack.getItem()); -+ AbstractFurnaceBlockEntity.fuelCache = com.google.common.collect.ImmutableMap.copyOf(map); -+ } -+ // Purpur End -+ - // CraftBukkit start - add fields and methods - private int maxStack = MAX_STACK; - public List transaction = new java.util.ArrayList(); -@@ -335,6 +351,21 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -219,6 +219,21 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit } ItemStack itemstack = (ItemStack) blockEntity.items.get(1); @@ -16025,16 +15996,16 @@ index 0d5c124ceffc5024240afa48cf900954977a1baf..cce1606a27ed3ac381b53e406caeb5a0 ItemStack itemstack1 = (ItemStack) blockEntity.items.get(0); boolean flag2 = !itemstack1.isEmpty(); boolean flag3 = !itemstack.isEmpty(); -@@ -421,6 +452,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -308,6 +323,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit setChanged(world, pos, state); } + if (usedLavaFromUnderneath) blockEntity.items.set(1, ItemStack.EMPTY); // Purpur } - private static boolean canBurn(RegistryAccess registryManager, @Nullable RecipeHolder recipe, NonNullList slots, int count) { + private static boolean canBurn(RegistryAccess dynamicRegistryManager, @Nullable RecipeHolder recipe, SingleRecipeInput input, NonNullList inventory, int maxCount) { diff --git a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -index 6186e55014bbb9d5bedaa0e9d196879c55339d42..f4f11292d6d00f4a7c65e3e2a157bba595f70889 100644 +index 618552afbdacc919c33b30a6bf4834fb71ab3d5b..7a059d20abdcc0073a314311d78f63ae4bd0365e 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java @@ -68,7 +68,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { @@ -16092,7 +16063,7 @@ index 6186e55014bbb9d5bedaa0e9d196879c55339d42..f4f11292d6d00f4a7c65e3e2a157bba5 @Override diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index 814e70f558d7a6186233da0ff86c94c95d390e09..df02a78855f1d0c32d1f744c20803fc97a8085c0 100644 +index 0e0d178f2793ab014358f534c8dc53218b89f083..2d190b3a6378b8cbadfa65510df1ccfbd5882ef8 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java @@ -92,6 +92,16 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name @@ -16127,7 +16098,7 @@ index 814e70f558d7a6186233da0ff86c94c95d390e09..df02a78855f1d0c32d1f744c20803fc9 + if (world.purpurConfig.beaconAllowEffectsWithTintedGlass && block.equals(Blocks.TINTED_GLASS)) { + isTintedGlass = true; + } - if (tileentitybeacon_beaconcolortracker == null || iblockdata1.getLightBlock(world, blockposition1) >= 15 && !iblockdata1.is(Blocks.BEDROCK)) { + if (tileentitybeacon_beaconcolortracker == null || iblockdata1.getLightBlock() >= 15 && !iblockdata1.is(Blocks.BEDROCK)) { blockEntity.checkingBeamSections.clear(); blockEntity.lastCheckY = l; @@ -220,7 +234,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name @@ -16140,10 +16111,10 @@ index 814e70f558d7a6186233da0ff86c94c95d390e09..df02a78855f1d0c32d1f744c20803fc9 BeaconBlockEntity.playSound(world, pos, SoundEvents.BEACON_AMBIENT); } diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -index f933fa419a4b55b0096ff42caf1b071d027b8e7e..a9cff34c85e1907bcbca2b051289781484580a15 100644 +index 83ad45aed0894e90825d22e078632352c3a06816..def408384cbd571b7bee23f5cecf430a5d690c4b 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -@@ -59,7 +59,7 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -60,7 +60,7 @@ public class BeehiveBlockEntity extends BlockEntity { private List stored = Lists.newArrayList(); @Nullable public BlockPos savedFlowerPos; @@ -16152,7 +16123,7 @@ index f933fa419a4b55b0096ff42caf1b071d027b8e7e..a9cff34c85e1907bcbca2b0512897814 public BeehiveBlockEntity(BlockPos pos, BlockState state) { super(BlockEntityType.BEEHIVE, pos, state); -@@ -146,11 +146,33 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -147,11 +147,33 @@ public class BeehiveBlockEntity extends BlockEntity { return list; } @@ -16186,16 +16157,7 @@ index f933fa419a4b55b0096ff42caf1b071d027b8e7e..a9cff34c85e1907bcbca2b0512897814 // Paper start - Add EntityBlockStorage clearEntities public void clearBees() { this.stored.clear(); -@@ -212,7 +234,7 @@ public class BeehiveBlockEntity extends BlockEntity { - } - - private static boolean releaseOccupant(Level world, BlockPos blockposition, BlockState iblockdata, BeehiveBlockEntity.Occupant tileentitybeehive_c, @Nullable List list, BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus, @Nullable BlockPos blockposition1, boolean force) { -- if (!force && (world.isNight() || world.isRaining()) && tileentitybeehive_releasestatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) { -+ if (!force && ((world.isNight() && !world.purpurConfig.beeCanWorkAtNight) || (world.isRaining() && !world.purpurConfig.beeCanWorkInRain)) && tileentitybeehive_releasestatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) { // Purpur - // CraftBukkit end - return false; - } else { -@@ -471,9 +493,9 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -472,9 +494,9 @@ public class BeehiveBlockEntity extends BlockEntity { } } @@ -16208,10 +16170,10 @@ index f933fa419a4b55b0096ff42caf1b071d027b8e7e..a9cff34c85e1907bcbca2b0512897814 private int ticksInHive; diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 7dfabb11d3c8112f6daef35d204a2e324f4ddb5e..a7b6c20afd9ec3fe61d2bdf42f96398c8d6751cc 100644 +index 1f929b467a0ece3143af58a657cf5983c07a8d51..eaa6ece956f90632831f0558924eaf18680a252b 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -100,6 +100,12 @@ public abstract class BlockEntity { +@@ -95,6 +95,12 @@ public abstract class BlockEntity { if (persistentDataTag instanceof CompoundTag) { this.persistentDataContainer.putAll((CompoundTag) persistentDataTag); } @@ -16224,8 +16186,8 @@ index 7dfabb11d3c8112f6daef35d204a2e324f4ddb5e..a7b6c20afd9ec3fe61d2bdf42f96398c } // CraftBukkit end -@@ -116,6 +122,15 @@ public abstract class BlockEntity { - this.loadAdditional(nbt, registryLookup); +@@ -111,6 +117,15 @@ public abstract class BlockEntity { + this.loadAdditional(nbt, registries); } + // Purpur start @@ -16237,10 +16199,10 @@ index 7dfabb11d3c8112f6daef35d204a2e324f4ddb5e..a7b6c20afd9ec3fe61d2bdf42f96398c + } + // Purpur end + - protected void saveAdditional(CompoundTag nbt, HolderLookup.Provider registryLookup) {} + protected void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) {} - public final CompoundTag saveWithFullMetadata(HolderLookup.Provider registryLookup) { -@@ -423,4 +438,16 @@ public abstract class BlockEntity { + public final CompoundTag saveWithFullMetadata(HolderLookup.Provider registries) { +@@ -419,4 +434,16 @@ public abstract class BlockEntity { T getOrDefault(DataComponentType type, T fallback); } @@ -16258,10 +16220,10 @@ index 7dfabb11d3c8112f6daef35d204a2e324f4ddb5e..a7b6c20afd9ec3fe61d2bdf42f96398c + // Purpur end } diff --git a/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java -index 73e532dc998e5701c1a73da846da3d3a79871b81..ff6fea842ca80c2ba51693fe62e5b74f9affdc19 100644 +index d354c2ad41533ec8d52f7c5f63f8f74a0b1ce235..a43c41a26c1e34a2f4eda1c498a562664a783c77 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java -@@ -168,7 +168,7 @@ public class ConduitBlockEntity extends BlockEntity { +@@ -169,7 +169,7 @@ public class ConduitBlockEntity extends BlockEntity { if ((l > 1 || i1 > 1 || j1 > 1) && (i == 0 && (i1 == 2 || j1 == 2) || j == 0 && (l == 2 || j1 == 2) || k == 0 && (l == 2 || i1 == 2))) { BlockPos blockposition2 = pos.offset(i, j, k); BlockState iblockdata = world.getBlockState(blockposition2); @@ -16270,7 +16232,7 @@ index 73e532dc998e5701c1a73da846da3d3a79871b81..ff6fea842ca80c2ba51693fe62e5b74f int k1 = ablock.length; for (int l1 = 0; l1 < k1; ++l1) { -@@ -188,13 +188,13 @@ public class ConduitBlockEntity extends BlockEntity { +@@ -189,13 +189,13 @@ public class ConduitBlockEntity extends BlockEntity { private static void applyEffects(Level world, BlockPos pos, List activatingBlocks) { // CraftBukkit start @@ -16287,7 +16249,7 @@ index 73e532dc998e5701c1a73da846da3d3a79871b81..ff6fea842ca80c2ba51693fe62e5b74f // CraftBukkit start return j; } -@@ -237,20 +237,20 @@ public class ConduitBlockEntity extends BlockEntity { +@@ -238,20 +238,20 @@ public class ConduitBlockEntity extends BlockEntity { tileentityconduit.destroyTarget = ConduitBlockEntity.findDestroyTarget(world, blockposition, tileentityconduit.destroyTargetUUID); tileentityconduit.destroyTargetUUID = null; } else if (tileentityconduit.destroyTarget == null) { @@ -16306,12 +16268,12 @@ index 73e532dc998e5701c1a73da846da3d3a79871b81..ff6fea842ca80c2ba51693fe62e5b74f // CraftBukkit start if (damageTarget && tileentityconduit.destroyTarget != null) { -- if (tileentityconduit.destroyTarget.hurt(world.damageSources().magic().directBlock(world, blockposition), 4.0F)) { -+ if (tileentityconduit.destroyTarget.hurt(world.damageSources().magic().directBlock(world, blockposition), world.purpurConfig.conduitDamageAmount)) { // Purpur +- if (tileentityconduit.destroyTarget.hurtServer((ServerLevel) world, world.damageSources().magic().directBlock(world, blockposition), 4.0F)) { ++ if (tileentityconduit.destroyTarget.hurtServer((ServerLevel) world, world.damageSources().magic().directBlock(world, blockposition), world.purpurConfig.conduitDamageAmount)) { // Purpur world.playSound(null, tileentityconduit.destroyTarget.getX(), tileentityconduit.destroyTarget.getY(), tileentityconduit.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F); } // CraftBukkit end -@@ -275,16 +275,22 @@ public class ConduitBlockEntity extends BlockEntity { +@@ -276,16 +276,22 @@ public class ConduitBlockEntity extends BlockEntity { } public static AABB getDestroyRangeAABB(BlockPos pos) { @@ -16337,7 +16299,7 @@ index 73e532dc998e5701c1a73da846da3d3a79871b81..ff6fea842ca80c2ba51693fe62e5b74f }); diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java -index d47bc2f54c4722a0b8c419b99ee57eb3cb25d750..fdeabdcc781b605d6f3ee18528fd380ffff95660 100644 +index 39aac959775afeaeea211f21d498cb0ddf0a3fcb..6349a342c023f378af431a73a62fb017882e257d 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/EnchantingTableBlockEntity.java @@ -28,6 +28,7 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable @@ -16350,7 +16312,7 @@ index d47bc2f54c4722a0b8c419b99ee57eb3cb25d750..fdeabdcc781b605d6f3ee18528fd380f super(BlockEntityType.ENCHANTING_TABLE, pos, state); @@ -39,6 +40,7 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable if (this.hasCustomName()) { - nbt.putString("CustomName", Component.Serializer.toJson(this.name, registryLookup)); + nbt.putString("CustomName", Component.Serializer.toJson(this.name, registries)); } + nbt.putInt("Purpur.Lapis", this.lapis); // Purpur } @@ -16358,7 +16320,7 @@ index d47bc2f54c4722a0b8c419b99ee57eb3cb25d750..fdeabdcc781b605d6f3ee18528fd380f @Override @@ -47,6 +49,7 @@ public class EnchantingTableBlockEntity extends BlockEntity implements Nameable if (nbt.contains("CustomName", 8)) { - this.name = parseCustomNameSafe(nbt.getString("CustomName"), registryLookup); + this.name = parseCustomNameSafe(nbt.getString("CustomName"), registries); } + this.lapis = nbt.getInt("Purpur.Lapis"); // Purpur } @@ -16379,11 +16341,24 @@ index d47bc2f54c4722a0b8c419b99ee57eb3cb25d750..fdeabdcc781b605d6f3ee18528fd380f + } + // Purpur } +diff --git a/src/main/java/net/minecraft/world/level/block/entity/FuelValues.java b/src/main/java/net/minecraft/world/level/block/entity/FuelValues.java +index 61ef08ac941b1e8988d001241780d3a1582f7a2d..2eab5b43ab654966d26424597c1f3baa919e8434 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/FuelValues.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/FuelValues.java +@@ -17,7 +17,7 @@ import net.minecraft.world.level.ItemLike; + import net.minecraft.world.level.block.Blocks; + + public class FuelValues { +- private final Object2IntSortedMap values; ++ public final Object2IntSortedMap values; // Purpur - private -> public + + FuelValues(Object2IntSortedMap fuelValues) { + this.values = fuelValues; diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -index 3070cd2b588f5a69fd8c0d3551e16251680d8c27..c9a1c071780351b584ad8e071ddc26f9a27e5964 100644 +index 8ac19e1e052e73ff3fd09089bb8e3fd687390ee4..6da1eec98c08e4909ecbd48fe90b3fd62011e284 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java -@@ -201,16 +201,31 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C +@@ -201,16 +201,31 @@ public class SignBlockEntity extends BlockEntity { return this.setText((SignText) textChanger.apply(signtext), front); } @@ -16417,7 +16392,7 @@ index 3070cd2b588f5a69fd8c0d3551e16251680d8c27..c9a1c071780351b584ad8e071ddc26f9 } } -@@ -345,6 +360,28 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C +@@ -348,6 +363,28 @@ public class SignBlockEntity extends BlockEntity { return new CommandSourceStack(commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel) world, 2, s, (Component) object, world.getServer(), player); // Paper - Fix commands from signs not firing command events } @@ -16478,10 +16453,10 @@ index 205e223c356634bd6bc6bd58c6f0b7fda61a6f5f..bea05cb928d540a2f19b51bb7352d032 } diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -index d0109633e8bdf109cfc9178963d7b6cf92f8b189..40f15a30b1a0dd2040e75045f32f33082e70aaeb 100644 +index 5b6fbfd1a7a2d87fb2b87d5d1e674206cdf9b280..dcf2dcece3e995ce4646b931329246be19a4e1c2 100644 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -86,7 +86,7 @@ public abstract class BlockBehaviour implements FeatureElement { +@@ -91,7 +91,7 @@ public abstract class BlockBehaviour implements FeatureElement { protected static final Direction[] UPDATE_SHAPE_ORDER = new Direction[]{Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH, Direction.DOWN, Direction.UP}; public final boolean hasCollision; @@ -16490,20 +16465,20 @@ index d0109633e8bdf109cfc9178963d7b6cf92f8b189..40f15a30b1a0dd2040e75045f32f3308 protected final boolean isRandomlyTicking; protected final SoundType soundType; protected final float friction; -@@ -94,7 +94,7 @@ public abstract class BlockBehaviour implements FeatureElement { +@@ -99,7 +99,7 @@ public abstract class BlockBehaviour implements FeatureElement { protected final float jumpFactor; protected final boolean dynamicShape; protected final FeatureFlagSet requiredFeatures; - protected final BlockBehaviour.Properties properties; + public final BlockBehaviour.Properties properties; // Purpur - protected -> public - @Nullable - protected ResourceKey drops; + protected final Optional> drops; + protected final String descriptionId; diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java -index d4a505ef4af9ded02aeb1a817bcbe5b1a912a5b3..97a310f042db1a838a744d2909d261aaf253ea17 100644 +index 356d010506fd21f3c752e4aa86c46c1106fdde3b..86e16dd6b905af31795fda8002f2e1f857ddcb9f 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java -@@ -105,6 +105,7 @@ public class EntityStorage implements EntityPersistentStorage { +@@ -106,6 +106,7 @@ public class EntityStorage implements EntityPersistentStorage { } // Paper end - Entity load/save limit per chunk CompoundTag compoundTagx = new CompoundTag(); @@ -16512,7 +16487,7 @@ index d4a505ef4af9ded02aeb1a817bcbe5b1a912a5b3..97a310f042db1a838a744d2909d261aa listTag.add(compoundTagx); } diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java -index ae1e164285f5675371bf036c8a564d9f5c1dd395..976ac286b4a6b8a843d275583dacb4ca2b0c4cb2 100644 +index 997f80d332b95bb011cbbc27c065b2811a2dddc7..d9a1ad945504d26a2c0717e40782f2859a4b2e9b 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java @@ -48,7 +48,7 @@ public class PhantomSpawner implements CustomSpawner { @@ -16547,21 +16522,21 @@ index ae1e164285f5675371bf036c8a564d9f5c1dd395..976ac286b4a6b8a843d275583dacb4ca for (int l = 0; l < k; ++l) { // Paper start - PhantomPreSpawnEvent diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -index 1c0712295695727ee9c4d430d4157b8e17cbd71f..3b197331f51b12b55a40f2abb6ce99ef0fb65f17 100644 +index 221978c64cf6171db078c6cbfc850f6aeae73884..408e7c61d87a0e6d8502bf1f5ca76fd728c5d10c 100644 --- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java +++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -@@ -217,7 +217,7 @@ public abstract class FlowingFluid extends Fluid { +@@ -266,7 +266,7 @@ public abstract class FlowingFluid extends Fluid { } } -- if (this.canConvertToSource(world) && j >= 2) { -+ if (this.canConvertToSource(world) && j >= getRequiredSources(world)) { - BlockState iblockdata2 = world.getBlockState(pos.below()); +- if (j >= 2 && this.canConvertToSource(world)) { ++ if (j >= getRequiredSources(world) && this.canConvertToSource(world)) { // Purpur + BlockState iblockdata2 = world.getBlockState(blockposition_mutableblockposition.setWithOffset(pos, Direction.DOWN)); FluidState fluid1 = iblockdata2.getFluidState(); -@@ -290,6 +290,12 @@ public abstract class FlowingFluid extends Fluid { +@@ -356,6 +356,12 @@ public abstract class FlowingFluid extends Fluid { - protected abstract boolean canConvertToSource(Level world); + protected abstract boolean canConvertToSource(ServerLevel world); + // Purpur start + protected int getRequiredSources(Level level) { @@ -16570,13 +16545,13 @@ index 1c0712295695727ee9c4d430d4157b8e17cbd71f..3b197331f51b12b55a40f2abb6ce99ef + // Purpur end + protected void spreadTo(LevelAccessor world, BlockPos pos, BlockState state, Direction direction, FluidState fluidState) { - if (state.getBlock() instanceof LiquidBlockContainer) { - ((LiquidBlockContainer) state.getBlock()).placeLiquid(world, pos, state, fluidState); + Block block = state.getBlock(); + diff --git a/src/main/java/net/minecraft/world/level/material/LavaFluid.java b/src/main/java/net/minecraft/world/level/material/LavaFluid.java -index 3bb4a9a1a6249e8ba2de237f801210e7f4fd5825..2d492d849ff73a738dfbcb16507feb89bf19a962 100644 +index 884db3e64cb22ed765beec8f11ea309fcf810207..6e643c1a7f7e71cfd20603facaf224985ee81716 100644 --- a/src/main/java/net/minecraft/world/level/material/LavaFluid.java +++ b/src/main/java/net/minecraft/world/level/material/LavaFluid.java -@@ -180,7 +180,7 @@ public abstract class LavaFluid extends FlowingFluid { +@@ -181,7 +181,7 @@ public abstract class LavaFluid extends FlowingFluid { @Override public int getTickDelay(LevelReader world) { @@ -16585,7 +16560,7 @@ index 3bb4a9a1a6249e8ba2de237f801210e7f4fd5825..2d492d849ff73a738dfbcb16507feb89 } @Override -@@ -198,6 +198,13 @@ public abstract class LavaFluid extends FlowingFluid { +@@ -199,6 +199,13 @@ public abstract class LavaFluid extends FlowingFluid { world.levelEvent(1501, pos, 0); } @@ -16597,13 +16572,13 @@ index 3bb4a9a1a6249e8ba2de237f801210e7f4fd5825..2d492d849ff73a738dfbcb16507feb89 + // Purpur end + @Override - protected boolean canConvertToSource(Level world) { + protected boolean canConvertToSource(ServerLevel world) { return world.getGameRules().getBoolean(GameRules.RULE_LAVA_SOURCE_CONVERSION); diff --git a/src/main/java/net/minecraft/world/level/material/WaterFluid.java b/src/main/java/net/minecraft/world/level/material/WaterFluid.java -index 109f71401c65f476ccf6813137386fc9fef10254..9dcdb2f4001115db0c26fdbf86531dbe6098485d 100644 +index 552925ba47c7475e2e1ec2ded0966f28ed3e50a5..1e741f36b79585f33abe413beafe00cf5205d54f 100644 --- a/src/main/java/net/minecraft/world/level/material/WaterFluid.java +++ b/src/main/java/net/minecraft/world/level/material/WaterFluid.java -@@ -80,6 +80,13 @@ public abstract class WaterFluid extends FlowingFluid { +@@ -81,6 +81,13 @@ public abstract class WaterFluid extends FlowingFluid { return world.getGameRules().getBoolean(GameRules.RULE_WATER_SOURCE_CONVERSION); } @@ -16618,7 +16593,7 @@ index 109f71401c65f476ccf6813137386fc9fef10254..9dcdb2f4001115db0c26fdbf86531dbe @Override protected void beforeDestroyingBlock(LevelAccessor world, BlockPos pos, BlockState state, BlockPos source) { diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java -index d5004290e40a1ff5e0fcfe75f8da34ae15962359..f26383cf896785333dbd6f86348d5a5f67a6731f 100644 +index c84fd369d92932903c76bb2012602617d3e2d213..224896124706764412033c8726c822e116f2c0f1 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java @@ -240,7 +240,7 @@ public class WalkNodeEvaluator extends NodeEvaluator { @@ -16640,10 +16615,10 @@ index d5004290e40a1ff5e0fcfe75f8da34ae15962359..f26383cf896785333dbd6f86348d5a5f } else if (blockState.is(Blocks.HONEY_BLOCK)) { return PathType.STICKY_HONEY; diff --git a/src/main/java/net/minecraft/world/level/portal/PortalShape.java b/src/main/java/net/minecraft/world/level/portal/PortalShape.java -index 86d95edc7dd1e42b4b38eba1177cd508e72e4fc4..6c07fc507df6070854f5950a8616d2949c040656 100644 +index 90056822cd17f3d33d14b3f94b34750ee522a0a9..acdff7b4a00d563739fd301c3633a266875296fa 100644 --- a/src/main/java/net/minecraft/world/level/portal/PortalShape.java +++ b/src/main/java/net/minecraft/world/level/portal/PortalShape.java -@@ -31,7 +31,7 @@ public class PortalShape { +@@ -35,7 +35,7 @@ public class PortalShape { private static final int MIN_HEIGHT = 3; public static final int MAX_HEIGHT = 21; private static final BlockBehaviour.StatePredicate FRAME = (iblockdata, iblockaccess, blockposition) -> { @@ -16653,10 +16628,10 @@ index 86d95edc7dd1e42b4b38eba1177cd508e72e4fc4..6c07fc507df6070854f5950a8616d294 private static final float SAFE_TRAVEL_MAX_ENTITY_XY = 4.0F; private static final double SAFE_TRAVEL_MAX_VERTICAL_DELTA = 1.0D; diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index 72d69cf3976abef064e2bf10455025536c67082f..b794c097039f6a3f812dd76df407587594d3ac49 100644 +index b15b0c8057e61c6aef05c0865e2c3e06adcf938b..aabc0b5a3e50aad8c4f902fa41e6bed319599ff3 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -@@ -80,6 +80,7 @@ public class MapItemSavedData extends SavedData { +@@ -81,6 +81,7 @@ public class MapItemSavedData extends SavedData { private final Map frameMarkers = Maps.newHashMap(); private int trackedDecorationCount; private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper @@ -16665,15 +16640,15 @@ index 72d69cf3976abef064e2bf10455025536c67082f..b794c097039f6a3f812dd76df4075875 // CraftBukkit start public final CraftMapView mapView; diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/EnchantedCountIncreaseFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/EnchantedCountIncreaseFunction.java -index d86189bd446c7cd7215cfbcef72b2125a064e3d1..53608b9dbb81c58819b9ae6bc676ffb3ed01ce70 100644 +index 5f27e1ce23f2ed68e4c8af1986fafce940dbf826..d8cf49cbd82ed12d23fa10a81a88cc4bcf1c0f10 100644 --- a/src/main/java/net/minecraft/world/level/storage/loot/functions/EnchantedCountIncreaseFunction.java +++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/EnchantedCountIncreaseFunction.java @@ -66,6 +66,11 @@ public class EnchantedCountIncreaseFunction extends LootItemConditionalFunction - Entity entity = context.getParamOrNull(LootContextParams.ATTACKING_ENTITY); + Entity entity = context.getOptionalParameter(LootContextParams.ATTACKING_ENTITY); if (entity instanceof LivingEntity livingEntity) { int i = EnchantmentHelper.getEnchantmentLevel(this.enchantment, livingEntity); + // Purpur start - Add an option to fix MC-3304 projectile looting -+ if (org.purpurmc.purpur.PurpurConfig.fixProjectileLootingTransfer && context.getParamOrNull(LootContextParams.DIRECT_ATTACKING_ENTITY) instanceof net.minecraft.world.entity.projectile.AbstractArrow arrow) { ++ if (org.purpurmc.purpur.PurpurConfig.fixProjectileLootingTransfer && context.getOptionalParameter(LootContextParams.DIRECT_ATTACKING_ENTITY) instanceof net.minecraft.world.entity.projectile.AbstractArrow arrow) { + i = arrow.actualEnchantments.getLevel(this.enchantment); + } + // Purpur end - Add an option to fix MC-3304 projectile looting @@ -16681,10 +16656,10 @@ index d86189bd446c7cd7215cfbcef72b2125a064e3d1..53608b9dbb81c58819b9ae6bc676ffb3 return stack; } diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java -index 29123f3a2f211c08d1a9ccf62ca9bc9822f90111..db78616676ba021ee0f03cfea932f2912f4ec987 100644 +index 6cf6d4ec7b9e43c7b2b4c0e2fb080964ff588130..e74866e5195a5eeae7666ad7be750edac5947094 100644 --- a/src/main/java/net/minecraft/world/phys/AABB.java +++ b/src/main/java/net/minecraft/world/phys/AABB.java -@@ -508,4 +508,10 @@ public class AABB { +@@ -551,4 +551,10 @@ public class AABB { public static AABB ofSize(Vec3 center, double dx, double dy, double dz) { return new AABB(center.x - dx / 2.0, center.y - dy / 2.0, center.z - dz / 2.0, center.x + dx / 2.0, center.y + dy / 2.0, center.z + dz / 2.0); } @@ -16934,10 +16909,10 @@ index 94ca0407303c4493ab4928b12ec6ecc75aaca549..a138e1b6b66d99f2035de054137a607a + // Purpur end - OfflinePlayer API } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index a28904a6d3bddad0057be4eea79cd404e855e19e..8049d77b8a01b4384016c3d22db9af95eaa5c2e8 100644 +index c11f638e120ae4989d110f55c4569dd67b6f3260..ef8041877456316fc32a382e28ee81161d962353 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -412,6 +412,20 @@ public final class CraftServer implements Server { +@@ -427,6 +427,20 @@ public final class CraftServer implements Server { this.paperPluginManager = new io.papermc.paper.plugin.manager.PaperPluginManagerImpl(this, this.commandMap, pluginManager); this.pluginManager.paperPluginManager = this.paperPluginManager; // Paper end @@ -16958,15 +16933,15 @@ index a28904a6d3bddad0057be4eea79cd404e855e19e..8049d77b8a01b4384016c3d22db9af95 CraftRegistry.setMinecraftRegistry(console.registryAccess()); -@@ -1074,6 +1088,7 @@ public final class CraftServer implements Server { +@@ -1088,6 +1102,7 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.init((File) this.console.options.valueOf("spigot-settings")); // Spigot this.console.paperConfigurations.reloadConfigs(this.console); this.console.galeConfigurations.reloadConfigs(this.console); // Gale - Gale configuration + org.purpurmc.purpur.PurpurConfig.init((File) console.options.valueOf("purpur-settings")); // Purpur for (ServerLevel world : this.console.getAllLevels()) { // world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty - world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters, config.spawnAnimals); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean)) -@@ -1089,6 +1104,7 @@ public final class CraftServer implements Server { + world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean)) +@@ -1103,6 +1118,7 @@ public final class CraftServer implements Server { } } world.spigotConfig.init(); // Spigot @@ -16974,7 +16949,7 @@ index a28904a6d3bddad0057be4eea79cd404e855e19e..8049d77b8a01b4384016c3d22db9af95 } Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper -@@ -1106,6 +1122,7 @@ public final class CraftServer implements Server { +@@ -1120,6 +1136,7 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.registerCommands(); // Spigot io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper this.spark.registerCommandBeforePlugins(this); // Paper - spark @@ -16982,7 +16957,7 @@ index a28904a6d3bddad0057be4eea79cd404e855e19e..8049d77b8a01b4384016c3d22db9af95 this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); -@@ -1616,6 +1633,55 @@ public final class CraftServer implements Server { +@@ -1632,6 +1649,58 @@ public final class CraftServer implements Server { return true; } @@ -16990,12 +16965,15 @@ index a28904a6d3bddad0057be4eea79cd404e855e19e..8049d77b8a01b4384016c3d22db9af95 + @Override + public void addFuel(org.bukkit.Material material, int burnTime) { + Preconditions.checkArgument(burnTime > 0, "BurnTime must be greater than 0"); -+ net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity.addFuel(net.minecraft.world.item.ItemStack.fromBukkitCopy(new ItemStack(material)), burnTime); ++ ++ net.minecraft.world.item.ItemStack itemStack = net.minecraft.world.item.ItemStack.fromBukkitCopy(new ItemStack(material)); ++ MinecraftServer.getServer().fuelValues().values.put(itemStack.getItem(), burnTime); + } + + @Override + public void removeFuel(org.bukkit.Material material) { -+ net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity.removeFuel(net.minecraft.world.item.ItemStack.fromBukkitCopy(new ItemStack(material))); ++ net.minecraft.world.item.ItemStack itemStack = net.minecraft.world.item.ItemStack.fromBukkitCopy(new ItemStack(material)); ++ MinecraftServer.getServer().fuelValues().values.keySet().removeIf(itemStack::is); + } + + @Override @@ -17038,7 +17016,7 @@ index a28904a6d3bddad0057be4eea79cd404e855e19e..8049d77b8a01b4384016c3d22db9af95 @Override public List getRecipesFor(ItemStack result) { Preconditions.checkArgument(result != null, "ItemStack cannot be null"); -@@ -3004,6 +3070,18 @@ public final class CraftServer implements Server { +@@ -3045,6 +3114,18 @@ public final class CraftServer implements Server { } // Gale end - Gale configuration - API @@ -17057,10 +17035,11 @@ index a28904a6d3bddad0057be4eea79cd404e855e19e..8049d77b8a01b4384016c3d22db9af95 @Override public void restart() { org.spigotmc.RestartCommand.restart(); -@@ -3286,4 +3364,15 @@ public final class CraftServer implements Server { +@@ -3338,4 +3419,16 @@ public final class CraftServer implements Server { + return MinecraftServer.lastTickOversleepTime; } // Gale end - YAPFA - last tick time - API - ++ + // Purpur start + @Override + public String getServerName() { @@ -17074,10 +17053,10 @@ index a28904a6d3bddad0057be4eea79cd404e855e19e..8049d77b8a01b4384016c3d22db9af95 + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 25aa3d0f9b44737059b567c802e33bd6261f2c8a..617c386290e525e2e81fe0e7b6d1f0b16ef8d109 100644 +index d39a0785f42c72d7b32af5c1c8067b2857f22a48..768ad742ff654a1e80c0d3746bc0ba503f350cd8 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -2386,6 +2386,48 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2384,6 +2384,48 @@ public class CraftWorld extends CraftRegionAccessor implements World { return (this.getHandle().getDragonFight() == null) ? null : new CraftDragonBattle(this.getHandle().getDragonFight()); } @@ -17127,7 +17106,7 @@ index 25aa3d0f9b44737059b567c802e33bd6261f2c8a..617c386290e525e2e81fe0e7b6d1f0b1 public Collection getStructures(int x, int z) { return this.getStructures(x, z, struct -> true); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index d9b4ab99ef6bf232b78ac162c3cf3a6b47a7bae2..284c500871e4f880da415a51979fe26b88a4744e 100644 +index 50a2b6e73ba4d8ad65582b2544fa409fd44f36d5..a7cc9af6979860d54c677a7d8d6c1589e97d4841 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -176,6 +176,14 @@ public class Main { @@ -17299,10 +17278,10 @@ index d657fd2c507a5b215aeab0a5f3e9c2ee892a27c8..985e9ec21c60a1f47973bd5fc53b96a6 // Paper start @Override diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..770606c4462d85d116f6d0bf91192dc49f438d0f 100644 +index ddabaed899c755925ad8618b78c33dacaf2126ac..51aee9a468f4ebfa9672fd9ce84883cf080859e3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -86,6 +86,23 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -87,6 +87,23 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { this.entityType = CraftEntityType.minecraftToBukkit(entity.getType()); } @@ -17326,7 +17305,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..770606c4462d85d116f6d0bf91192dc4 public static CraftEntity getEntity(CraftServer server, T entity) { Preconditions.checkArgument(entity != null, "Unknown entity"); -@@ -245,6 +262,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -246,6 +263,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { boolean ignorePassengers = flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS); // Don't allow teleporting between worlds while keeping passengers if (flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS) && this.entity.isVehicle() && location.getWorld() != this.getWorld()) { @@ -17334,7 +17313,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..770606c4462d85d116f6d0bf91192dc4 return false; } -@@ -1310,4 +1328,27 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1306,4 +1324,27 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } } // Paper end - broadcast hurt animation @@ -17363,7 +17342,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..770606c4462d85d116f6d0bf91192dc4 + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 7dcfb45c24d7743956be514c7d554e06aac77b3e..46856d2b7e24c5d223b7b1627ccb451749b183e7 100644 +index e345cdbfab44a0f5da80d738798dbb4424b7ab5c..856f12eb276c214f2f57a58a89a4da9eea34db2d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -273,6 +273,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -17453,10 +17432,10 @@ index 30d62ee4d5cd2ddacb8783b5bbbf475d592b3e02..5c1cda88080850314dac196dbe71ff12 + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 57b71a3894638253c6d24d4967a96768834bb02b..491c320d3745587757ddc9131a7585275e35d0c2 100644 +index d0c409f4efad289e3e325f44b500fc72589d89d4..051ffc663317fe5a4fafe0750c89fafdece4d316 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -514,7 +514,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -523,7 +523,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { net.minecraft.server.level.ServerPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle(); getHandle().lastHurtByPlayer = entityPlayer; getHandle().lastHurtByMob = entityPlayer; @@ -17465,7 +17444,7 @@ index 57b71a3894638253c6d24d4967a96768834bb02b..491c320d3745587757ddc9131a758527 } // Paper end -@@ -1192,4 +1192,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -1211,4 +1211,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { return this.getHandle().canUseSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); } // Paper end - Expose canUseSlot @@ -17504,10 +17483,10 @@ index 351f42842b780d053cd2e5bad9ae299449141b10..4860574e7fad7a9527dda599703c573c + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 42d7660efe5baa6f796f2a7606686c765b6f2478..173e4a075078af67f030750c9a6294ab3f796677 100644 +index d4e497961578bb693275cdf95915b60b2cc76eb7..63065a22ff359c142bab23fccacfd5ebd86f81a5 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -578,10 +578,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -583,10 +583,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setPlayerListName(String name) { @@ -17540,7 +17519,7 @@ index 42d7660efe5baa6f796f2a7606686c765b6f2478..173e4a075078af67f030750c9a6294ab return false; } -@@ -2757,6 +2764,28 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2769,6 +2776,28 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this.getHandle().getAbilities().walkingSpeed * 2f; } @@ -17569,7 +17548,7 @@ index 42d7660efe5baa6f796f2a7606686c765b6f2478..173e4a075078af67f030750c9a6294ab private void validateSpeed(float value) { Preconditions.checkArgument(value <= 1f && value >= -1f, "Speed value (%s) need to be between -1f and 1f", value); } -@@ -3568,4 +3597,70 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3580,4 +3609,70 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundEntityEventPacket(((CraftEntity) target).getHandle(), effect.getData())); } // Paper end - entity effect API @@ -17663,10 +17642,10 @@ index 4ce2373ff71c3c1b8951646e057587a3ab09e145..4f7f6cf6ca24406570d2d29dc63dc894 + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index bd2987fa1fb194a581567134ed980e8fc043f435..bdd345595ed71a8018349e184afe8582a24f3622 100644 +index 8e895d6f84f7d84b219f2424909dd42e5f08dec4..53dcce0701d713c5dd097340a91b8be4806de4b8 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -374,4 +374,11 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { +@@ -375,4 +375,11 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { getHandle().getGossips().gossips.clear(); } // Paper end @@ -17701,7 +17680,7 @@ index 7881c6253c1d652c0c0d54a9a8accdf0a1ff0f3e..da6ccb2a38df76770821a1a2203e54e7 + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java -index 86574da257731de7646a712ed73384955fe35aa3..e223234dd64b0e41441c3b9f649f0b64dc6d98c4 100644 +index ecd33b4add46acbe4e4f8879c0601220423d66ca..1506a8c0fa490726eb4a4ae14f3aa194dc81d9ab 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java @@ -146,4 +146,16 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf { @@ -17722,10 +17701,10 @@ index 86574da257731de7646a712ed73384955fe35aa3..e223234dd64b0e41441c3b9f649f0b64 + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 4632eb883e9f5efde520ee543bcad25827c0da2c..858c6c860d9b8aaa1d3f9f77a9e410726239d7cc 100644 +index e37aaf77f94b97b736cc20ef070cefdff0400188..763d06265c7d0000e4c641c3aaba785bb0efb23e 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -603,6 +603,15 @@ public class CraftEventFactory { +@@ -602,6 +602,15 @@ public class CraftEventFactory { // Paper end craftServer.getPluginManager().callEvent(event); @@ -17741,7 +17720,7 @@ index 4632eb883e9f5efde520ee543bcad25827c0da2c..858c6c860d9b8aaa1d3f9f77a9e41072 return event; } -@@ -1133,7 +1142,7 @@ public class CraftEventFactory { +@@ -1131,7 +1140,7 @@ public class CraftEventFactory { return CraftEventFactory.callEntityDamageEvent(source.getDirectBlock(), source.getDirectBlockState(), entity, DamageCause.LAVA, bukkitDamageSource, modifiers, modifierFunctions, cancelled); } else if (source.getDirectBlock() != null) { DamageCause cause; @@ -17750,7 +17729,7 @@ index 4632eb883e9f5efde520ee543bcad25827c0da2c..858c6c860d9b8aaa1d3f9f77a9e41072 cause = DamageCause.CONTACT; } else if (source.is(DamageTypes.HOT_FLOOR)) { cause = DamageCause.HOT_FLOOR; -@@ -1193,6 +1202,7 @@ public class CraftEventFactory { +@@ -1191,6 +1200,7 @@ public class CraftEventFactory { EntityDamageEvent event; if (damager != null) { event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions, critical); @@ -17784,7 +17763,7 @@ index 6d3f9d5dab6c9a2860ae31cae24310aa2d62da7c..4f29c579f94efe59a8c78520d75676fc case DISPENSER: case DROPPER: diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index af1ae3dacb628da23f7d2988c6e76d3fb2d64103..4ee2d501f882279b48edb4b8bf0824587c276bf6 100644 +index c6159c70f7a37b9bffe268b91905ce848d1d2927..d02adaaa6fbdc1c0eff44cb4a1f1642f9575a821 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java @@ -84,7 +84,7 @@ public class CraftInventory implements Inventory { @@ -17854,13 +17833,13 @@ index 792cb6adf0c7a6335cc5985fce8bed2e0f1149af..5734c5caffda79383ae30df20c3defb5 + // Purpur end - Anvil API } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 6081c588c61406d0d21a15e8e6140d5d5240f0a8..52811706808f3adff16fb0e969ebbcae36c609c3 100644 +index 78975412da0f0c2b802bfce6d30d56b26d8023e2..4ec6a07796023aab2f8f84f131f48108c235c852 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -514,4 +514,285 @@ public final class CraftItemStack extends ItemStack { - return this.pdcView; +@@ -658,4 +658,285 @@ public final class CraftItemStack extends ItemStack { } - // Paper end - pdc + + // Paper end - data component API + + // Purpur start + @Override @@ -18144,17 +18123,17 @@ index 6081c588c61406d0d21a15e8e6140d5d5240f0a8..52811706808f3adff16fb0e969ebbcae + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java -index c76c78bb7757d407102271463e14716a1b012deb..458b91582a22fb1e6deb1551c38d2a10e33e24f1 100644 +index 3592091c6d1371224e82e1f95b003951ad2f8779..4fdc78a9c74b42a8894030221e0452493d68020e 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java -@@ -29,6 +29,7 @@ public interface CraftRecipe extends Recipe { +@@ -38,6 +38,7 @@ public interface CraftRecipe extends Recipe { + stack = Ingredient.of(((RecipeChoice.MaterialChoice) bukkit).getChoices().stream().map((mat) -> CraftItemType.bukkitToMinecraft(mat))); } else if (bukkit instanceof RecipeChoice.ExactChoice) { - stack = new Ingredient(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> new net.minecraft.world.item.crafting.Ingredient.ItemValue(CraftItemStack.asNMSCopy(mat)))); - stack.exact = true; + stack = Ingredient.ofStacks(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> CraftItemStack.asNMSCopy(mat)).toList()); + stack.predicate = ((RecipeChoice.ExactChoice) bukkit).getPredicate(); // Purpur - // Paper start - support "empty" choices - } else if (bukkit == RecipeChoice.empty()) { - stack = Ingredient.EMPTY; + // Paper start - support "empty" choices - legacy method that spigot might incorrectly call + // Their impl of Ingredient.of() will error, ingredients need at least one entry. + // Callers running into this exception may have passed an incorrect empty() recipe choice to a non-empty slot or diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java b/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java index f86c95a13dff012de5db3e41ac261e9e8d44d9f3..1db0b790d824e419bb5fb6ab1f3003e120f9763b 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java @@ -18224,10 +18203,10 @@ index db8d8e2a07296d62c3097f02b03319e2e1ba9394..e5c30847297e056782084d81fb9300f9 + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java b/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java -index 0cbbd915631904fe8c6effefb92895422b33eff6..aef19cfbecb4ddfc8dc71c4f3b2a011364c12dc2 100644 +index cf0920e5f84b35647882fb963e9972af4e8427e0..e30c851acf49a425cd4fd409a6d5bbb2ff836e0e 100644 --- a/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java +++ b/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java -@@ -47,4 +47,10 @@ public class CraftMapRenderer extends MapRenderer { +@@ -49,4 +49,10 @@ public class CraftMapRenderer extends MapRenderer { } } @@ -18239,7 +18218,7 @@ index 0cbbd915631904fe8c6effefb92895422b33eff6..aef19cfbecb4ddfc8dc71c4f3b2a0113 + // Purpur - end } diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -index 52649f82351ab4f675c3cc3cd6640956b0f76b91..eb51c88c7a0658190d3a8bfd5d18dca79d85fba0 100644 +index b3169c551b8410f5861f9db0543c785439ecba7c..916ca3f1f39e10158fc7c10141785fff49ed1501 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java +++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java @@ -23,7 +23,15 @@ public final class CommandPermissions { @@ -18261,10 +18240,10 @@ index 52649f82351ab4f675c3cc3cd6640956b0f76b91..eb51c88c7a0658190d3a8bfd5d18dca7 DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "seed", "Allows the user to view the seed of the world", PermissionDefault.OP, commands); diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java new file mode 100644 -index 0000000000000000000000000000000000000000..3700904b82d3116c1336b86907ce1c2c4644b0ab +index 0000000000000000000000000000000000000000..4401cd919951e92f613e0899f243b0105dd852b7 --- /dev/null +++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java -@@ -0,0 +1,581 @@ +@@ -0,0 +1,580 @@ +package org.purpurmc.purpur; + +import com.google.common.base.Throwables; @@ -18286,6 +18265,7 @@ index 0000000000000000000000000000000000000000..3700904b82d3116c1336b86907ce1c2c +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.state.BlockBehaviour; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.configuration.ConfigurationSection; @@ -18349,7 +18329,7 @@ index 0000000000000000000000000000000000000000..3700904b82d3116c1336b86907ce1c2c + + readConfig(PurpurConfig.class, null); + -+ Blocks.rebuildCache(); ++ Block.BLOCK_STATE_REGISTRY.forEach(BlockBehaviour.BlockStateBase::initCache); + } + + protected static void log(String s) { @@ -18644,8 +18624,8 @@ index 0000000000000000000000000000000000000000..3700904b82d3116c1336b86907ce1c2c + defaultCurses.clear(); + } + getList("settings.blocks.grindstone.ignored-enchants", defaultCurses).forEach(key -> { -+ Registry registry = MinecraftServer.getServer().registryAccess().registryOrThrow(Registries.ENCHANTMENT); -+ Enchantment enchantment = registry.get(ResourceLocation.parse(key.toString())); ++ Registry registry = MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.ENCHANTMENT); ++ Enchantment enchantment = registry.getValue(ResourceLocation.parse(key.toString())); + if (enchantment == null) return; + grindstoneIgnoredEnchants.add(enchantment); + }); @@ -18679,7 +18659,6 @@ index 0000000000000000000000000000000000000000..3700904b82d3116c1336b86907ce1c2c + soulSandBlockReverseBubbleColumnFlow = getBoolean("settings.blocks.soul-sand.reverse-bubble-column-flow", soulSandBlockReverseBubbleColumnFlow); + } + -+ public static boolean allowShearsLooting = false; + public static boolean allowInapplicableEnchants = false; + public static boolean allowIncompatibleEnchants = false; + public static boolean allowHigherEnchantsLevels = false; @@ -18704,7 +18683,6 @@ index 0000000000000000000000000000000000000000..3700904b82d3116c1336b86907ce1c2c + } + set("settings.enchantment.anvil.allow-unsafe-enchants", null); + } -+ allowShearsLooting = getBoolean("settings.enchantment.allow-looting-on-shears", allowShearsLooting); + allowInapplicableEnchants = getBoolean("settings.enchantment.anvil.allow-inapplicable-enchants", allowInapplicableEnchants); + allowIncompatibleEnchants = getBoolean("settings.enchantment.anvil.allow-incompatible-enchants", allowIncompatibleEnchants); + allowHigherEnchantsLevels = getBoolean("settings.enchantment.anvil.allow-higher-enchants-levels", allowHigherEnchantsLevels); @@ -18765,7 +18743,7 @@ index 0000000000000000000000000000000000000000..3700904b82d3116c1336b86907ce1c2c + + private static void blastResistanceSettings() { + getMap("settings.blast-resistance-overrides", Collections.emptyMap()).forEach((blockId, value) -> { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(blockId)); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(blockId)); + if (block == Blocks.AIR) { + log(Level.SEVERE, "Invalid block for `settings.blast-resistance-overrides`: " + blockId); + return; @@ -18797,7 +18775,7 @@ index 0000000000000000000000000000000000000000..3700904b82d3116c1336b86907ce1c2c + Map.entry("minecraft:purple_bed", Map.of("distance", 0.5F)), + Map.entry("minecraft:magenta_bed", Map.of("distance", 0.5F)) + )).forEach((blockId, value) -> { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(blockId)); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(blockId)); + if (block == Blocks.AIR) { + log(Level.SEVERE, "Invalid block for `settings.block-fall-multipliers`: " + blockId); + return; @@ -18848,10 +18826,10 @@ index 0000000000000000000000000000000000000000..3700904b82d3116c1336b86907ce1c2c +} diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java new file mode 100644 -index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715ac0bb9d4a +index 0000000000000000000000000000000000000000..36b875a1cb10f1704e8530b6eb7b7e9dc51ef995 --- /dev/null +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -@@ -0,0 +1,3416 @@ +@@ -0,0 +1,3431 @@ +package org.purpurmc.purpur; + +import net.minecraft.core.registries.BuiltInRegistries; @@ -18973,28 +18951,28 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + public boolean boatEjectPlayersOnLand = false; + public boolean boatsDoFallDamage = false; + public boolean disableDropsOnCrammingDeath = false; ++ public boolean milkCuresBadOmen = true; ++ public double tridentLoyaltyVoidReturnHeight = 0.0D; + public boolean entitiesCanUsePortals = true; ++ public int raidCooldownSeconds = 0; ++ public int animalBreedingCooldownSeconds = 0; ++ public boolean persistentDroppableEntityDisplayNames = true; + public boolean entitiesPickUpLootBypassMobGriefing = false; + public boolean fireballsBypassMobGriefing = false; ++ public boolean projectilesBypassMobGriefing = false; ++ public boolean noteBlockIgnoreAbove = false; + public boolean imposeTeleportRestrictionsOnGateways = false; + public boolean imposeTeleportRestrictionsOnNetherPortals = false; + public boolean imposeTeleportRestrictionsOnEndPortals = false; -+ public boolean milkCuresBadOmen = true; -+ public boolean milkClearsBeneficialEffects = true; -+ public boolean noteBlockIgnoreAbove = false; -+ public boolean persistentDroppableEntityDisplayNames = true; -+ public boolean persistentTileEntityLore = false; -+ public boolean persistentTileEntityDisplayName = true; -+ public boolean projectilesBypassMobGriefing = false; + public boolean tickFluids = true; + public double mobsBlindnessMultiplier = 1; -+ public double tridentLoyaltyVoidReturnHeight = 0.0D; -+ public int raidCooldownSeconds = 0; -+ public int animalBreedingCooldownSeconds = 0; + public boolean mobsIgnoreRails = false; + public boolean rainStopsAfterSleep = true; + public boolean thunderStopsAfterSleep = true; ++ public boolean persistentTileEntityLore = false; ++ public boolean persistentTileEntityDisplayName = true; + public int mobLastHurtByPlayerTime = 100; ++ public boolean milkClearsBeneficialEffects = true; + public boolean disableOxidationProximityPenalty = false; + private void miscGameplayMechanicsSettings() { + useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending); @@ -19002,15 +18980,24 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + boatEjectPlayersOnLand = getBoolean("gameplay-mechanics.boat.eject-players-on-land", boatEjectPlayersOnLand); + boatsDoFallDamage = getBoolean("gameplay-mechanics.boat.do-fall-damage", boatsDoFallDamage); + disableDropsOnCrammingDeath = getBoolean("gameplay-mechanics.disable-drops-on-cramming-death", disableDropsOnCrammingDeath); ++ milkCuresBadOmen = getBoolean("gameplay-mechanics.milk-cures-bad-omen", milkCuresBadOmen); ++ tridentLoyaltyVoidReturnHeight = getDouble("gameplay-mechanics.trident-loyalty-void-return-height", tridentLoyaltyVoidReturnHeight); + entitiesCanUsePortals = getBoolean("gameplay-mechanics.entities-can-use-portals", entitiesCanUsePortals); ++ raidCooldownSeconds = getInt("gameplay-mechanics.raid-cooldown-seconds", raidCooldownSeconds); ++ animalBreedingCooldownSeconds = getInt("gameplay-mechanics.animal-breeding-cooldown-seconds", animalBreedingCooldownSeconds); ++ persistentDroppableEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-droppable-entity-display-names", persistentDroppableEntityDisplayNames); + entitiesPickUpLootBypassMobGriefing = getBoolean("gameplay-mechanics.entities-pick-up-loot-bypass-mob-griefing", entitiesPickUpLootBypassMobGriefing); + fireballsBypassMobGriefing = getBoolean("gameplay-mechanics.fireballs-bypass-mob-griefing", fireballsBypassMobGriefing); ++ projectilesBypassMobGriefing = getBoolean("gameplay-mechanics.projectiles-bypass-mob-griefing", projectilesBypassMobGriefing); ++ noteBlockIgnoreAbove = getBoolean("gameplay-mechanics.note-block-ignore-above", noteBlockIgnoreAbove); + imposeTeleportRestrictionsOnGateways = getBoolean("gameplay-mechanics.impose-teleport-restrictions-on-gateways", imposeTeleportRestrictionsOnGateways); + imposeTeleportRestrictionsOnNetherPortals = getBoolean("gameplay-mechanics.impose-teleport-restrictions-on-nether-portals", imposeTeleportRestrictionsOnNetherPortals); + imposeTeleportRestrictionsOnEndPortals = getBoolean("gameplay-mechanics.impose-teleport-restrictions-on-end-portals", imposeTeleportRestrictionsOnEndPortals); -+ milkCuresBadOmen = getBoolean("gameplay-mechanics.milk-cures-bad-omen", milkCuresBadOmen); -+ milkClearsBeneficialEffects = getBoolean("gameplay-mechanics.milk-clears-beneficial-effects", milkClearsBeneficialEffects); -+ noteBlockIgnoreAbove = getBoolean("gameplay-mechanics.note-block-ignore-above", noteBlockIgnoreAbove); ++ tickFluids = getBoolean("gameplay-mechanics.tick-fluids", tickFluids); ++ mobsBlindnessMultiplier = getDouble("gameplay-mechanics.entity-blindness-multiplier", mobsBlindnessMultiplier); ++ mobsIgnoreRails = getBoolean("gameplay-mechanics.mobs-ignore-rails", mobsIgnoreRails); ++ rainStopsAfterSleep = getBoolean("gameplay-mechanics.rain-stops-after-sleep", rainStopsAfterSleep); ++ thunderStopsAfterSleep = getBoolean("gameplay-mechanics.thunder-stops-after-sleep", thunderStopsAfterSleep); + if (PurpurConfig.version < 35) { + boolean oldVal = getBoolean("gameplay-mechanics.persistent-tileentity-display-names-and-lore", persistentTileEntityLore); + set("gameplay-mechanics.persistent-tileentity-display-names-and-lore", null); @@ -19019,17 +19006,8 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + } + persistentTileEntityLore = getBoolean("gameplay-mechanics.persistent-tileentity-lore", persistentTileEntityLore); + persistentTileEntityDisplayName = getBoolean("gameplay-mechanics.persistent-tileentity-display-name", persistentTileEntityDisplayName); -+ persistentDroppableEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-droppable-entity-display-names", persistentDroppableEntityDisplayNames); -+ projectilesBypassMobGriefing = getBoolean("gameplay-mechanics.projectiles-bypass-mob-griefing", projectilesBypassMobGriefing); -+ tickFluids = getBoolean("gameplay-mechanics.tick-fluids", tickFluids); -+ mobsBlindnessMultiplier = getDouble("gameplay-mechanics.entity-blindness-multiplier", mobsBlindnessMultiplier); -+ tridentLoyaltyVoidReturnHeight = getDouble("gameplay-mechanics.trident-loyalty-void-return-height", tridentLoyaltyVoidReturnHeight); -+ raidCooldownSeconds = getInt("gameplay-mechanics.raid-cooldown-seconds", raidCooldownSeconds); -+ animalBreedingCooldownSeconds = getInt("gameplay-mechanics.animal-breeding-cooldown-seconds", animalBreedingCooldownSeconds); -+ mobsIgnoreRails = getBoolean("gameplay-mechanics.mobs-ignore-rails", mobsIgnoreRails); -+ rainStopsAfterSleep = getBoolean("gameplay-mechanics.rain-stops-after-sleep", rainStopsAfterSleep); -+ thunderStopsAfterSleep = getBoolean("gameplay-mechanics.thunder-stops-after-sleep", thunderStopsAfterSleep); + mobLastHurtByPlayerTime = getInt("gameplay-mechanics.mob-last-hurt-by-player-time", mobLastHurtByPlayerTime); ++ milkClearsBeneficialEffects = getBoolean("gameplay-mechanics.milk-clears-beneficial-effects", milkClearsBeneficialEffects); + disableOxidationProximityPenalty = getBoolean("gameplay-mechanics.disable-oxidation-proximity-penalty", disableOxidationProximityPenalty); + } + @@ -19106,7 +19084,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + BuiltInRegistries.ITEM.stream().filter(item -> item != Items.AIR).forEach((item) -> itemImmuneToCactus.add(item)); + return; + } -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(key.toString())); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(key.toString())); + if (item != Items.AIR) itemImmuneToCactus.add(item); + }); + itemImmuneToExplosion.clear(); @@ -19115,7 +19093,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + BuiltInRegistries.ITEM.stream().filter(item -> item != Items.AIR).forEach((item) -> itemImmuneToExplosion.add(item)); + return; + } -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(key.toString())); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(key.toString())); + if (item != Items.AIR) itemImmuneToExplosion.add(item); + }); + itemImmuneToFire.clear(); @@ -19124,7 +19102,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + BuiltInRegistries.ITEM.stream().filter(item -> item != Items.AIR).forEach((item) -> itemImmuneToFire.add(item)); + return; + } -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(key.toString())); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(key.toString())); + if (item != Items.AIR) itemImmuneToFire.add(item); + }); + itemImmuneToLightning.clear(); @@ -19133,7 +19111,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + BuiltInRegistries.ITEM.stream().filter(item -> item != Items.AIR).forEach((item) -> itemImmuneToLightning.add(item)); + return; + } -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(key.toString())); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(key.toString())); + if (item != Items.AIR) itemImmuneToLightning.add(item); + }); + dontRunWithScissors = getBoolean("gameplay-mechanics.item.shears.damage-if-sprinting", dontRunWithScissors); @@ -19204,7 +19182,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + ConfigurationSection section = getConfigurationSection("gameplay-mechanics.minecart.controllable.block-speed"); + if (section != null) { + for (String key : section.getKeys(false)) { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(key)); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(key)); + if (block != Blocks.AIR) { + minecartControllableBlockSpeeds.put(block, section.getDouble(key, minecartControllableBaseSpeed)); + } @@ -19345,7 +19323,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + "minecraft:diamond_pickaxe", + "minecraft:netherite_pickaxe" + )).forEach(key -> { -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(key.toString())); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(key.toString())); + if (item != Items.AIR) silkTouchTools.add(item); + }); + } @@ -19481,17 +19459,17 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + Map.entry("minecraft:crimson_stem", Map.of("into", "minecraft:stripped_crimson_stem", "drops", new HashMap())), + Map.entry("minecraft:crimson_hyphae", Map.of("into", "minecraft:stripped_crimson_hyphae", "drops", new HashMap()))) + ).forEach((blockId, obj) -> { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(blockId)); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(blockId)); + if (block == Blocks.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid block for `tools.axe.strippables`: " + blockId); return; } + if (!(obj instanceof Map map)) { PurpurConfig.log(Level.SEVERE, "Invalid yaml for `tools.axe.strippables." + blockId + "`"); return; } + String intoId = (String) map.get("into"); -+ Block into = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(intoId)); ++ Block into = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(intoId)); + if (into == Blocks.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid block for `tools.axe.strippables." + blockId + ".into`: " + intoId); return; } + Object dropsObj = map.get("drops"); + if (!(dropsObj instanceof Map dropsMap)) { PurpurConfig.log(Level.SEVERE, "Invalid yaml for `tools.axe.strippables." + blockId + ".drops`"); return; } + Map drops = new HashMap<>(); + dropsMap.forEach((itemId, chance) -> { -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(itemId.toString())); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(itemId.toString())); + if (item == Items.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid item for `tools.axe.strippables." + blockId + ".drops`: " + itemId); return; } + drops.put(item, (double) chance); + }); @@ -19535,17 +19513,17 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + Map.entry("minecraft:waxed_weathered_copper_bulb", Map.of("into", "minecraft:weathered_copper_bulb", "drops", new HashMap())), + Map.entry("minecraft:waxed_oxidized_copper_bulb", Map.of("into", "minecraft:oxidized_copper_bulb", "drops", new HashMap()))) + ).forEach((blockId, obj) -> { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(blockId)); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(blockId)); + if (block == Blocks.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid block for `tools.axe.waxables`: " + blockId); return; } + if (!(obj instanceof Map map)) { PurpurConfig.log(Level.SEVERE, "Invalid yaml for `tools.axe.waxables." + blockId + "`"); return; } + String intoId = (String) map.get("into"); -+ Block into = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(intoId)); ++ Block into = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(intoId)); + if (into == Blocks.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid block for `tools.axe.waxables." + blockId + ".into`: " + intoId); return; } + Object dropsObj = map.get("drops"); + if (!(dropsObj instanceof Map dropsMap)) { PurpurConfig.log(Level.SEVERE, "Invalid yaml for `tools.axe.waxables." + blockId + ".drops`"); return; } + Map drops = new HashMap<>(); + dropsMap.forEach((itemId, chance) -> { -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(itemId.toString())); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(itemId.toString())); + if (item == Items.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid item for `tools.axe.waxables." + blockId + ".drops`: " + itemId); return; } + drops.put(item, (double) chance); + }); @@ -19580,17 +19558,17 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + Map.entry("minecraft:weathered_copper_bulb", Map.of("into", "minecraft:exposed_copper_bulb", "drops", new HashMap())), + Map.entry("minecraft:oxidized_copper_bulb", Map.of("into", "minecraft:weathered_copper_bulb", "drops", new HashMap()))) + ).forEach((blockId, obj) -> { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(blockId)); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(blockId)); + if (block == Blocks.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid block for `tools.axe.weatherables`: " + blockId); return; } + if (!(obj instanceof Map map)) { PurpurConfig.log(Level.SEVERE, "Invalid yaml for `tools.axe.weatherables." + blockId + "`"); return; } + String intoId = (String) map.get("into"); -+ Block into = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(intoId)); ++ Block into = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(intoId)); + if (into == Blocks.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid block for `tools.axe.weatherables." + blockId + ".into`: " + intoId); return; } + Object dropsObj = map.get("drops"); + if (!(dropsObj instanceof Map dropsMap)) { PurpurConfig.log(Level.SEVERE, "Invalid yaml for `tools.axe.weatherables." + blockId + ".drops`"); return; } + Map drops = new HashMap<>(); + dropsMap.forEach((itemId, chance) -> { -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(itemId.toString())); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(itemId.toString())); + if (item == Items.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid item for `tools.axe.weatherables." + blockId + ".drops`: " + itemId); return; } + drops.put(item, (double) chance); + }); @@ -19603,20 +19581,20 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + Map.entry("minecraft:coarse_dirt", Map.of("condition", "air_above", "into", "minecraft:dirt", "drops", new HashMap())), + Map.entry("minecraft:rooted_dirt", Map.of("condition", "always", "into", "minecraft:dirt", "drops", Map.of("minecraft:hanging_roots", 1.0D)))) + ).forEach((blockId, obj) -> { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(blockId)); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(blockId)); + if (block == Blocks.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid block for `tools.hoe.tillables`: " + blockId); return; } + if (!(obj instanceof Map map)) { PurpurConfig.log(Level.SEVERE, "Invalid yaml for `tools.hoe.tillables." + blockId + "`"); return; } + String conditionId = (String) map.get("condition"); + Tillable.Condition condition = Tillable.Condition.get(conditionId); + if (condition == null) { PurpurConfig.log(Level.SEVERE, "Invalid condition for `tools.hoe.tillables." + blockId + ".condition`: " + conditionId); return; } + String intoId = (String) map.get("into"); -+ Block into = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(intoId)); ++ Block into = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(intoId)); + if (into == Blocks.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid block for `tools.hoe.tillables." + blockId + ".into`: " + intoId); return; } + Object dropsObj = map.get("drops"); + if (!(dropsObj instanceof Map dropsMap)) { PurpurConfig.log(Level.SEVERE, "Invalid yaml for `tools.hoe.tillables." + blockId + ".drops`"); return; } + Map drops = new HashMap<>(); + dropsMap.forEach((itemId, chance) -> { -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(itemId.toString())); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(itemId.toString())); + if (item == Items.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid item for `tools.hoe.tillables." + blockId + ".drops`: " + itemId); return; } + drops.put(item, (double) chance); + }); @@ -19630,17 +19608,17 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + Map.entry("minecraft:mycelium", Map.of("into", "minecraft:dirt_path", "drops", new HashMap())), + Map.entry("minecraft:rooted_dirt", Map.of("into", "minecraft:dirt_path", "drops", new HashMap()))) + ).forEach((blockId, obj) -> { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(blockId)); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(blockId)); + if (block == Blocks.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid block for `tools.shovel.flattenables`: " + blockId); return; } + if (!(obj instanceof Map map)) { PurpurConfig.log(Level.SEVERE, "Invalid yaml for `tools.shovel.flattenables." + blockId + "`"); return; } + String intoId = (String) map.get("into"); -+ Block into = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(intoId)); ++ Block into = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(intoId)); + if (into == Blocks.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid block for `tools.shovel.flattenables." + blockId + ".into`: " + intoId); return; } + Object dropsObj = map.get("drops"); + if (!(dropsObj instanceof Map dropsMap)) { PurpurConfig.log(Level.SEVERE, "Invalid yaml for `tools.shovel.flattenables." + blockId + ".drops`"); return; } + Map drops = new HashMap<>(); + dropsMap.forEach((itemId, chance) -> { -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(itemId.toString())); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(itemId.toString())); + if (item == Items.AIR) { PurpurConfig.log(Level.SEVERE, "Invalid item for `tools.shovel.flattenables." + blockId + ".drops`: " + itemId); return; } + drops.put(item, (double) chance); + }); @@ -19765,7 +19743,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + public List doorRequiresRedstone = new ArrayList<>(); + private void doorSettings() { + getList("blocks.door.requires-redstone", new ArrayList()).forEach(key -> { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(key.toString())); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(key.toString())); + if (!block.defaultBlockState().isAir()) { + doorRequiresRedstone.add(block); + } @@ -20067,7 +20045,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + public double beeMaxHealth = 10.0D; + public double beeScale = 1.0D; + public int beeBreedingTicks = 6000; -+ public boolean beeTakeDamageFromWater = false; ++ public boolean beeTakeDamageFromWater = true; + public boolean beeCanWorkAtNight = false; + public boolean beeCanWorkInRain = false; + public boolean beeAlwaysDropExp = false; @@ -20287,6 +20265,19 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + cowAlwaysDropExp = getBoolean("mobs.cow.always-drop-exp", cowAlwaysDropExp); + } + ++ public boolean creakingRidable = false; ++ public boolean creakingRidableInWater = true; ++ public boolean creakingControllable = true; ++ public double creakingMaxHealth = 1.0D; ++ public double creakingScale = 1.0D; ++ private void creakingSettings() { ++ creakingRidable = getBoolean("mobs.creaking.ridable", creakingRidable); ++ creakingRidableInWater = getBoolean("mobs.creaking.ridable-in-water", creakingRidableInWater); ++ creakingControllable = getBoolean("mobs.creaking.controllable", creakingControllable); ++ creakingMaxHealth = getDouble("mobs.creaking.attributes.max_health", creakingMaxHealth); ++ creakingScale = Mth.clamp(getDouble("mobs.creaking.attributes.scale", creakingScale), 0.0625D, 16.0D); ++ } ++ + public boolean creeperRidable = false; + public boolean creeperRidableInWater = true; + public boolean creeperControllable = true; @@ -20481,7 +20472,6 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + public boolean endermanTakeDamageFromWater = true; + public boolean endermanAggroEndermites = true; + public boolean endermanAggroEndermitesOnlyIfPlayerSpawned = false; -+ public boolean endermanIgnorePlayerDragonHead = false; + public boolean endermanDisableStareAggro = false; + public boolean endermanIgnoreProjectiles = false; + public boolean endermanAlwaysDropExp = false; @@ -20506,7 +20496,6 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + endermanTakeDamageFromWater = getBoolean("mobs.enderman.takes-damage-from-water", endermanTakeDamageFromWater); + endermanAggroEndermites = getBoolean("mobs.enderman.aggressive-towards-endermites", endermanAggroEndermites); + endermanAggroEndermitesOnlyIfPlayerSpawned = getBoolean("mobs.enderman.aggressive-towards-endermites-only-spawned-by-player-thrown-ender-pearls", endermanAggroEndermitesOnlyIfPlayerSpawned); -+ endermanIgnorePlayerDragonHead = getBoolean("mobs.enderman.ignore-players-wearing-dragon-head", endermanIgnorePlayerDragonHead); + endermanDisableStareAggro = getBoolean("mobs.enderman.disable-player-stare-aggression", endermanDisableStareAggro); + endermanIgnoreProjectiles = getBoolean("mobs.enderman.ignore-projectiles", endermanIgnoreProjectiles); + endermanAlwaysDropExp = getBoolean("mobs.enderman.always-drop-exp", endermanAlwaysDropExp); @@ -21255,7 +21244,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + polarBearMaxHealth = getDouble("mobs.polar_bear.attributes.max_health", polarBearMaxHealth); + polarBearScale = Mth.clamp(getDouble("mobs.polar_bear.attributes.scale", polarBearScale), 0.0625D, 16.0D); + polarBearBreedableItemString = getString("mobs.polar_bear.breedable-item", polarBearBreedableItemString); -+ Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(polarBearBreedableItemString)); ++ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(polarBearBreedableItemString)); + if (item != Items.AIR) polarBearBreedableItem = item; + polarBearBreedingTicks = getInt("mobs.polar_bear.breeding-delay-ticks", polarBearBreedingTicks); + polarBearTakeDamageFromWater = getBoolean("mobs.polar_bear.takes-damage-from-water", polarBearTakeDamageFromWater); @@ -21347,7 +21336,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + add("minecraft:potatoes"); + add("minecraft:wheat"); + }}).forEach(key -> { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(key.toString())); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(key.toString())); + if (!block.defaultBlockState().isAir()) { + ravagerGriefableBlocks.add(block); + } @@ -21825,6 +21814,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + public double villagerMaxHealth = 20.0D; + public double villagerScale = 1.0D; + public boolean villagerFollowEmeraldBlock = false; ++ public double villagerTemptRange = 10.0D; + public boolean villagerCanBeLeashed = false; + public boolean villagerCanBreed = true; + public int villagerBreedingTicks = 6000; @@ -21855,6 +21845,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + villagerMaxHealth = getDouble("mobs.villager.attributes.max_health", villagerMaxHealth); + villagerScale = Mth.clamp(getDouble("mobs.villager.attributes.scale", villagerScale), 0.0625D, 16.0D); + villagerFollowEmeraldBlock = getBoolean("mobs.villager.follow-emerald-blocks", villagerFollowEmeraldBlock); ++ villagerTemptRange = getDouble("mobs.villager.attributes.tempt_range", villagerTemptRange); + villagerCanBeLeashed = getBoolean("mobs.villager.can-be-leashed", villagerCanBeLeashed); + villagerCanBreed = getBoolean("mobs.villager.can-breed", villagerCanBreed); + villagerBreedingTicks = getInt("mobs.villager.breeding-delay-ticks", villagerBreedingTicks); @@ -21914,6 +21905,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + public double wanderingTraderMaxHealth = 20.0D; + public double wanderingTraderScale = 1.0D; + public boolean wanderingTraderFollowEmeraldBlock = false; ++ public double wanderingTraderTemptRange = 10.0D; + public boolean wanderingTraderCanBeLeashed = false; + public boolean wanderingTraderTakeDamageFromWater = false; + public boolean wanderingTraderAllowTrading = true; @@ -21930,6 +21922,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + wanderingTraderMaxHealth = getDouble("mobs.wandering_trader.attributes.max_health", wanderingTraderMaxHealth); + wanderingTraderScale = Mth.clamp(getDouble("mobs.wandering_trader.attributes.scale", wanderingTraderScale), 0.0625D, 16.0D); + wanderingTraderFollowEmeraldBlock = getBoolean("mobs.wandering_trader.follow-emerald-blocks", wanderingTraderFollowEmeraldBlock); ++ wanderingTraderTemptRange = getDouble("mobs.wandering_trader.attributes.tempt_range", wanderingTraderTemptRange); + wanderingTraderCanBeLeashed = getBoolean("mobs.wandering_trader.can-be-leashed", wanderingTraderCanBeLeashed); + wanderingTraderTakeDamageFromWater = getBoolean("mobs.wandering_trader.takes-damage-from-water", wanderingTraderTakeDamageFromWater); + wanderingTraderAllowTrading = getBoolean("mobs.wandering_trader.allow-trading", wanderingTraderAllowTrading); @@ -22242,7 +22235,7 @@ index 0000000000000000000000000000000000000000..d2021197a100279f2e9bcad4cadd715a + add("minecraft:sea_lantern"); + add("minecraft:dark_prismarine"); + }}).forEach(key -> { -+ Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse(key.toString())); ++ Block block = BuiltInRegistries.BLOCK.getValue(ResourceLocation.parse(key.toString())); + if (!block.defaultBlockState().isAir()) { + conduitBlockList.add(block); + } @@ -22997,15 +22990,17 @@ index 0000000000000000000000000000000000000000..dd219518150ca90f89ad238904fd4095 +} diff --git a/src/main/java/org/purpurmc/purpur/controller/MoveControllerWASD.java b/src/main/java/org/purpurmc/purpur/controller/MoveControllerWASD.java new file mode 100644 -index 0000000000000000000000000000000000000000..21fd6ea2a482758a3016e3bc2cdebe2d89267481 +index 0000000000000000000000000000000000000000..ad85c1ff6cd5d5ce2262bdb367ce9c8a5b707170 --- /dev/null +++ b/src/main/java/org/purpurmc/purpur/controller/MoveControllerWASD.java -@@ -0,0 +1,89 @@ +@@ -0,0 +1,92 @@ +package org.purpurmc.purpur.controller; + ++import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.control.MoveControl; ++import net.minecraft.world.entity.player.Input; +import net.minecraft.world.entity.player.Player; +import org.purpurmc.purpur.event.entity.RidableSpacebarEvent; + @@ -23042,8 +23037,9 @@ index 0000000000000000000000000000000000000000..21fd6ea2a482758a3016e3bc2cdebe2d + } + + public void purpurTick(Player rider) { -+ float forward = rider.getForwardMot() * 0.5F; -+ float strafe = rider.getStrafeMot() * 0.25F; ++ Input lastClientInput = ((ServerPlayer) rider).getLastClientInput(); ++ float forward = (lastClientInput.forward() == lastClientInput.backward() ? 0.0F : lastClientInput.forward() ? 1.0F : -1.0F) * 0.5F; ++ float strafe = (lastClientInput.left() == lastClientInput.right() ? 0.0F : lastClientInput.left() ? 1.0F : -1.0F) * 0.25F; + + if (forward <= 0.0F) { + forward *= 0.5F; @@ -23261,10 +23257,10 @@ index 0000000000000000000000000000000000000000..f25abee6dbf99c8d08f8e09db02b41df +} diff --git a/src/main/java/org/purpurmc/purpur/entity/PhantomFlames.java b/src/main/java/org/purpurmc/purpur/entity/PhantomFlames.java new file mode 100644 -index 0000000000000000000000000000000000000000..75e31aee6e706f042398444f272888f9ad0fa3f4 +index 0000000000000000000000000000000000000000..58957b0bd3cd2c37fd4a6766a02e2506d9f51010 --- /dev/null +++ b/src/main/java/org/purpurmc/purpur/entity/PhantomFlames.java -@@ -0,0 +1,121 @@ +@@ -0,0 +1,129 @@ +package org.purpurmc.purpur.entity; + +import net.minecraft.core.particles.ParticleTypes; @@ -23362,13 +23358,17 @@ index 0000000000000000000000000000000000000000..75e31aee6e706f042398444f272888f9 + + @Override + protected void onHitEntity(EntityHitResult entityHitResult) { -+ Entity shooter = this.getOwner(); -+ if (shooter instanceof LivingEntity) { -+ Entity target = entityHitResult.getEntity(); -+ if (canGrief || (target instanceof LivingEntity && !(target instanceof ArmorStand))) { -+ boolean hurt = target.hurt(target.damageSources().mobProjectile(this, (LivingEntity) shooter), level().purpurConfig.phantomFlameDamage); -+ if (hurt && level().purpurConfig.phantomFlameFireTime > 0) { -+ target.igniteForSeconds(level().purpurConfig.phantomFlameFireTime); ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel worldserver) { ++ Entity shooter = this.getOwner(); ++ if (shooter instanceof LivingEntity) { ++ Entity target = entityHitResult.getEntity(); ++ if (canGrief || (target instanceof LivingEntity && !(target instanceof ArmorStand))) { ++ boolean hurt = target.hurtServer(worldserver, target.damageSources().mobProjectile(this, (LivingEntity) shooter), worldserver.purpurConfig.phantomFlameDamage); ++ if (hurt && worldserver.purpurConfig.phantomFlameFireTime > 0) { ++ target.igniteForSeconds(worldserver.purpurConfig.phantomFlameFireTime); ++ } + } + } + } @@ -23376,14 +23376,18 @@ index 0000000000000000000000000000000000000000..75e31aee6e706f042398444f272888f9 + + @Override + protected void onHitBlock(BlockHitResult blockHitResult) { -+ if (this.hitCancelled) { -+ return; -+ } -+ if (this.canGrief) { -+ BlockState state = this.level().getBlockState(blockHitResult.getBlockPos()); -+ state.onProjectileHit(this.level(), state, blockHitResult, this); ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel worldserver) { ++ if (this.hitCancelled) { ++ return; ++ } ++ if (this.canGrief) { ++ BlockState state = worldserver.getBlockState(blockHitResult.getBlockPos()); ++ state.onProjectileHit(worldserver, state, blockHitResult, this); ++ } ++ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); + } -+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); + } +} diff --git a/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java b/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java @@ -23822,7 +23826,7 @@ index 0000000000000000000000000000000000000000..d75fb5e77eff27d86135ed7d605dbc25 +} diff --git a/src/main/java/org/purpurmc/purpur/item/GlowBerryItem.java b/src/main/java/org/purpurmc/purpur/item/GlowBerryItem.java new file mode 100644 -index 0000000000000000000000000000000000000000..7f526883495b3222746de3d0442e9e4fb5107036 +index 0000000000000000000000000000000000000000..b257f35caa13b660854cf17f41fd8fba1d56c458 --- /dev/null +++ b/src/main/java/org/purpurmc/purpur/item/GlowBerryItem.java @@ -0,0 +1,26 @@ @@ -23832,13 +23836,13 @@ index 0000000000000000000000000000000000000000..7f526883495b3222746de3d0442e9e4f +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.LivingEntity; -+import net.minecraft.world.item.ItemNameBlockItem; ++import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import org.bukkit.event.entity.EntityPotionEffectEvent; + -+public class GlowBerryItem extends ItemNameBlockItem { ++public class GlowBerryItem extends BlockItem { + public GlowBerryItem(Block block, Properties settings) { + super(block, settings); + } @@ -24825,10 +24829,10 @@ index 0000000000000000000000000000000000000000..129acb8ad139decc6b1c023cb10bc32d + // Paper end - lifecycle events +} diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 54c9075029161212827c07cc83a5ed439b5ae5bf..22e937218864fed922192c1499e26ed3d3323320 100644 +index 62bb1fa77045ea83afe8a181c3b3a4d7284103b7..a526121ff6af27bb0a87fec672aa23493d018df0 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -213,6 +213,8 @@ public class ActivationRange +@@ -211,6 +211,8 @@ public class ActivationRange continue; } @@ -24837,13 +24841,13 @@ index 54c9075029161212827c07cc83a5ed439b5ae5bf..22e937218864fed922192c1499e26ed3 // Paper start int worldHeight = world.getHeight(); ActivationRange.maxBB = player.getBoundingBox().inflate( maxRange, worldHeight, maxRange ); -@@ -408,6 +410,7 @@ public class ActivationRange +@@ -405,6 +407,7 @@ public class ActivationRange */ public static boolean checkIfActive(Entity entity) { + if (entity.level().purpurConfig.squidImmuneToEAR && entity instanceof net.minecraft.world.entity.animal.Squid) return true; // Purpur - // Never safe to skip fireworks or entities not yet added to chunk - if ( entity instanceof FireworkRocketEntity ) { + // Never safe to skip fireworks or item gravity + if (entity instanceof FireworkRocketEntity || (entity instanceof ItemEntity && (entity.tickCount + entity.getId()) % 4 == 0)) { // Paper - Needed for item gravity, see ItemEntity tick return true; diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index d2a75850af9c6ad2aca66a5f994f1b587d73eac4..a056aa167887abef9e6d531a9edd2cda433567d2 100644 diff --git a/patches/server/0012-Fix-Pufferfish-and-Purpur-patches.patch b/patches/server/0011-Fix-Pufferfish-and-Purpur-patches.patch similarity index 80% rename from patches/server/0012-Fix-Pufferfish-and-Purpur-patches.patch rename to patches/server/0011-Fix-Pufferfish-and-Purpur-patches.patch index dd3d10fd9..c3596bc73 100644 --- a/patches/server/0012-Fix-Pufferfish-and-Purpur-patches.patch +++ b/patches/server/0011-Fix-Pufferfish-and-Purpur-patches.patch @@ -5,17 +5,17 @@ Subject: [PATCH] Fix Pufferfish and Purpur patches diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java -index 23609a71a993fc91271578ee0a541a9c6ec7354f..34f7f74b374d319d0d578e498db7663dd58b8458 100644 +index 23609a71a993fc91271578ee0a541a9c6ec7354f..298574c83ed88c307b07ca163a97b2f43784401c 100644 --- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java +++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java -@@ -32,6 +32,7 @@ public record ServerBuildInfoImpl( - +@@ -33,6 +33,7 @@ public record ServerBuildInfoImpl( private static final String BRAND_PAPER_NAME = "Paper"; private static final String BRAND_GALE_NAME = "Gale"; // Gale - branding changes -+ private static final String BRAND_PUFFERFISH_NAME = "Pufferfish"; // Leaf private static final String BRAND_PURPUR_NAME = "Purpur"; // Purpur ++ private static final String BRAND_PUFFERFISH_NAME = "Pufferfish"; // Leaf private static final String BRAND_LEAF_NAME = "Leaf"; // Leaf + private static final String BUILD_DEV = "DEV"; @@ -66,7 +67,9 @@ public record ServerBuildInfoImpl( public boolean isBrandCompatible(final @NotNull Key brandId) { return brandId.equals(this.brandId) @@ -28,10 +28,10 @@ index 23609a71a993fc91271578ee0a541a9c6ec7354f..34f7f74b374d319d0d578e498db7663d @Override diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 2bdc050df0333dbd611d1eb2714aa2a00116a2be..332305f3112072ad2d3570af767cc9a3fbef7e46 100644 +index a624cd8a0fa9ad05f8f69c50f3fdf961713b1791..b6d930287dd02c08575ffbf3353076c9bb74ecfc 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -300,7 +300,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping - public gg.pufferfish.pufferfish.util.AsyncExecutor mobSpawnExecutor = new gg.pufferfish.pufferfish.util.AsyncExecutor("MobSpawning"); // Pufferfish - optimize mob spawning + public gg.pufferfish.pufferfish.util.AsyncExecutor mobSpawnExecutor = new gg.pufferfish.pufferfish.util.AsyncExecutor("Leaf Async Mob Spawn Thread"); // Pufferfish - optimize mob spawning // Leaf - Unify thread name public static S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); -@@ -1306,9 +1306,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop byteAllowed) { @@ -131,10 +131,10 @@ index 182e5cb7bb9b62e78248330bb05c79fb835df170..adf4732e57927810d34bf37fb3e9d2dc this.disconnectAsync(Component.literal("Book too large!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Paper - add proper async disconnect return; diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index b652bfd4aea7eca7eebc0265a518956eac8b7e73..39be345524b621e6ae2eec9af9d46da3291c671b 100644 +index 68f94543395c143234957cd5e33600a0c4b1c87d..3665fa73fb0bd788335a8bbbdaa8f5aba0b45d8b 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -562,13 +562,29 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -579,13 +579,29 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // Purpur end // Purpur start - copied from Mob - API for any mob to burn daylight @@ -167,20 +167,11 @@ index b652bfd4aea7eca7eebc0265a518956eac8b7e73..39be345524b621e6ae2eec9af9d46da3 return true; } } -@@ -874,7 +890,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - public void tick() { - // Pufferfish start - entity TTL - if (type != EntityType.PLAYER && type.ttl >= 0 && this.tickCount >= type.ttl) { -- discard(); -+ discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); // Purpur - return; - } - // Pufferfish end - entity TTL diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 92b0e53ca1e154dde919502a99e82b16b3092450..64013ae4bdaabf10ac0dbbab8ccfa6430df76b83 100644 +index 260e9b0398ddaacacfe5de352ac686ef273a6167..6f3986ba57ce794a1f78b8960a7c8de8a3508c19 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1045,17 +1045,19 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1064,18 +1064,20 @@ public abstract class LivingEntity extends Entity implements Attackable { if (entity != null) { EntityType entitytypes = entity.getType(); @@ -192,8 +183,9 @@ index 92b0e53ca1e154dde919502a99e82b16b3092450..64013ae4bdaabf10ac0dbbab8ccfa643 - } else if (entitytypes == EntityType.ZOMBIE && itemstack.is(Items.ZOMBIE_HEAD)) { + } else if (entitytypes == EntityType.ZOMBIE && this.getItemBySlot(EquipmentSlot.HEAD).is(Items.ZOMBIE_HEAD)) { d0 *= entity.level().purpurConfig.zombieHeadVisibilityPercent; -- } else if (entitytypes == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) { -+ } else if (entitytypes == EntityType.CREEPER && this.getItemBySlot(EquipmentSlot.HEAD).is(Items.CREEPER_HEAD)) { + } +- else if (entitytypes == EntityType.CREEPER && itemstack.is(Items.CREEPER_HEAD)) { ++ else if (entitytypes == EntityType.CREEPER && this.getItemBySlot(EquipmentSlot.HEAD).is(Items.CREEPER_HEAD)) { d0 *= entity.level().purpurConfig.creeperHeadVisibilityPercent; - } else if ((entitytypes == EntityType.PIGLIN || entitytypes == EntityType.PIGLIN_BRUTE) && itemstack.is(Items.PIGLIN_HEAD)) { + } else if ((entitytypes == EntityType.PIGLIN || entitytypes == EntityType.PIGLIN_BRUTE) && this.getItemBySlot(EquipmentSlot.HEAD).is(Items.PIGLIN_HEAD)) { @@ -205,19 +197,10 @@ index 92b0e53ca1e154dde919502a99e82b16b3092450..64013ae4bdaabf10ac0dbbab8ccfa643 // Purpur start if (entity instanceof LivingEntity entityliving) { diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 78745bc7373c36a871ed9672b7fb4311f2ff3ebd..63b827d91a935d6b6f04266eea682da97af79cf2 100644 +index dfae42ed76d11438ac79d083c82914c60f0e606e..6c603c83d9caeed480f5d67854e40c3fa8ff20dd 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -705,7 +705,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab - @Override - public void aiStep() { - super.aiStep(); -- if (!this.level().isClientSide && this.canPickUpLoot() && this.isAlive() && !this.dead && (this.level().purpurConfig.entitiesPickUpLootBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { -+ if (!this.level().isClientSide && this.canPickUpLoot() && this.isAlive() && !this.dead && (this.level().purpurConfig.entitiesPickUpLootBypassMobGriefing || this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // Purpur - Vec3i baseblockposition = this.getPickupReach(); - List list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate((double) baseblockposition.getX(), (double) baseblockposition.getY(), (double) baseblockposition.getZ())); - Iterator iterator = list.iterator(); -@@ -1762,11 +1762,6 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1746,11 +1746,6 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab protected void playAttackSound() {} @@ -278,10 +261,10 @@ index 675126d9ab94b6c69d0436a42b9594a567aca6e4..67f16bd710e0c04b4e2dac2c2cf58628 ResourceKey resourceKey = world.dimension(); BlockPos blockPos = entity.blockPosition(); diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -index c0383771b08e1d89dfa4996b979248da1de8aca1..3bb46ed871fd56bbbe52cfd2575f9e853e03cd73 100644 +index 037586c0fdb42a02660aba89dd741a647c67e52b..a3c284976b37e865c51ee91166c4046a3c4f3a16 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -687,7 +687,7 @@ public class ArmorStand extends LivingEntity { +@@ -685,7 +685,7 @@ public class ArmorStand extends LivingEntity { @Override public void tick() { @@ -291,10 +274,10 @@ index c0383771b08e1d89dfa4996b979248da1de8aca1..3bb46ed871fd56bbbe52cfd2575f9e85 if (!this.canTick) { if (this.noTickPoseDirty) { diff --git a/src/main/java/net/minecraft/world/entity/monster/Blaze.java b/src/main/java/net/minecraft/world/entity/monster/Blaze.java -index 6c68c1df84e006f9992435f4c8e328c17e88c51c..f86f42863227494f7f71a7813fd49049d04aa081 100644 +index 07db4557ab0d7a4a0f5432257bd18195d2de7255..c334f0bdd4d5e1e5468216b13e6f5350d2348349 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Blaze.java +++ b/src/main/java/net/minecraft/world/entity/monster/Blaze.java -@@ -72,7 +72,6 @@ public class Blaze extends Monster { +@@ -73,7 +73,6 @@ public class Blaze extends Monster { setDeltaMovement(mot.scale(0.9D)); } } @@ -302,7 +285,7 @@ index 6c68c1df84e006f9992435f4c8e328c17e88c51c..f86f42863227494f7f71a7813fd49049 @Override public void initAttributes() { -@@ -84,6 +83,7 @@ public class Blaze extends Monster { +@@ -85,6 +84,7 @@ public class Blaze extends Monster { protected boolean isAlwaysExperienceDropper() { return this.level().purpurConfig.blazeAlwaysDropExp; } @@ -311,7 +294,7 @@ index 6c68c1df84e006f9992435f4c8e328c17e88c51c..f86f42863227494f7f71a7813fd49049 @Override protected void registerGoals() { diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java b/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java -index 67ede6b9d6ff2953f155f50c0e92c517ee02c65f..759d808ee73dfb480d91ae6f17dc56f4ad0b0a20 100644 +index 4f3ce7ff387835b8a14eb36c90700fdb837a933c..6dd64c56581fcf42ceafaeed557ee5214f67184f 100644 --- a/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java +++ b/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java @@ -31,7 +31,7 @@ public record VillagerProfession( @@ -324,10 +307,10 @@ index 67ede6b9d6ff2953f155f50c0e92c517ee02c65f..759d808ee73dfb480d91ae6f17dc56f4 "farmer", PoiTypes.FARMER, diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index 0f143ed6b3448c8d40eb79dfe19b3d9e4e68d853..cbd510df8f1b886d1c40f431cb236d73f83417b9 100644 +index a7fe724fd2aec7a72781e7b3ab74ff317cec8fbf..fd22b5374fe5de11474f495ea941b8dd10e2d41f 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -77,7 +77,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { +@@ -83,7 +83,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { int maxChunkLoadsPerProjectile = maxProjectileChunkLoadsConfig.perProjectile.max; if (maxChunkLoadsPerProjectile >= 0 && this.chunksLoadedByProjectile >= maxChunkLoadsPerProjectile) { if (maxProjectileChunkLoadsConfig.perProjectile.removeFromWorldAfterReachLimit) { diff --git a/patches/server/0013-Purpur-Configurable-server-mod-name.patch b/patches/server/0012-Purpur-Configurable-server-mod-name.patch similarity index 92% rename from patches/server/0013-Purpur-Configurable-server-mod-name.patch rename to patches/server/0012-Purpur-Configurable-server-mod-name.patch index 9a3e325b3..6c7f776f2 100644 --- a/patches/server/0013-Purpur-Configurable-server-mod-name.patch +++ b/patches/server/0012-Purpur-Configurable-server-mod-name.patch @@ -7,10 +7,10 @@ Original license: MIT Original project: https://github.com/PurpurMC/Purpur diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d9c654a16066857979623a54c6108c36faf91173..bfe6d88ec4181b093281e3371b41dcee039dff4e 100644 +index b6d930287dd02c08575ffbf3353076c9bb74ecfc..a7a8273a21434fc04b01d06708b65e80487a95d3 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1945,7 +1945,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop