From 64802e7e50c4f6d80a98ad04062924729b573d43 Mon Sep 17 00:00:00 2001 From: AlphaKR93 Date: Wed, 30 Oct 2024 15:03:07 +0900 Subject: [PATCH] 1.21.3 --- .../alwaysuptodate/tasks/PurpurUpdateTask.kt | 12 +- gradle.properties | 12 +- libs/server.versions.toml | 4 +- patches/api/0001-Pufferfish-API-Changes.patch | 527 -- ...es.patch => 0001-Purpur-API-Changes.patch} | 551 +- ...=> 0002-Use-Gradle-Version-Catalogs.patch} | 4 +- ...ch => 0003-Fork-friendly-Rebranding.patch} | 0 ...patch => 0004-Plazma-Configurations.patch} | 0 ...ks.patch => 0005-Various-API-Tweaks.patch} | 2 +- .../0001-Purpur-Generated-API-Changes.patch | 4 +- .../0001-Pufferfish-Server-Changes.patch | 2570 ------- ...patch => 0001-Purpur-Server-Changes.patch} | 6428 ++++++++--------- ....patch => 0002-Build-System-Changes.patch} | 21 +- ...ch => 0003-Fork-friendly-Rebranding.patch} | 41 +- ...and-Logo.patch => 0004-Rebrand-Logo.patch} | 0 ...patch => 0005-Plazma-Configurations.patch} | 52 +- ...-Setup-basic-configuration-sections.patch} | 0 ...artup.patch => 0007-Warn-on-startup.patch} | 2 +- ...ways-agree-EULA-on-development-mode.patch} | 6 +- ...rics.patch => 0009-Add-more-metrics.patch} | 2 +- ...010-Optimize-default-configurations.patch} | 106 +- ...apply-the-configuration-to-the-vani.patch} | 8 +- ...patch => 0012-Tweak-console-logging.patch} | 14 +- ...issing-purpur-configuration-options.patch} | 66 +- ...option-to-change-nether-portal-size.patch} | 26 +- ...=> 0015-Apply-various-optimizations.patch} | 6 +- ...Do-not-load-chunks-to-spawn-phantom.patch} | 2 +- ...able-moved-to-quickly-check-for-spe.patch} | 22 +- ...18-Configurable-cave-lava-sea-level.patch} | 2 +- ...0011-Optimize-default-configurations.patch | 58 + ...me-missing-Pufferfish-configurations.patch | 0 ...0020-Configurable-entity-sensor-tick.patch | 0 ...0021-Variable-entity-wakeup-duration.patch | 0 .../0022-Optimise-state-lookup-more.patch | 0 .../0023-Skip-event-if-no-listeners.patch | 0 ...0024-Add-entity-spawn-deadlock-timer.patch | 0 .../server/0025-Lithium-HashedList.patch | 0 .../0026-Improve-SwingTime-ticking.patch | 0 .../0027-Save-Json-list-asynchronously.patch | 0 ...8-Process-pathfinding-asynchronously.patch | 0 ...-when-running-the-test-server-with-g.patch | 0 ...instead-if-server-favicon-doesn-t-ex.patch | 0 .../server/0031-Implement-FreedomChat.patch | 0 .../0033-Port-SparklyPaper-patches.patch | 0 .../server/0034-Add-more-MSPT.patch | 0 ...flag-when-loading-maps-from-the-disk.patch | 0 ...-hopper-checks-if-the-target-contain.patch | 0 ...uppress-errors-from-dirty-attributes.patch | 0 .../0038-Implement-Rail-Optimazition.patch | 0 ...nt-alternative-noise-chunk-generator.patch | 0 ...0040-Load-player-data-asynchronously.patch | 0 ...urable-RandomSource-factory-provider.patch | 0 ...mize-advancement-criteria-triggering.patch | 0 ...043-Configurable-water-flowing-speed.patch | 0 .../server/0044-TickControl-System.patch | 0 55 files changed, 3611 insertions(+), 6937 deletions(-) delete mode 100644 patches/api/0001-Pufferfish-API-Changes.patch rename patches/api/{0002-Purpur-API-Changes.patch => 0001-Purpur-API-Changes.patch} (86%) rename patches/api/{0003-Use-Gradle-Version-Catalogs.patch => 0002-Use-Gradle-Version-Catalogs.patch} (97%) rename patches/api/{0004-Fork-friendly-Rebranding.patch => 0003-Fork-friendly-Rebranding.patch} (100%) rename patches/api/{0005-Plazma-Configurations.patch => 0004-Plazma-Configurations.patch} (100%) rename patches/api/{0006-Various-API-Tweaks.patch => 0005-Various-API-Tweaks.patch} (92%) delete mode 100644 patches/server/0001-Pufferfish-Server-Changes.patch rename patches/server/{0002-Purpur-Server-Changes.patch => 0001-Purpur-Server-Changes.patch} (85%) rename patches/server/{0003-Build-System-Changes.patch => 0002-Build-System-Changes.patch} (90%) rename patches/server/{0004-Fork-friendly-Rebranding.patch => 0003-Fork-friendly-Rebranding.patch} (95%) rename patches/server/{0005-Rebrand-Logo.patch => 0004-Rebrand-Logo.patch} (100%) rename patches/server/{0006-Plazma-Configurations.patch => 0005-Plazma-Configurations.patch} (95%) rename patches/server/{0007-Setup-basic-configuration-sections.patch => 0006-Setup-basic-configuration-sections.patch} (100%) rename patches/server/{0008-Warn-on-startup.patch => 0007-Warn-on-startup.patch} (96%) rename patches/server/{0009-Always-agree-EULA-on-development-mode.patch => 0008-Always-agree-EULA-on-development-mode.patch} (89%) rename patches/server/{0010-Add-more-metrics.patch => 0009-Add-more-metrics.patch} (98%) rename patches/server/{0011-Optimize-default-configurations.patch => 0010-Optimize-default-configurations.patch} (85%) rename patches/server/{0012-Add-an-option-to-apply-the-configuration-to-the-vani.patch => 0011-Add-an-option-to-apply-the-configuration-to-the-vani.patch} (97%) rename patches/server/{0013-Tweak-console-logging.patch => 0012-Tweak-console-logging.patch} (92%) rename patches/server/{0014-Add-missing-purpur-configuration-options.patch => 0013-Add-missing-purpur-configuration-options.patch} (83%) rename patches/server/{0015-Add-option-to-change-nether-portal-size.patch => 0014-Add-option-to-change-nether-portal-size.patch} (51%) rename patches/server/{0016-Apply-various-optimizations.patch => 0015-Apply-various-optimizations.patch} (87%) rename patches/server/{0017-Do-not-load-chunks-to-spawn-phantom.patch => 0016-Do-not-load-chunks-to-spawn-phantom.patch} (95%) rename patches/server/{0018-Add-option-to-disable-moved-to-quickly-check-for-spe.patch => 0017-Add-option-to-disable-moved-to-quickly-check-for-spe.patch} (57%) rename patches/server/{0019-Configurable-cave-lava-sea-level.patch => 0018-Configurable-cave-lava-sea-level.patch} (97%) rename patches/{ => unapplied}/server/0032-Add-some-missing-Pufferfish-configurations.patch (100%) rename patches/{ => works}/server/0020-Configurable-entity-sensor-tick.patch (100%) rename patches/{ => works}/server/0021-Variable-entity-wakeup-duration.patch (100%) rename patches/{ => works}/server/0022-Optimise-state-lookup-more.patch (100%) rename patches/{ => works}/server/0023-Skip-event-if-no-listeners.patch (100%) rename patches/{ => works}/server/0024-Add-entity-spawn-deadlock-timer.patch (100%) rename patches/{ => works}/server/0025-Lithium-HashedList.patch (100%) rename patches/{ => works}/server/0026-Improve-SwingTime-ticking.patch (100%) rename patches/{ => works}/server/0027-Save-Json-list-asynchronously.patch (100%) rename patches/{ => works}/server/0028-Process-pathfinding-asynchronously.patch (100%) rename patches/{ => works}/server/0029-Use-Akair-s-flag-when-running-the-test-server-with-g.patch (100%) rename patches/{ => works}/server/0030-Use-Plazma-logo-instead-if-server-favicon-doesn-t-ex.patch (100%) rename patches/{ => works}/server/0031-Implement-FreedomChat.patch (100%) rename patches/{ => works}/server/0033-Port-SparklyPaper-patches.patch (100%) rename patches/{ => works}/server/0034-Add-more-MSPT.patch (100%) rename patches/{ => works}/server/0035-Reset-dirty-flag-when-loading-maps-from-the-disk.patch (100%) rename patches/{ => works}/server/0036-Allow-throttling-hopper-checks-if-the-target-contain.patch (100%) rename patches/{ => works}/server/0037-Suppress-errors-from-dirty-attributes.patch (100%) rename patches/{ => works}/server/0038-Implement-Rail-Optimazition.patch (100%) rename patches/{ => works}/server/0039-Implement-alternative-noise-chunk-generator.patch (100%) rename patches/{ => works}/server/0040-Load-player-data-asynchronously.patch (100%) rename patches/{ => works}/server/0041-Configurable-RandomSource-factory-provider.patch (100%) rename patches/{ => works}/server/0042-Optimize-advancement-criteria-triggering.patch (100%) rename patches/{ => works}/server/0043-Configurable-water-flowing-speed.patch (100%) rename patches/{ => works}/server/0044-TickControl-System.patch (100%) diff --git a/buildSrc/src/main/kotlin/org/plazmamc/alwaysuptodate/tasks/PurpurUpdateTask.kt b/buildSrc/src/main/kotlin/org/plazmamc/alwaysuptodate/tasks/PurpurUpdateTask.kt index e566611..f32f0c0 100644 --- a/buildSrc/src/main/kotlin/org/plazmamc/alwaysuptodate/tasks/PurpurUpdateTask.kt +++ b/buildSrc/src/main/kotlin/org/plazmamc/alwaysuptodate/tasks/PurpurUpdateTask.kt @@ -97,7 +97,7 @@ abstract class PurpurUpdateTask : Task() { fun checkout( name: String, repo: Provider, ref: Provider, regex: String, block: CheckoutRepo.() -> Unit - ): Pair, Directory> { + ): Pair, Directory> { val updatePaper = configureTask("update${name}Paper", "Update $name's Paper") { this.repo.convention(extension.paperRepo) this.ref.convention(extension.paperRef) @@ -113,10 +113,10 @@ abstract class PurpurUpdateTask : Task() { this.workDir.set(wd) this.block() - this.finalizedBy(updatePaper) + // this.finalizedBy(updatePaper) } - return updatePaper to checkout.flatMap { it.outputDir }.get() + return checkout to checkout.flatMap { it.outputDir }.get() } val (checkoutPufferfish, pufferfish) = @@ -124,9 +124,7 @@ abstract class PurpurUpdateTask : Task() { onlyIf { extension { usePufferfish } } } val (checkoutPurpur, purpur) = - checkout("Purpur", extension.purpurRepo, extension.purpurRef, "paperCommit = ") { - dependsOn(checkoutPufferfish) - } + checkout("Purpur", extension.purpurRepo, extension.purpurRef, "paperCommit = ") {} pufferfishDir.set(pufferfish) purpurDir.set(purpur) @@ -245,7 +243,7 @@ abstract class PurpurUpdateTask : Task() { @OptIn(ExperimentalPathApi::class) private fun Path.copyPatch(to: Path, vararg name: String) = walk().sorted() - .filter { entry -> name.any { entry.name.endsWith("$it.patch") } }.map(Path::toFile) + .filter { entry -> name.filter { it != "" }.any { entry.name.endsWith("$it.patch") } }.map(Path::toFile) .forEachIndexed { count, patch -> patch.copyTo( to.resolve("${count + 1}".padStart(4, '0') + "-" + name.first { patch.name.substring(5) == "$it.patch" } + ".patch").toFile(), diff --git a/gradle.properties b/gradle.properties index 88a817d..331ebe5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,17 +13,17 @@ brandName = Plazma providerName = PlazmaMC providerRepo = PlazmaMC/PlazmaBukkit -version = 1.21.1-R0.1-SNAPSHOT -mcVersion = 1.21.1 +version = 1.21.3-R0.1-SNAPSHOT +mcVersion = 1.21.3 jdkVersion = 21 paperRepo = https://github.com/PaperMC/Paper paperBranch = master purpurRepo = https://github.com/PurpurMC/Purpur -purpurBranch = ver/1.21.1 +purpurBranch = ver/1.21.3 pufferfishRepo = https://github.com/pufferfish-gg/Pufferfish pufferfishBranch = ver/1.21 -usePufferfish = true +usePufferfish = false -paperCommit = d348cb88a9fe8d19e46102c8b9febe18f746d46b -purpurCommit = 4b57bed513aaadb0a1ecebae3796a5e93b7561ea +paperCommit = 6288adb001b71a2f2a0a1866fc406016ada06bb5 +purpurCommit = 89e388c3a2c40b61e8e34ec03fcf1af735396af2 diff --git a/libs/server.versions.toml b/libs/server.versions.toml index 8f58905..1dbea69 100644 --- a/libs/server.versions.toml +++ b/libs/server.versions.toml @@ -5,9 +5,9 @@ upnp = "1.0" ansi = "1.0.3" jansi = "3.21.0" rhino = "1.7.14" -mysql = "8.4.0" +mysql = "9.1.0" flare = "34637f3f87" -sqlite = "3.46.0.0" +sqlite = "3.46.1.3" pioneer = "2.2.0" haproxy = "4.1.97.Final" rewriter = "0.0.3" diff --git a/patches/api/0001-Pufferfish-API-Changes.patch b/patches/api/0001-Pufferfish-API-Changes.patch deleted file mode 100644 index e5f5047..0000000 --- a/patches/api/0001-Pufferfish-API-Changes.patch +++ /dev/null @@ -1,527 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kevin Raneri -Date: Tue, 22 Oct 2024 07:31:43 +0900 -Subject: [PATCH] Pufferfish API Changes - -Pufferfish -Copyright (C) 2024 Pufferfish Studios LLC - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -diff --git a/build.gradle.kts b/build.gradle.kts -index e7c96be769fde8375b9a1b128cc7ce474144d16d..f9b44a03fe8d9a2fea2d968f4e944a6663c6f9c9 100644 ---- a/build.gradle.kts -+++ b/build.gradle.kts -@@ -52,6 +52,7 @@ dependencies { - apiAndDocs("net.kyori:adventure-text-logger-slf4j") - api("org.apache.logging.log4j:log4j-api:$log4jVersion") - api("org.slf4j:slf4j-api:$slf4jVersion") -+ api("io.sentry:sentry:5.4.0") // Pufferfish - - implementation("org.ow2.asm:asm:9.7.1") - implementation("org.ow2.asm:asm-commons:9.7.1") -@@ -131,6 +132,13 @@ val generateApiVersioningFile by tasks.registering { - } - } - -+// Pufferfish Start -+tasks.withType { -+ val compilerArgs = options.compilerArgs -+ compilerArgs.add("--add-modules=jdk.incubator.vector") -+} -+// Pufferfish End -+ - tasks.jar { - from(generateApiVersioningFile.map { it.outputs.files.singleFile }) { - into("META-INF/maven/${project.group}/${project.name}") -diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java -new file mode 100644 -index 0000000000000000000000000000000000000000..10310fdd53de28efb8a8250f6d3b0c8eb08fb68a ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java -@@ -0,0 +1,161 @@ -+package gg.pufferfish.pufferfish.sentry; -+ -+import com.google.gson.Gson; -+import java.lang.reflect.Field; -+import java.lang.reflect.Modifier; -+import java.util.Map; -+import java.util.TreeMap; -+import org.apache.logging.log4j.ThreadContext; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Event; -+import org.bukkit.event.player.PlayerEvent; -+import org.bukkit.plugin.Plugin; -+import org.bukkit.plugin.RegisteredListener; -+import org.jetbrains.annotations.Nullable; -+ -+public class SentryContext { -+ -+ private static final Gson GSON = new Gson(); -+ -+ public static void setPluginContext(@Nullable Plugin plugin) { -+ if (plugin != null) { -+ ThreadContext.put("pufferfishsentry_pluginname", plugin.getName()); -+ ThreadContext.put("pufferfishsentry_pluginversion", plugin.getDescription().getVersion()); -+ } -+ } -+ -+ public static void removePluginContext() { -+ ThreadContext.remove("pufferfishsentry_pluginname"); -+ ThreadContext.remove("pufferfishsentry_pluginversion"); -+ } -+ -+ public static void setSenderContext(@Nullable CommandSender sender) { -+ if (sender != null) { -+ ThreadContext.put("pufferfishsentry_playername", sender.getName()); -+ if (sender instanceof Player player) { -+ ThreadContext.put("pufferfishsentry_playerid", player.getUniqueId().toString()); -+ } -+ } -+ } -+ -+ public static void removeSenderContext() { -+ ThreadContext.remove("pufferfishsentry_playername"); -+ ThreadContext.remove("pufferfishsentry_playerid"); -+ } -+ -+ public static void setEventContext(Event event, RegisteredListener registration) { -+ setPluginContext(registration.getPlugin()); -+ -+ try { -+ // Find the player that was involved with this event -+ Player player = null; -+ if (event instanceof PlayerEvent) { -+ player = ((PlayerEvent) event).getPlayer(); -+ } else { -+ Class eventClass = event.getClass(); -+ -+ Field playerField = null; -+ -+ for (Field field : eventClass.getDeclaredFields()) { -+ if (field.getType().equals(Player.class)) { -+ playerField = field; -+ break; -+ } -+ } -+ -+ if (playerField != null) { -+ playerField.setAccessible(true); -+ player = (Player) playerField.get(event); -+ } -+ } -+ -+ if (player != null) { -+ setSenderContext(player); -+ } -+ } catch (Exception e) {} // We can't really safely log exceptions. -+ -+ ThreadContext.put("pufferfishsentry_eventdata", GSON.toJson(serializeFields(event))); -+ } -+ -+ public static void removeEventContext() { -+ removePluginContext(); -+ removeSenderContext(); -+ ThreadContext.remove("pufferfishsentry_eventdata"); -+ } -+ -+ private static Map serializeFields(Object object) { -+ Map fields = new TreeMap<>(); -+ fields.put("_class", object.getClass().getName()); -+ for (Field declaredField : object.getClass().getDeclaredFields()) { -+ try { -+ if (Modifier.isStatic(declaredField.getModifiers())) { -+ continue; -+ } -+ -+ String fieldName = declaredField.getName(); -+ if (fieldName.equals("handlers")) { -+ continue; -+ } -+ declaredField.setAccessible(true); -+ Object value = declaredField.get(object); -+ if (value != null) { -+ fields.put(fieldName, value.toString()); -+ } else { -+ fields.put(fieldName, ""); -+ } -+ } catch (Exception e) {} // We can't really safely log exceptions. -+ } -+ return fields; -+ } -+ -+ public static class State { -+ -+ private Plugin plugin; -+ private Command command; -+ private String commandLine; -+ private Event event; -+ private RegisteredListener registeredListener; -+ -+ public Plugin getPlugin() { -+ return plugin; -+ } -+ -+ public void setPlugin(Plugin plugin) { -+ this.plugin = plugin; -+ } -+ -+ public Command getCommand() { -+ return command; -+ } -+ -+ public void setCommand(Command command) { -+ this.command = command; -+ } -+ -+ public String getCommandLine() { -+ return commandLine; -+ } -+ -+ public void setCommandLine(String commandLine) { -+ this.commandLine = commandLine; -+ } -+ -+ public Event getEvent() { -+ return event; -+ } -+ -+ public void setEvent(Event event) { -+ this.event = event; -+ } -+ -+ public RegisteredListener getRegisteredListener() { -+ return registeredListener; -+ } -+ -+ public void setRegisteredListener(RegisteredListener registeredListener) { -+ this.registeredListener = registeredListener; -+ } -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3441cdad70da1bd523c5933b1a914688718c2657 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java -@@ -0,0 +1,40 @@ -+package gg.pufferfish.pufferfish.simd; -+ -+import java.util.logging.Level; -+import java.util.logging.Logger; -+import jdk.incubator.vector.FloatVector; -+import jdk.incubator.vector.IntVector; -+import jdk.incubator.vector.VectorSpecies; -+ -+/** -+ * Basically, java is annoying and we have to push this out to its own class. -+ */ -+@Deprecated -+public class SIMDChecker { -+ -+ @Deprecated -+ public static boolean canEnable(Logger logger) { -+ try { -+ if (SIMDDetection.getJavaVersion() < 17 || SIMDDetection.getJavaVersion() > 21) { -+ return false; -+ } else { -+ SIMDDetection.testRun = true; -+ -+ VectorSpecies ISPEC = IntVector.SPECIES_PREFERRED; -+ VectorSpecies FSPEC = FloatVector.SPECIES_PREFERRED; -+ -+ logger.log(Level.INFO, "Max SIMD vector size on this system is " + ISPEC.vectorBitSize() + " bits (int)"); -+ logger.log(Level.INFO, "Max SIMD vector size on this system is " + FSPEC.vectorBitSize() + " bits (float)"); -+ -+ if (ISPEC.elementSize() < 2 || FSPEC.elementSize() < 2) { -+ logger.log(Level.WARNING, "SIMD is not properly supported on this system!"); -+ return false; -+ } -+ -+ return true; -+ } -+ } catch (NoClassDefFoundError | Exception ignored) {} // Basically, we don't do anything. This lets us detect if it's not functional and disable it. -+ return false; -+ } -+ -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java -new file mode 100644 -index 0000000000000000000000000000000000000000..a84889d3e9cfc4d7ab5f867820a6484c6070711b ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java -@@ -0,0 +1,35 @@ -+package gg.pufferfish.pufferfish.simd; -+ -+import java.util.logging.Logger; -+ -+@Deprecated -+public class SIMDDetection { -+ -+ public static boolean isEnabled = false; -+ public static boolean versionLimited = false; -+ public static boolean testRun = false; -+ -+ @Deprecated -+ public static boolean canEnable(Logger logger) { -+ try { -+ return SIMDChecker.canEnable(logger); -+ } catch (NoClassDefFoundError | Exception ignored) { -+ return false; -+ } -+ } -+ -+ @Deprecated -+ public static int getJavaVersion() { -+ // https://stackoverflow.com/a/2591122 -+ String version = System.getProperty("java.version"); -+ if(version.startsWith("1.")) { -+ version = version.substring(2, 3); -+ } else { -+ int dot = version.indexOf("."); -+ if(dot != -1) { version = version.substring(0, dot); } -+ } -+ version = version.split("-")[0]; // Azul is stupid -+ return Integer.parseInt(version); -+ } -+ -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java b/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ae2464920c9412ac90b819a540ee58be0741465f ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java -@@ -0,0 +1,83 @@ -+package gg.pufferfish.pufferfish.simd; -+ -+import java.awt.Color; -+import jdk.incubator.vector.FloatVector; -+import jdk.incubator.vector.IntVector; -+import jdk.incubator.vector.VectorMask; -+import jdk.incubator.vector.VectorSpecies; -+import org.bukkit.map.MapPalette; -+ -+@Deprecated -+public class VectorMapPalette { -+ -+ private static final VectorSpecies I_SPEC = IntVector.SPECIES_PREFERRED; -+ private static final VectorSpecies F_SPEC = FloatVector.SPECIES_PREFERRED; -+ -+ @Deprecated -+ public static void matchColorVectorized(int[] in, byte[] out) { -+ int speciesLength = I_SPEC.length(); -+ int i; -+ for (i = 0; i < in.length - speciesLength; i += speciesLength) { -+ float[] redsArr = new float[speciesLength]; -+ float[] bluesArr = new float[speciesLength]; -+ float[] greensArr = new float[speciesLength]; -+ int[] alphasArr = new int[speciesLength]; -+ -+ for (int j = 0; j < speciesLength; j++) { -+ alphasArr[j] = (in[i + j] >> 24) & 0xFF; -+ redsArr[j] = (in[i + j] >> 16) & 0xFF; -+ greensArr[j] = (in[i + j] >> 8) & 0xFF; -+ bluesArr[j] = (in[i + j] >> 0) & 0xFF; -+ } -+ -+ IntVector alphas = IntVector.fromArray(I_SPEC, alphasArr, 0); -+ FloatVector reds = FloatVector.fromArray(F_SPEC, redsArr, 0); -+ FloatVector greens = FloatVector.fromArray(F_SPEC, greensArr, 0); -+ FloatVector blues = FloatVector.fromArray(F_SPEC, bluesArr, 0); -+ IntVector resultIndex = IntVector.zero(I_SPEC); -+ VectorMask modificationMask = VectorMask.fromLong(I_SPEC, 0xffffffff); -+ -+ modificationMask = modificationMask.and(alphas.lt(128).not()); -+ FloatVector bestDistances = FloatVector.broadcast(F_SPEC, Float.MAX_VALUE); -+ -+ for (int c = 4; c < MapPalette.colors.length; c++) { -+ // We're using 32-bit floats here because it's 2x faster and nobody will know the difference. -+ // For correctness, the original algorithm uses 64-bit floats instead. Completely unnecessary. -+ FloatVector compReds = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getRed()); -+ FloatVector compGreens = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getGreen()); -+ FloatVector compBlues = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getBlue()); -+ -+ FloatVector rMean = reds.add(compReds).div(2.0f); -+ FloatVector rDiff = reds.sub(compReds); -+ FloatVector gDiff = greens.sub(compGreens); -+ FloatVector bDiff = blues.sub(compBlues); -+ -+ FloatVector weightR = rMean.div(256.0f).add(2); -+ FloatVector weightG = FloatVector.broadcast(F_SPEC, 4.0f); -+ FloatVector weightB = FloatVector.broadcast(F_SPEC, 255.0f).sub(rMean).div(256.0f).add(2.0f); -+ -+ FloatVector distance = weightR.mul(rDiff).mul(rDiff).add(weightG.mul(gDiff).mul(gDiff)).add(weightB.mul(bDiff).mul(bDiff)); -+ -+ // Now we compare to the best distance we've found. -+ // This mask contains a "1" if better, and a "0" otherwise. -+ VectorMask bestDistanceMask = distance.lt(bestDistances); -+ bestDistances = bestDistances.blend(distance, bestDistanceMask); // Update the best distances -+ -+ // Update the result array -+ // We also AND with the modification mask because we don't want to interfere if the alpha value isn't large enough. -+ resultIndex = resultIndex.blend(c, bestDistanceMask.cast(I_SPEC).and(modificationMask)); // Update the results -+ } -+ -+ for (int j = 0; j < speciesLength; j++) { -+ int index = resultIndex.lane(j); -+ out[i + j] = (byte) (index < 128 ? index : -129 + (index - 127)); -+ } -+ } -+ -+ // For the final ones, fall back to the regular method -+ for (; i < in.length; i++) { -+ out[i] = MapPalette.matchColor(new Color(in[i], true)); -+ } -+ } -+ -+} -diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java -index c80faa079eca1564847070f0338fc98024639829..e632d51d3487eb4807243b6705999ad124466bf5 100644 ---- a/src/main/java/org/bukkit/map/MapPalette.java -+++ b/src/main/java/org/bukkit/map/MapPalette.java -@@ -1,6 +1,7 @@ - package org.bukkit.map; - - import com.google.common.base.Preconditions; -+import gg.pufferfish.pufferfish.simd.SIMDDetection; // Pufferfish - import java.awt.Color; - import java.awt.Graphics2D; - import java.awt.Image; -@@ -40,7 +41,7 @@ public final class MapPalette { - } - - @NotNull -- static final Color[] colors = { -+ public static final Color[] colors = { // Pufferfish - public access - c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0), - c(89, 125, 39), c(109, 153, 48), c(127, 178, 56), c(67, 94, 29), - c(174, 164, 115), c(213, 201, 140), c(247, 233, 163), c(130, 123, 86), -@@ -211,9 +212,15 @@ public final class MapPalette { - temp.getRGB(0, 0, temp.getWidth(), temp.getHeight(), pixels, 0, temp.getWidth()); - - byte[] result = new byte[temp.getWidth() * temp.getHeight()]; -+ // Pufferfish start -+ if (!SIMDDetection.isEnabled) { - for (int i = 0; i < pixels.length; i++) { - result[i] = matchColor(new Color(pixels[i], true)); - } -+ } else { -+ gg.pufferfish.pufferfish.simd.VectorMapPalette.matchColorVectorized(pixels, result); -+ } -+ // Pufferfish end - return result; - } - -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 003bece642b682985625db93cad93026352bfc66..e8ba4f1108f2548a487877027e37d81fc150e042 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -597,7 +597,9 @@ public final class SimplePluginManager implements PluginManager { - - // Paper start - private void handlePluginException(String msg, Throwable ex, Plugin plugin) { -+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish - server.getLogger().log(Level.SEVERE, msg, ex); -+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish - callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin))); - } - // Paper end -@@ -667,9 +669,11 @@ public final class SimplePluginManager implements PluginManager { - )); - } - } catch (Throwable ex) { -+ gg.pufferfish.pufferfish.sentry.SentryContext.setEventContext(event, registration); // Pufferfish - // Paper start - error reporting - String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(); - server.getLogger().log(Level.SEVERE, msg, ex); -+ gg.pufferfish.pufferfish.sentry.SentryContext.removeEventContext(); // Pufferfish - if (!(event instanceof com.destroystokyo.paper.event.server.ServerExceptionEvent)) { // We don't want to cause an endless event loop - callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event))); - } -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index eaefbb00e9993d54906cc8cf35cf753c0d6c7707..301e82369603f3dd6e6c1bd380da4bacacd7ef6c 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -336,7 +336,13 @@ public final class JavaPluginLoader implements PluginLoader { - try { - jPlugin.setEnabled(true); - } catch (Throwable ex) { -+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish - server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish -+ // Paper start - Disable plugins that fail to load -+ this.server.getPluginManager().disablePlugin(jPlugin); -+ return; -+ // Paper end - } - - // Perhaps abort here, rather than continue going, but as it stands, -@@ -361,7 +367,9 @@ public final class JavaPluginLoader implements PluginLoader { - try { - jPlugin.setEnabled(false); - } catch (Throwable ex) { -+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish - server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); -+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish - } - - if (cloader instanceof PluginClassLoader) { -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 7e4f7cb2afbc145e532285c793573ad107bc3033..12449e18180d604e9cbbc744da74a8b222a18e1f 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -50,6 +50,8 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm - private io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup classLoaderGroup; // Paper - public io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext; // Paper - -+ private boolean closed = false; // Pufferfish -+ - static { - ClassLoader.registerAsParallelCapable(); - } -@@ -197,6 +199,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm - throw new ClassNotFoundException(name); - } - -+ public boolean _airplane_hasClass(@NotNull String name) { return this.classes.containsKey(name); } // Pufferfish - @Override - protected Class findClass(String name) throws ClassNotFoundException { - if (name.startsWith("org.bukkit.") || name.startsWith("net.minecraft.")) { -@@ -204,7 +207,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm - } - Class result = classes.get(name); - -- if (result == null) { -+ if (result == null && !this.closed) { // Pufferfish - String path = name.replace('.', '/').concat(".class"); - JarEntry entry = jar.getJarEntry(path); - -@@ -251,6 +254,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm - this.setClass(name, result); // Paper - } - -+ if (result == null) throw new ClassNotFoundException(name); // Pufferfish - return result; - } - -@@ -265,6 +269,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm - // Paper end - super.close(); - } finally { -+ this.closed = true; // Pufferfish - jar.close(); - } - } diff --git a/patches/api/0002-Purpur-API-Changes.patch b/patches/api/0001-Purpur-API-Changes.patch similarity index 86% rename from patches/api/0002-Purpur-API-Changes.patch rename to patches/api/0001-Purpur-API-Changes.patch index 91f46a8..98125ff 100644 --- a/patches/api/0002-Purpur-API-Changes.patch +++ b/patches/api/0001-Purpur-API-Changes.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: granny -Date: Tue, 22 Oct 2024 07:33:42 +0900 +Date: Wed, 30 Oct 2024 13:25:01 +0900 Subject: [PATCH] Purpur API Changes PurpurMC @@ -25,10 +25,32 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/build.gradle.kts b/build.gradle.kts -index f9b44a03fe8d9a2fea2d968f4e944a6663c6f9c9..f536f8f42b99e4b7dc2e25785617837fbc405b5b 100644 +index 254fd96d3950b4494c7e43547b00b5175ee53c93..628ec6699d34c1877c02001de95096bc7b44120e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -151,6 +151,8 @@ tasks.jar { +@@ -52,6 +52,7 @@ dependencies { + apiAndDocs("net.kyori:adventure-text-logger-slf4j") + api("org.apache.logging.log4j:log4j-api:$log4jVersion") + api("org.slf4j:slf4j-api:$slf4jVersion") ++ api("io.sentry:sentry:5.4.0") // Pufferfish + + implementation("org.ow2.asm:asm:9.7.1") + implementation("org.ow2.asm:asm-commons:9.7.1") +@@ -135,6 +136,13 @@ val generateApiVersioningFile by tasks.registering { + } + } + ++// Pufferfish Start ++tasks.withType { ++ val compilerArgs = options.compilerArgs ++ compilerArgs.add("--add-modules=jdk.incubator.vector") ++} ++// Pufferfish End ++ + tasks.jar { + from(generateApiVersioningFile.map { it.outputs.files.singleFile }) { + into("META-INF/maven/${project.group}/${project.name}") +@@ -147,6 +155,8 @@ tasks.jar { } tasks.withType { @@ -104,7 +126,7 @@ index 4195efcfe044618052bb03dea34a4fb2ca7c44f0..8709c955bac34bc546a8e022cfac808b void close(); } diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java -index e81d0bc309de877ed2b5da6122f55c162e9b5f10..3d663104c8e3089abdb9dc4d7309f873ac182e98 100644 +index 95b7cdf0677ef71e6885fa78aa5c75bb500f5f53..27a02f0c3261067d8e4ee6169c62cecbbfe50d42 100644 --- a/src/main/java/co/aikar/timings/Timings.java +++ b/src/main/java/co/aikar/timings/Timings.java @@ -124,7 +124,7 @@ public final class Timings { @@ -116,23 +138,17 @@ index e81d0bc309de877ed2b5da6122f55c162e9b5f10..3d663104c8e3089abdb9dc4d7309f873 return timing; } -@@ -145,9 +145,11 @@ public final class Timings { - * @param enabled Should timings be reported +@@ -146,7 +146,7 @@ public final class Timings { */ public static void setTimingsEnabled(boolean enabled) { -- timingsEnabled = enabled; -- warnAboutDeprecationOnEnable(); -- reset(); -+ // Purpur start - we don't do that here... -+ timingsEnabled = false; -+ //warnAboutDeprecationOnEnable(); -+ //reset(); -+ // Purpur end + if (enabled && !warnedAboutDeprecationOnEnable) { +- Bukkit.getLogger().severe(PlainTextComponentSerializer.plainText().serialize(deprecationMessage())); ++ //Bukkit.getLogger().severe(PlainTextComponentSerializer.plainText().serialize(deprecationMessage())); + warnedAboutDeprecationOnEnable = true; + } } - - private static void warnAboutDeprecationOnEnable() { diff --git a/src/main/java/co/aikar/timings/TimingsCommand.java b/src/main/java/co/aikar/timings/TimingsCommand.java -index 95d87c9dbf2b237787294dfbe7fed87a36e6dedf..9e165525c4c4c07c783ae2899e07c37ae49ec2de 100644 +index b83e5ff7ada8771fdf27ba9807c77ba6a4ce12da..f28eec202237461cb489a2b13289d813381a25bc 100644 --- a/src/main/java/co/aikar/timings/TimingsCommand.java +++ b/src/main/java/co/aikar/timings/TimingsCommand.java @@ -47,7 +47,7 @@ public class TimingsCommand extends BukkitCommand { @@ -144,24 +160,19 @@ index 95d87c9dbf2b237787294dfbe7fed87a36e6dedf..9e165525c4c4c07c783ae2899e07c37a this.setPermission("bukkit.command.timings"); } -@@ -56,8 +56,14 @@ public class TimingsCommand extends BukkitCommand { - if (!testPermission(sender)) { +@@ -57,7 +57,10 @@ public class TimingsCommand extends BukkitCommand { return true; } -- if (false) { + if (true) { - sender.sendMessage(Timings.deprecationMessage()); -+ // Purpur start -+ if (true) { + net.kyori.adventure.text.minimessage.MiniMessage mm = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage(); + sender.sendMessage(mm.deserialize("Purpur has removed timings to save your performance. Please use /spark instead")); + sender.sendMessage(mm.deserialize("For more information, view its documentation at")); -+ sender.sendMessage(mm.deserialize("https://spark.lucko.me/docs/Command-Usage")); -+ return true; -+ // Purpur end ++ sender.sendMessage(mm.deserialize("https://spark.lucko.me/docs/Command-Usage")); // Purpur + return true; } if (args.length < 1) { - sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED)); -@@ -117,7 +123,7 @@ public class TimingsCommand extends BukkitCommand { +@@ -118,7 +121,7 @@ public class TimingsCommand extends BukkitCommand { Preconditions.checkNotNull(args, "Arguments cannot be null"); Preconditions.checkNotNull(alias, "Alias cannot be null"); @@ -187,6 +198,349 @@ index 023cc52a9e28e1238c7452c0f3f577f2850fd861..00b3f46ddd26ae08744d3dba211f9262 @ApiStatus.Internal class DummyVersionFetcher implements VersionFetcher { +diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java +new file mode 100644 +index 0000000000000000000000000000000000000000..10310fdd53de28efb8a8250f6d3b0c8eb08fb68a +--- /dev/null ++++ b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java +@@ -0,0 +1,161 @@ ++package gg.pufferfish.pufferfish.sentry; ++ ++import com.google.gson.Gson; ++import java.lang.reflect.Field; ++import java.lang.reflect.Modifier; ++import java.util.Map; ++import java.util.TreeMap; ++import org.apache.logging.log4j.ThreadContext; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Event; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.RegisteredListener; ++import org.jetbrains.annotations.Nullable; ++ ++public class SentryContext { ++ ++ private static final Gson GSON = new Gson(); ++ ++ public static void setPluginContext(@Nullable Plugin plugin) { ++ if (plugin != null) { ++ ThreadContext.put("pufferfishsentry_pluginname", plugin.getName()); ++ ThreadContext.put("pufferfishsentry_pluginversion", plugin.getDescription().getVersion()); ++ } ++ } ++ ++ public static void removePluginContext() { ++ ThreadContext.remove("pufferfishsentry_pluginname"); ++ ThreadContext.remove("pufferfishsentry_pluginversion"); ++ } ++ ++ public static void setSenderContext(@Nullable CommandSender sender) { ++ if (sender != null) { ++ ThreadContext.put("pufferfishsentry_playername", sender.getName()); ++ if (sender instanceof Player player) { ++ ThreadContext.put("pufferfishsentry_playerid", player.getUniqueId().toString()); ++ } ++ } ++ } ++ ++ public static void removeSenderContext() { ++ ThreadContext.remove("pufferfishsentry_playername"); ++ ThreadContext.remove("pufferfishsentry_playerid"); ++ } ++ ++ public static void setEventContext(Event event, RegisteredListener registration) { ++ setPluginContext(registration.getPlugin()); ++ ++ try { ++ // Find the player that was involved with this event ++ Player player = null; ++ if (event instanceof PlayerEvent) { ++ player = ((PlayerEvent) event).getPlayer(); ++ } else { ++ Class eventClass = event.getClass(); ++ ++ Field playerField = null; ++ ++ for (Field field : eventClass.getDeclaredFields()) { ++ if (field.getType().equals(Player.class)) { ++ playerField = field; ++ break; ++ } ++ } ++ ++ if (playerField != null) { ++ playerField.setAccessible(true); ++ player = (Player) playerField.get(event); ++ } ++ } ++ ++ if (player != null) { ++ setSenderContext(player); ++ } ++ } catch (Exception e) {} // We can't really safely log exceptions. ++ ++ ThreadContext.put("pufferfishsentry_eventdata", GSON.toJson(serializeFields(event))); ++ } ++ ++ public static void removeEventContext() { ++ removePluginContext(); ++ removeSenderContext(); ++ ThreadContext.remove("pufferfishsentry_eventdata"); ++ } ++ ++ private static Map serializeFields(Object object) { ++ Map fields = new TreeMap<>(); ++ fields.put("_class", object.getClass().getName()); ++ for (Field declaredField : object.getClass().getDeclaredFields()) { ++ try { ++ if (Modifier.isStatic(declaredField.getModifiers())) { ++ continue; ++ } ++ ++ String fieldName = declaredField.getName(); ++ if (fieldName.equals("handlers")) { ++ continue; ++ } ++ declaredField.setAccessible(true); ++ Object value = declaredField.get(object); ++ if (value != null) { ++ fields.put(fieldName, value.toString()); ++ } else { ++ fields.put(fieldName, ""); ++ } ++ } catch (Exception e) {} // We can't really safely log exceptions. ++ } ++ return fields; ++ } ++ ++ public static class State { ++ ++ private Plugin plugin; ++ private Command command; ++ private String commandLine; ++ private Event event; ++ private RegisteredListener registeredListener; ++ ++ public Plugin getPlugin() { ++ return plugin; ++ } ++ ++ public void setPlugin(Plugin plugin) { ++ this.plugin = plugin; ++ } ++ ++ public Command getCommand() { ++ return command; ++ } ++ ++ public void setCommand(Command command) { ++ this.command = command; ++ } ++ ++ public String getCommandLine() { ++ return commandLine; ++ } ++ ++ public void setCommandLine(String commandLine) { ++ this.commandLine = commandLine; ++ } ++ ++ public Event getEvent() { ++ return event; ++ } ++ ++ public void setEvent(Event event) { ++ this.event = event; ++ } ++ ++ public RegisteredListener getRegisteredListener() { ++ return registeredListener; ++ } ++ ++ public void setRegisteredListener(RegisteredListener registeredListener) { ++ this.registeredListener = registeredListener; ++ } ++ } ++} +diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3441cdad70da1bd523c5933b1a914688718c2657 +--- /dev/null ++++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java +@@ -0,0 +1,40 @@ ++package gg.pufferfish.pufferfish.simd; ++ ++import java.util.logging.Level; ++import java.util.logging.Logger; ++import jdk.incubator.vector.FloatVector; ++import jdk.incubator.vector.IntVector; ++import jdk.incubator.vector.VectorSpecies; ++ ++/** ++ * Basically, java is annoying and we have to push this out to its own class. ++ */ ++@Deprecated ++public class SIMDChecker { ++ ++ @Deprecated ++ public static boolean canEnable(Logger logger) { ++ try { ++ if (SIMDDetection.getJavaVersion() < 17 || SIMDDetection.getJavaVersion() > 21) { ++ return false; ++ } else { ++ SIMDDetection.testRun = true; ++ ++ VectorSpecies ISPEC = IntVector.SPECIES_PREFERRED; ++ VectorSpecies FSPEC = FloatVector.SPECIES_PREFERRED; ++ ++ logger.log(Level.INFO, "Max SIMD vector size on this system is " + ISPEC.vectorBitSize() + " bits (int)"); ++ logger.log(Level.INFO, "Max SIMD vector size on this system is " + FSPEC.vectorBitSize() + " bits (float)"); ++ ++ if (ISPEC.elementSize() < 2 || FSPEC.elementSize() < 2) { ++ logger.log(Level.WARNING, "SIMD is not properly supported on this system!"); ++ return false; ++ } ++ ++ return true; ++ } ++ } catch (NoClassDefFoundError | Exception ignored) {} // Basically, we don't do anything. This lets us detect if it's not functional and disable it. ++ return false; ++ } ++ ++} +diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a84889d3e9cfc4d7ab5f867820a6484c6070711b +--- /dev/null ++++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java +@@ -0,0 +1,35 @@ ++package gg.pufferfish.pufferfish.simd; ++ ++import java.util.logging.Logger; ++ ++@Deprecated ++public class SIMDDetection { ++ ++ public static boolean isEnabled = false; ++ public static boolean versionLimited = false; ++ public static boolean testRun = false; ++ ++ @Deprecated ++ public static boolean canEnable(Logger logger) { ++ try { ++ return SIMDChecker.canEnable(logger); ++ } catch (NoClassDefFoundError | Exception ignored) { ++ return false; ++ } ++ } ++ ++ @Deprecated ++ public static int getJavaVersion() { ++ // https://stackoverflow.com/a/2591122 ++ String version = System.getProperty("java.version"); ++ if(version.startsWith("1.")) { ++ version = version.substring(2, 3); ++ } else { ++ int dot = version.indexOf("."); ++ if(dot != -1) { version = version.substring(0, dot); } ++ } ++ version = version.split("-")[0]; // Azul is stupid ++ return Integer.parseInt(version); ++ } ++ ++} +diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java b/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ae2464920c9412ac90b819a540ee58be0741465f +--- /dev/null ++++ b/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java +@@ -0,0 +1,83 @@ ++package gg.pufferfish.pufferfish.simd; ++ ++import java.awt.Color; ++import jdk.incubator.vector.FloatVector; ++import jdk.incubator.vector.IntVector; ++import jdk.incubator.vector.VectorMask; ++import jdk.incubator.vector.VectorSpecies; ++import org.bukkit.map.MapPalette; ++ ++@Deprecated ++public class VectorMapPalette { ++ ++ private static final VectorSpecies I_SPEC = IntVector.SPECIES_PREFERRED; ++ private static final VectorSpecies F_SPEC = FloatVector.SPECIES_PREFERRED; ++ ++ @Deprecated ++ public static void matchColorVectorized(int[] in, byte[] out) { ++ int speciesLength = I_SPEC.length(); ++ int i; ++ for (i = 0; i < in.length - speciesLength; i += speciesLength) { ++ float[] redsArr = new float[speciesLength]; ++ float[] bluesArr = new float[speciesLength]; ++ float[] greensArr = new float[speciesLength]; ++ int[] alphasArr = new int[speciesLength]; ++ ++ for (int j = 0; j < speciesLength; j++) { ++ alphasArr[j] = (in[i + j] >> 24) & 0xFF; ++ redsArr[j] = (in[i + j] >> 16) & 0xFF; ++ greensArr[j] = (in[i + j] >> 8) & 0xFF; ++ bluesArr[j] = (in[i + j] >> 0) & 0xFF; ++ } ++ ++ IntVector alphas = IntVector.fromArray(I_SPEC, alphasArr, 0); ++ FloatVector reds = FloatVector.fromArray(F_SPEC, redsArr, 0); ++ FloatVector greens = FloatVector.fromArray(F_SPEC, greensArr, 0); ++ FloatVector blues = FloatVector.fromArray(F_SPEC, bluesArr, 0); ++ IntVector resultIndex = IntVector.zero(I_SPEC); ++ VectorMask modificationMask = VectorMask.fromLong(I_SPEC, 0xffffffff); ++ ++ modificationMask = modificationMask.and(alphas.lt(128).not()); ++ FloatVector bestDistances = FloatVector.broadcast(F_SPEC, Float.MAX_VALUE); ++ ++ for (int c = 4; c < MapPalette.colors.length; c++) { ++ // We're using 32-bit floats here because it's 2x faster and nobody will know the difference. ++ // For correctness, the original algorithm uses 64-bit floats instead. Completely unnecessary. ++ FloatVector compReds = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getRed()); ++ FloatVector compGreens = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getGreen()); ++ FloatVector compBlues = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getBlue()); ++ ++ FloatVector rMean = reds.add(compReds).div(2.0f); ++ FloatVector rDiff = reds.sub(compReds); ++ FloatVector gDiff = greens.sub(compGreens); ++ FloatVector bDiff = blues.sub(compBlues); ++ ++ FloatVector weightR = rMean.div(256.0f).add(2); ++ FloatVector weightG = FloatVector.broadcast(F_SPEC, 4.0f); ++ FloatVector weightB = FloatVector.broadcast(F_SPEC, 255.0f).sub(rMean).div(256.0f).add(2.0f); ++ ++ FloatVector distance = weightR.mul(rDiff).mul(rDiff).add(weightG.mul(gDiff).mul(gDiff)).add(weightB.mul(bDiff).mul(bDiff)); ++ ++ // Now we compare to the best distance we've found. ++ // This mask contains a "1" if better, and a "0" otherwise. ++ VectorMask bestDistanceMask = distance.lt(bestDistances); ++ bestDistances = bestDistances.blend(distance, bestDistanceMask); // Update the best distances ++ ++ // Update the result array ++ // We also AND with the modification mask because we don't want to interfere if the alpha value isn't large enough. ++ resultIndex = resultIndex.blend(c, bestDistanceMask.cast(I_SPEC).and(modificationMask)); // Update the results ++ } ++ ++ for (int j = 0; j < speciesLength; j++) { ++ int index = resultIndex.lane(j); ++ out[i + j] = (byte) (index < 128 ? index : -129 + (index - 127)); ++ } ++ } ++ ++ // For the final ones, fall back to the regular method ++ for (; i < in.length; i++) { ++ out[i] = MapPalette.matchColor(new Color(in[i], true)); ++ } ++ } ++ ++} diff --git a/src/main/java/io/papermc/paper/ServerBuildInfo.java b/src/main/java/io/papermc/paper/ServerBuildInfo.java index 652ff54e7c50412503725d628bfe72ed03059790..7196594e07af19a14c320d77df893978525fe386 100644 --- a/src/main/java/io/papermc/paper/ServerBuildInfo.java @@ -427,10 +781,10 @@ index 918a045165cdcde264bc24082b7afebb407271de..e98d6321c5f2cdde91b54f8a74cbcc04 + // Purpur end } diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 77a15a99e441bd81650806142581bd5b24f30e10..3ec2154956087a370799f0fa485f3b6cae894c69 100644 +index 615eb24ffdd8f6d55ccd4f21760b809c1098bc68..fbbe9e52ed3437d2407e042f45b0a18abdd48fe1 100644 --- a/src/main/java/org/bukkit/Material.java +++ b/src/main/java/org/bukkit/Material.java -@@ -5636,4 +5636,40 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla +@@ -5799,4 +5799,40 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla public BlockType asBlockType() { return blockType.get(); } @@ -1167,10 +1521,10 @@ index bc84b892cae5fe7019a3ad481e9da79956efa1fe..48eb5b00c460cccde29d327cef1d63fc + // Purpur end } diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 8086acceacbceb2c5a7228fff005e41a86d37008..65260b33a13858309356d573dfa2989b92e7437c 100644 +index 95f0b3186e313c7fbd5c8531d52b82a69e525f94..a7f989121c493baff9d2b6910c39145a0e12477d 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -3871,4 +3871,123 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -3911,4 +3911,123 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ void sendEntityEffect(org.bukkit.@NotNull EntityEffect effect, @NotNull Entity target); // Paper end - entity effect API @@ -2057,6 +2411,43 @@ index 3c1aa1e036bee08304c1cdca59f6a5bc0ba306c0..709fb2d1c7e3253034a651a9f68c0036 + void setDoUnsafeEnchants(boolean canDoUnsafeEnchants); + // Purpur end } +diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java +index c80faa079eca1564847070f0338fc98024639829..e632d51d3487eb4807243b6705999ad124466bf5 100644 +--- a/src/main/java/org/bukkit/map/MapPalette.java ++++ b/src/main/java/org/bukkit/map/MapPalette.java +@@ -1,6 +1,7 @@ + package org.bukkit.map; + + import com.google.common.base.Preconditions; ++import gg.pufferfish.pufferfish.simd.SIMDDetection; // Pufferfish + import java.awt.Color; + import java.awt.Graphics2D; + import java.awt.Image; +@@ -40,7 +41,7 @@ public final class MapPalette { + } + + @NotNull +- static final Color[] colors = { ++ public static final Color[] colors = { // Pufferfish - public access + c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0), + c(89, 125, 39), c(109, 153, 48), c(127, 178, 56), c(67, 94, 29), + c(174, 164, 115), c(213, 201, 140), c(247, 233, 163), c(130, 123, 86), +@@ -211,9 +212,15 @@ public final class MapPalette { + temp.getRGB(0, 0, temp.getWidth(), temp.getHeight(), pixels, 0, temp.getWidth()); + + byte[] result = new byte[temp.getWidth() * temp.getHeight()]; ++ // Pufferfish start ++ if (!SIMDDetection.isEnabled) { + for (int i = 0; i < pixels.length; i++) { + result[i] = matchColor(new Color(pixels[i], true)); + } ++ } else { ++ gg.pufferfish.pufferfish.simd.VectorMapPalette.matchColorVectorized(pixels, result); ++ } ++ // Pufferfish end + return result; + } + diff --git a/src/main/java/org/bukkit/map/MapRenderer.java b/src/main/java/org/bukkit/map/MapRenderer.java index cb7040876a99a5a7e49b81684ef0f3b79584c376..22d8f31b1b8a5dbb5ab3275068642937c097abfe 100644 --- a/src/main/java/org/bukkit/map/MapRenderer.java @@ -2096,8 +2487,34 @@ index 75b77cc4fe189b4b6baa1af3663dc492e992a266..30b98d1645c571ba5c18e5cc93b0bec3 String lname = name.toLowerCase(Locale.ROOT); permissions.put(lname, new PermissionAttachmentInfo(parent, lname, attachment, value)); +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index b878e7167cfcdea0e224c182b40abeadd339d3b3..6b6edf9007997d9672e4c850464c1b71cb55f6b4 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -597,7 +597,9 @@ public final class SimplePluginManager implements PluginManager { + + // Paper start + private void handlePluginException(String msg, Throwable ex, Plugin plugin) { ++ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish + server.getLogger().log(Level.SEVERE, msg, ex); ++ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish + callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin))); + } + // Paper end +@@ -667,9 +669,11 @@ public final class SimplePluginManager implements PluginManager { + )); + } + } catch (Throwable ex) { ++ gg.pufferfish.pufferfish.sentry.SentryContext.setEventContext(event, registration); // Pufferfish + // Paper start - error reporting + String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(); + server.getLogger().log(Level.SEVERE, msg, ex); ++ gg.pufferfish.pufferfish.sentry.SentryContext.removeEventContext(); // Pufferfish + if (!(event instanceof com.destroystokyo.paper.event.server.ServerExceptionEvent)) { // We don't want to cause an endless event loop + callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event))); + } diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 301e82369603f3dd6e6c1bd380da4bacacd7ef6c..0c6ca7588fb3d6b6497ddf032fe75e5c6c9719e5 100644 +index eaefbb00e9993d54906cc8cf35cf753c0d6c7707..0c6ca7588fb3d6b6497ddf032fe75e5c6c9719e5 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java @@ -55,6 +55,7 @@ public final class JavaPluginLoader implements PluginLoader { @@ -2108,6 +2525,30 @@ index 301e82369603f3dd6e6c1bd380da4bacacd7ef6c..0c6ca7588fb3d6b6497ddf032fe75e5c /** * This class was not meant to be constructed explicitly +@@ -336,7 +337,13 @@ public final class JavaPluginLoader implements PluginLoader { + try { + jPlugin.setEnabled(true); + } catch (Throwable ex) { ++ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish + server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish ++ // Paper start - Disable plugins that fail to load ++ this.server.getPluginManager().disablePlugin(jPlugin); ++ return; ++ // Paper end + } + + // Perhaps abort here, rather than continue going, but as it stands, +@@ -361,7 +368,9 @@ public final class JavaPluginLoader implements PluginLoader { + try { + jPlugin.setEnabled(false); + } catch (Throwable ex) { ++ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish + server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish + } + + if (cloader instanceof PluginClassLoader) { diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java index c66252802c51174bc26f266cb5cdecdd856ff220..97f580fccd06a8db5f592a53c8b95a7a6159adac 100644 --- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java @@ -2136,6 +2577,52 @@ index c66252802c51174bc26f266cb5cdecdd856ff220..97f580fccd06a8db5f592a53c8b95a7a logger.log( Level.INFO, "[{0}] Loaded library {1}", new Object[] { java.util.Objects.requireNonNullElseGet(desc.getPrefix(), desc::getName), file // Paper - use configured log prefix +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 7e4f7cb2afbc145e532285c793573ad107bc3033..12449e18180d604e9cbbc744da74a8b222a18e1f 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -50,6 +50,8 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm + private io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup classLoaderGroup; // Paper + public io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext; // Paper + ++ private boolean closed = false; // Pufferfish ++ + static { + ClassLoader.registerAsParallelCapable(); + } +@@ -197,6 +199,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm + throw new ClassNotFoundException(name); + } + ++ public boolean _airplane_hasClass(@NotNull String name) { return this.classes.containsKey(name); } // Pufferfish + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (name.startsWith("org.bukkit.") || name.startsWith("net.minecraft.")) { +@@ -204,7 +207,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm + } + Class result = classes.get(name); + +- if (result == null) { ++ if (result == null && !this.closed) { // Pufferfish + String path = name.replace('.', '/').concat(".class"); + JarEntry entry = jar.getJarEntry(path); + +@@ -251,6 +254,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm + this.setClass(name, result); // Paper + } + ++ if (result == null) throw new ClassNotFoundException(name); // Pufferfish + return result; + } + +@@ -265,6 +269,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm + // Paper end + super.close(); + } finally { ++ this.closed = true; // Pufferfish + jar.close(); + } + } diff --git a/src/main/java/org/bukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/util/permissions/CommandPermissions.java index 7763d6101ac61900db1e2310966b99584539fd0e..d5a42707d365ffd72532bbb1a59a1ca7145f9918 100644 --- a/src/main/java/org/bukkit/util/permissions/CommandPermissions.java diff --git a/patches/api/0003-Use-Gradle-Version-Catalogs.patch b/patches/api/0002-Use-Gradle-Version-Catalogs.patch similarity index 97% rename from patches/api/0003-Use-Gradle-Version-Catalogs.patch rename to patches/api/0002-Use-Gradle-Version-Catalogs.patch index 56a36c4..9cc2472 100644 --- a/patches/api/0003-Use-Gradle-Version-Catalogs.patch +++ b/patches/api/0002-Use-Gradle-Version-Catalogs.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Use Gradle Version Catalogs diff --git a/build.gradle.kts b/build.gradle.kts -index f536f8f42b99e4b7dc2e25785617837fbc405b5b..51ef37146672e17ac140d260fbc229bcbd4ad049 100644 +index 628ec6699d34c1877c02001de95096bc7b44120e..782a4c89b2f861f4c96718713ed2e4cd443084af 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,11 +9,13 @@ java { @@ -103,7 +103,7 @@ index f536f8f42b99e4b7dc2e25785617837fbc405b5b..51ef37146672e17ac140d260fbc229bc } // Paper start -@@ -158,27 +132,24 @@ tasks.withType { +@@ -162,27 +136,24 @@ tasks.withType { options.use() options.isDocFilesSubDirs = true options.links( diff --git a/patches/api/0004-Fork-friendly-Rebranding.patch b/patches/api/0003-Fork-friendly-Rebranding.patch similarity index 100% rename from patches/api/0004-Fork-friendly-Rebranding.patch rename to patches/api/0003-Fork-friendly-Rebranding.patch diff --git a/patches/api/0005-Plazma-Configurations.patch b/patches/api/0004-Plazma-Configurations.patch similarity index 100% rename from patches/api/0005-Plazma-Configurations.patch rename to patches/api/0004-Plazma-Configurations.patch diff --git a/patches/api/0006-Various-API-Tweaks.patch b/patches/api/0005-Various-API-Tweaks.patch similarity index 92% rename from patches/api/0006-Various-API-Tweaks.patch rename to patches/api/0005-Various-API-Tweaks.patch index 315542f..4b20293 100644 --- a/patches/api/0006-Various-API-Tweaks.patch +++ b/patches/api/0005-Various-API-Tweaks.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Various API Tweaks diff --git a/src/main/java/com/destroystokyo/paper/MaterialTags.java b/src/main/java/com/destroystokyo/paper/MaterialTags.java -index be212b4fbeabab32a4dab6ae554768c368efaa88..2c08e2000fc1c2cfaae9b82c57c0f2a5079311f1 100644 +index 41eaa8159f8c028faa118300e95f6a0fb9cfe989..76a5381a959ae4e153dba291a362f3d58aeceac9 100644 --- a/src/main/java/com/destroystokyo/paper/MaterialTags.java +++ b/src/main/java/com/destroystokyo/paper/MaterialTags.java @@ -584,6 +584,15 @@ public class MaterialTags { diff --git a/patches/generated-api/0001-Purpur-Generated-API-Changes.patch b/patches/generated-api/0001-Purpur-Generated-API-Changes.patch index 4a8d50a..45a7200 100644 --- a/patches/generated-api/0001-Purpur-Generated-API-Changes.patch +++ b/patches/generated-api/0001-Purpur-Generated-API-Changes.patch @@ -25,10 +25,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/com/destroystokyo/paper/entity/ai/VanillaGoal.java -index 02411466bdcf4ff731f01ccebb2c99942e0db878..2718c0e5061838b01881bb231c53f4da348adce3 100644 +index e0aa5b925cbd6c2733ad70cb0722c7ab7c4d0419..51cea31c55c7e1a00cfb966349147fc874e1736b 100644 --- a/com/destroystokyo/paper/entity/ai/VanillaGoal.java +++ b/com/destroystokyo/paper/entity/ai/VanillaGoal.java -@@ -436,6 +436,18 @@ public interface VanillaGoal extends Goal { +@@ -440,6 +440,18 @@ public interface VanillaGoal extends Goal { GoalKey ZOMBIE_ATTACK_TURTLE_EGG = create("zombie_attack_turtle_egg", Zombie.class); diff --git a/patches/server/0001-Pufferfish-Server-Changes.patch b/patches/server/0001-Pufferfish-Server-Changes.patch deleted file mode 100644 index b6e85ca..0000000 --- a/patches/server/0001-Pufferfish-Server-Changes.patch +++ /dev/null @@ -1,2570 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kevin Raneri -Date: Tue, 22 Oct 2024 07:33:50 +0900 -Subject: [PATCH] Pufferfish Server Changes - -Pufferfish -Copyright (C) 2024 Pufferfish Studios LLC - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -diff --git a/build.gradle.kts b/build.gradle.kts -index de0474b8dce58cb419c00b7614d7dd66be832a02..6cfa3f9994de36e135658841aa3c091b90a14424 100644 ---- a/build.gradle.kts -+++ b/build.gradle.kts -@@ -13,7 +13,7 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { - val alsoShade: Configuration by configurations.creating - - dependencies { -- implementation(project(":paper-api")) -+ implementation(project(":pufferfish-api")) // Pufferfish // Paper - // Paper start - implementation("org.jline:jline-terminal-jansi:3.21.0") - implementation("net.minecrell:terminalconsoleappender:1.3.0") -@@ -47,6 +47,13 @@ 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") - -+ // Pufferfish start -+ implementation("org.yaml:snakeyaml:1.32") -+ implementation ("me.carleslc.Simple-YAML:Simple-Yaml:1.8.4") { -+ exclude(group="org.yaml", module="snakeyaml") -+ } -+ // Pufferfish end -+ - 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") -@@ -72,6 +79,14 @@ paperweight { - craftBukkitPackageVersion.set("v1_21_R1") // also needs to be updated in MappingEnvironment - } - -+ -+// Pufferfish Start -+tasks.withType { -+ val compilerArgs = options.compilerArgs -+ compilerArgs.add("--add-modules=jdk.incubator.vector") -+} -+// Pufferfish End -+ - tasks.jar { - archiveClassifier.set("dev") - -@@ -85,14 +100,14 @@ tasks.jar { - val gitBranch = git("rev-parse", "--abbrev-ref", "HEAD").getText().trim() // Paper - attributes( - "Main-Class" to "org.bukkit.craftbukkit.Main", -- "Implementation-Title" to "Paper", -+ "Implementation-Title" to "Pufferfish", // Pufferfish - "Implementation-Version" to implementationVersion, - "Implementation-Vendor" to date, // Paper -- "Specification-Title" to "Paper", -+ "Specification-Title" to "Pufferfish", // Pufferfish - "Specification-Version" to project.version, -- "Specification-Vendor" to "Paper Team", -- "Brand-Id" to "papermc:paper", -- "Brand-Name" to "Paper", -+ "Specification-Vendor" to "Pufferfish Studios LLC", // Pufferfish -+ "Brand-Id" to "pufferfish:pufferfish", // Pufferfish -+ "Brand-Name" to "Pufferfish", // Pufferfish - "Build-Number" to (build ?: ""), - "Build-Time" to Instant.now().toString(), - "Git-Branch" to gitBranch, // Paper -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index 7620c72a4c243cbeea245203ce03a97cbfa7d922..b35a9f4c5f8960864c402ede8a51fb5ab9c4fcc0 100644 ---- a/src/main/java/co/aikar/timings/TimingsExport.java -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -240,7 +240,8 @@ public class TimingsExport extends Thread { - parent.put("config", createObject( - pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), - pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), -- pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) -+ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)), // Pufferfish -+ pair("pufferfish", mapAsJSON(gg.pufferfish.pufferfish.PufferfishConfig.getConfigCopy(), null)) // Pufferfish - )); - - new TimingsExport(listeners, parent, history).start(); -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 4b002e8b75d117b726b0de274a76d3596fce015b..692c962193cf9fcc6801fc93f3220bdc673d527b 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 { - boolean logFailedRequests = config.getBoolean("logFailedRequests", false); - // Only start Metrics, if it's enabled in the config - if (config.getBoolean("enabled", true)) { -- Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); -+ Metrics metrics = new Metrics("Pufferfish", serverUUID, logFailedRequests, Bukkit.getLogger()); // Pufferfish - - metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { - String minecraftVersion = Bukkit.getVersion(); -@@ -607,11 +607,11 @@ public class Metrics { - final String implVersion = org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion(); - if (implVersion != null) { - final String buildOrHash = implVersion.substring(implVersion.lastIndexOf('-') + 1); -- paperVersion = "git-Paper-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash); -+ paperVersion = "git-Pufferfish-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash); // Pufferfish - } else { - paperVersion = "unknown"; - } -- metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> paperVersion)); -+ metrics.addCustomChart(new Metrics.SimplePie("pufferfish_version", () -> paperVersion)); // Pufferfish - - metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { - Map> map = new HashMap<>(); -diff --git a/src/main/java/gg/airplane/structs/FluidDirectionCache.java b/src/main/java/gg/airplane/structs/FluidDirectionCache.java -new file mode 100644 -index 0000000000000000000000000000000000000000..aa8467b9dda1f7707e41f50ac7b3e9d7343723ec ---- /dev/null -+++ b/src/main/java/gg/airplane/structs/FluidDirectionCache.java -@@ -0,0 +1,136 @@ -+package gg.airplane.structs; -+ -+import it.unimi.dsi.fastutil.HashCommon; -+ -+/** -+ * This is a replacement for the cache used in FluidTypeFlowing. -+ * The requirements for the previous cache were: -+ * - Store 200 entries -+ * - Look for the flag in the cache -+ * - If it exists, move to front of cache -+ * - If it doesn't exist, remove last entry in cache and insert in front -+ * -+ * This class accomplishes something similar, however has a few different -+ * requirements put into place to make this more optimize: -+ * -+ * - maxDistance is the most amount of entries to be checked, instead -+ * of having to check the entire list. -+ * - In combination with that, entries are all tracked by age and how -+ * frequently they're used. This enables us to remove old entries, -+ * without constantly shifting any around. -+ * -+ * Usage of the previous map would have to reset the head every single usage, -+ * shifting the entire map. Here, nothing happens except an increment when -+ * the cache is hit, and when it needs to replace an old element only a single -+ * element is modified. -+ */ -+public class FluidDirectionCache { -+ -+ private static class FluidDirectionEntry { -+ private final T data; -+ private final boolean flag; -+ private int uses = 0; -+ private int age = 0; -+ -+ private FluidDirectionEntry(T data, boolean flag) { -+ this.data = data; -+ this.flag = flag; -+ } -+ -+ public int getValue() { -+ return this.uses - (this.age >> 1); // age isn't as important as uses -+ } -+ -+ public void incrementUses() { -+ this.uses = this.uses + 1 & Integer.MAX_VALUE; -+ } -+ -+ public void incrementAge() { -+ this.age = this.age + 1 & Integer.MAX_VALUE; -+ } -+ } -+ -+ private final FluidDirectionEntry[] entries; -+ private final int mask; -+ private final int maxDistance; // the most amount of entries to check for a value -+ -+ public FluidDirectionCache(int size) { -+ int arraySize = HashCommon.nextPowerOfTwo(size); -+ this.entries = new FluidDirectionEntry[arraySize]; -+ this.mask = arraySize - 1; -+ this.maxDistance = Math.min(arraySize, 4); -+ } -+ -+ public Boolean getValue(T data) { -+ FluidDirectionEntry curr; -+ int pos; -+ -+ if ((curr = this.entries[pos = HashCommon.mix(data.hashCode()) & this.mask]) == null) { -+ return null; -+ } else if (data.equals(curr.data)) { -+ curr.incrementUses(); -+ return curr.flag; -+ } -+ -+ int checked = 1; // start at 1 because we already checked the first spot above -+ -+ while ((curr = this.entries[pos = (pos + 1) & this.mask]) != null) { -+ if (data.equals(curr.data)) { -+ curr.incrementUses(); -+ return curr.flag; -+ } else if (++checked >= this.maxDistance) { -+ break; -+ } -+ } -+ -+ return null; -+ } -+ -+ public void putValue(T data, boolean flag) { -+ FluidDirectionEntry curr; -+ int pos; -+ -+ if ((curr = this.entries[pos = HashCommon.mix(data.hashCode()) & this.mask]) == null) { -+ this.entries[pos] = new FluidDirectionEntry<>(data, flag); // add -+ return; -+ } else if (data.equals(curr.data)) { -+ curr.incrementUses(); -+ return; -+ } -+ -+ int checked = 1; // start at 1 because we already checked the first spot above -+ -+ while ((curr = this.entries[pos = (pos + 1) & this.mask]) != null) { -+ if (data.equals(curr.data)) { -+ curr.incrementUses(); -+ return; -+ } else if (++checked >= this.maxDistance) { -+ this.forceAdd(data, flag); -+ return; -+ } -+ } -+ -+ this.entries[pos] = new FluidDirectionEntry<>(data, flag); // add -+ } -+ -+ private void forceAdd(T data, boolean flag) { -+ int expectedPos = HashCommon.mix(data.hashCode()) & this.mask; -+ -+ int toRemovePos = expectedPos; -+ FluidDirectionEntry entryToRemove = this.entries[toRemovePos]; -+ -+ for (int i = expectedPos + 1; i < expectedPos + this.maxDistance; i++) { -+ int pos = i & this.mask; -+ FluidDirectionEntry entry = this.entries[pos]; -+ if (entry.getValue() < entryToRemove.getValue()) { -+ toRemovePos = pos; -+ entryToRemove = entry; -+ } -+ -+ entry.incrementAge(); // use this as a mechanism to age the other entries -+ } -+ -+ // remove the least used/oldest entry -+ this.entries[toRemovePos] = new FluidDirectionEntry(data, flag); -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishCommand.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..020368da69b9a492155f6de6297f74732f4ab6ea ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishCommand.java -@@ -0,0 +1,68 @@ -+package gg.pufferfish.pufferfish; -+ -+import java.io.IOException; -+import java.util.Collections; -+import java.util.List; -+import java.util.stream.Collectors; -+import java.util.stream.Stream; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.format.NamedTextColor; -+import net.md_5.bungee.api.ChatColor; -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.Location; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+ -+public class PufferfishCommand extends Command { -+ -+ public PufferfishCommand() { -+ super("pufferfish"); -+ this.description = "Pufferfish related commands"; -+ this.usageMessage = "/pufferfish [reload | version]"; -+ this.setPermission("bukkit.command.pufferfish"); -+ } -+ -+ public static void init() { -+ MinecraftServer.getServer().server.getCommandMap().register("pufferfish", "Pufferfish", new PufferfishCommand()); -+ } -+ -+ @Override -+ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { -+ if (args.length == 1) { -+ return Stream.of("reload", "version") -+ .filter(arg -> arg.startsWith(args[0].toLowerCase())) -+ .collect(Collectors.toList()); -+ } -+ return Collections.emptyList(); -+ } -+ -+ @Override -+ public boolean execute(CommandSender sender, String commandLabel, String[] args) { -+ if (!testPermission(sender)) return true; -+ String prefix = ChatColor.of("#12fff6") + "" + ChatColor.BOLD + "Pufferfish » " + ChatColor.of("#e8f9f9"); -+ -+ if (args.length != 1) { -+ sender.sendMessage(prefix + "Usage: " + usageMessage); -+ args = new String[]{"version"}; -+ } -+ -+ if (args[0].equalsIgnoreCase("reload")) { -+ MinecraftServer console = MinecraftServer.getServer(); -+ try { -+ PufferfishConfig.load(); -+ } catch (IOException e) { -+ sender.sendMessage(Component.text("Failed to reload.", NamedTextColor.RED)); -+ e.printStackTrace(); -+ return true; -+ } -+ console.server.reloadCount++; -+ -+ Command.broadcastCommandMessage(sender, prefix + "Pufferfish configuration has been reloaded."); -+ } else if (args[0].equalsIgnoreCase("version")) { -+ Command.broadcastCommandMessage(sender, prefix + "This server is running " + Bukkit.getName() + " version " + Bukkit.getVersion() + " (Implementing API version " + Bukkit.getBukkitVersion() + ")"); -+ } -+ -+ return true; -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -new file mode 100644 -index 0000000000000000000000000000000000000000..11075b0b4d4c5591850704999868c678348170ff ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -@@ -0,0 +1,299 @@ -+package gg.pufferfish.pufferfish; -+ -+import gg.pufferfish.pufferfish.simd.SIMDDetection; -+import java.io.File; -+import java.io.IOException; -+import java.util.Collections; -+import net.minecraft.core.registries.BuiltInRegistries; -+import java.util.Locale; -+import java.util.Map; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.tags.TagKey; -+import org.apache.logging.log4j.Level; -+import org.bukkit.configuration.ConfigurationSection; -+import net.minecraft.world.entity.EntityType; -+import java.lang.reflect.Method; -+import java.lang.reflect.Modifier; -+import java.util.List; -+import net.minecraft.server.MinecraftServer; -+import org.apache.logging.log4j.Level; -+import org.bukkit.configuration.ConfigurationSection; -+import org.bukkit.configuration.MemoryConfiguration; -+import org.jetbrains.annotations.Nullable; -+import org.simpleyaml.configuration.comments.CommentType; -+import org.simpleyaml.configuration.file.YamlFile; -+import org.simpleyaml.exceptions.InvalidConfigurationException; -+ -+public class PufferfishConfig { -+ -+ private static final YamlFile config = new YamlFile(); -+ private static int updates = 0; -+ -+ private static ConfigurationSection convertToBukkit(org.simpleyaml.configuration.ConfigurationSection section) { -+ ConfigurationSection newSection = new MemoryConfiguration(); -+ for (String key : section.getKeys(false)) { -+ if (section.isConfigurationSection(key)) { -+ newSection.set(key, convertToBukkit(section.getConfigurationSection(key))); -+ } else { -+ newSection.set(key, section.get(key)); -+ } -+ } -+ return newSection; -+ } -+ -+ public static ConfigurationSection getConfigCopy() { -+ return convertToBukkit(config); -+ } -+ -+ public static int getUpdates() { -+ return updates; -+ } -+ -+ public static void load() throws IOException { -+ File configFile = new File("pufferfish.yml"); -+ -+ if (configFile.exists()) { -+ try { -+ config.load(configFile); -+ } catch (InvalidConfigurationException e) { -+ throw new IOException(e); -+ } -+ } -+ -+ getString("info.version", "1.0"); -+ setComment("info", -+ "Pufferfish Configuration", -+ "Check out Pufferfish Host for maximum performance server hosting: https://pufferfish.host", -+ "Join our Discord for support: https://discord.gg/reZw4vQV9H", -+ "Download new builds at https://ci.pufferfish.host/job/Pufferfish"); -+ -+ for (Method method : PufferfishConfig.class.getDeclaredMethods()) { -+ if (Modifier.isStatic(method.getModifiers()) && Modifier.isPrivate(method.getModifiers()) && method.getParameterCount() == 0 && -+ method.getReturnType() == Void.TYPE && !method.getName().startsWith("lambda")) { -+ method.setAccessible(true); -+ try { -+ method.invoke(null); -+ } catch (Throwable t) { -+ MinecraftServer.LOGGER.warn("Failed to load configuration option from " + method.getName(), t); -+ } -+ } -+ } -+ -+ updates++; -+ -+ config.save(configFile); -+ -+ // Attempt to detect vectorization -+ try { -+ SIMDDetection.isEnabled = SIMDDetection.canEnable(PufferfishLogger.LOGGER); -+ SIMDDetection.versionLimited = SIMDDetection.getJavaVersion() < 17 || SIMDDetection.getJavaVersion() > 21; -+ } catch (NoClassDefFoundError | Exception ignored) { -+ ignored.printStackTrace(); -+ } -+ -+ if (SIMDDetection.isEnabled) { -+ PufferfishLogger.LOGGER.info("SIMD operations detected as functional. Will replace some operations with faster versions."); -+ } else if (SIMDDetection.versionLimited) { -+ PufferfishLogger.LOGGER.warning("Will not enable SIMD! These optimizations are only safely supported on Java 17-21."); -+ } else { -+ PufferfishLogger.LOGGER.warning("SIMD operations are available for your server, but are not configured!"); -+ PufferfishLogger.LOGGER.warning("To enable additional optimizations, add \"--add-modules=jdk.incubator.vector\" to your startup flags, BEFORE the \"-jar\"."); -+ PufferfishLogger.LOGGER.warning("If you have already added this flag, then SIMD operations are not supported on your JVM or CPU."); -+ PufferfishLogger.LOGGER.warning("Debug: Java: " + System.getProperty("java.version") + ", test run: " + SIMDDetection.testRun); -+ } -+ } -+ -+ private static void setComment(String key, String... comment) { -+ if (config.contains(key)) { -+ config.setComment(key, String.join("\n", comment), CommentType.BLOCK); -+ } -+ } -+ -+ private static void ensureDefault(String key, Object defaultValue, String... comment) { -+ if (!config.contains(key)) { -+ config.set(key, defaultValue); -+ config.setComment(key, String.join("\n", comment), CommentType.BLOCK); -+ } -+ } -+ -+ private static boolean getBoolean(String key, boolean defaultValue, String... comment) { -+ return getBoolean(key, null, defaultValue, comment); -+ } -+ -+ private static boolean getBoolean(String key, @Nullable String oldKey, boolean defaultValue, String... comment) { -+ ensureDefault(key, defaultValue, comment); -+ return config.getBoolean(key, defaultValue); -+ } -+ -+ private static int getInt(String key, int defaultValue, String... comment) { -+ return getInt(key, null, defaultValue, comment); -+ } -+ -+ private static int getInt(String key, @Nullable String oldKey, int defaultValue, String... comment) { -+ ensureDefault(key, defaultValue, comment); -+ return config.getInt(key, defaultValue); -+ } -+ -+ private static double getDouble(String key, double defaultValue, String... comment) { -+ return getDouble(key, null, defaultValue, comment); -+ } -+ -+ private static double getDouble(String key, @Nullable String oldKey, double defaultValue, String... comment) { -+ ensureDefault(key, defaultValue, comment); -+ return config.getDouble(key, defaultValue); -+ } -+ -+ private static String getString(String key, String defaultValue, String... comment) { -+ return getOldString(key, null, defaultValue, comment); -+ } -+ -+ private static String getOldString(String key, @Nullable String oldKey, String defaultValue, String... comment) { -+ ensureDefault(key, defaultValue, comment); -+ return config.getString(key, defaultValue); -+ } -+ -+ private static List getStringList(String key, List defaultValue, String... comment) { -+ return getStringList(key, null, defaultValue, comment); -+ } -+ -+ private static List getStringList(String key, @Nullable String oldKey, List defaultValue, String... comment) { -+ ensureDefault(key, defaultValue, comment); -+ return config.getStringList(key); -+ } -+ -+ public static String sentryDsn; -+ private static void sentry() { -+ String sentryEnvironment = System.getenv("SENTRY_DSN"); -+ String sentryConfig = getString("sentry-dsn", "", "Sentry DSN for improved error logging, leave blank to disable", "Obtain from https://sentry.io/"); -+ -+ sentryDsn = sentryEnvironment == null ? sentryConfig : sentryEnvironment; -+ if (sentryDsn != null && !sentryDsn.isBlank()) { -+ gg.pufferfish.pufferfish.sentry.SentryManager.init(); -+ } -+ } -+ -+ public static boolean enableBooks; -+ private static void books() { -+ enableBooks = getBoolean("enable-books", true, -+ "Whether or not books should be writeable.", -+ "Servers that anticipate being a target for duping may want to consider", -+ "disabling this option.", -+ "This can be overridden per-player with the permission pufferfish.usebooks"); -+ } -+ -+ public static boolean tpsCatchup; -+ private static void tpsCatchup() { -+ tpsCatchup = getBoolean("tps-catchup", true, -+ "If this setting is true, the server will run faster after a lag spike in", -+ "an attempt to maintain 20 TPS. This option (defaults to true per", -+ "spigot/paper) can cause mobs to move fast after a lag spike."); -+ } -+ -+ public static boolean enableSuffocationOptimization; -+ private static void suffocationOptimization() { -+ enableSuffocationOptimization = getBoolean("enable-suffocation-optimization", true, -+ "Optimizes the suffocation check by selectively skipping", -+ "the check in a way that still appears vanilla. This should", -+ "be left enabled on most servers, but is provided as a", -+ "configuration option if the vanilla deviation is undesirable."); -+ } -+ -+ public static boolean enableAsyncMobSpawning; -+ public static boolean asyncMobSpawningInitialized; -+ private static void asyncMobSpawning() { -+ boolean temp = getBoolean("enable-async-mob-spawning", true, -+ "Whether or not asynchronous mob spawning should be enabled.", -+ "On servers with many entities, this can improve performance by up to 15%. You must have", -+ "paper's per-player-mob-spawns setting set to true for this to work.", -+ "One quick note - this does not actually spawn mobs async (that would be very unsafe).", -+ "This just offloads some expensive calculations that are required for mob spawning."); -+ -+ // This prevents us from changing the value during a reload. -+ if (!asyncMobSpawningInitialized) { -+ asyncMobSpawningInitialized = true; -+ enableAsyncMobSpawning = temp; -+ } -+ } -+ -+ public static int maxProjectileLoadsPerTick; -+ public static int maxProjectileLoadsPerProjectile; -+ private static void projectileLoading() { -+ maxProjectileLoadsPerTick = getInt("projectile.max-loads-per-tick", 10, "Controls how many chunks are allowed", "to be sync loaded by projectiles in a tick."); -+ maxProjectileLoadsPerProjectile = getInt("projectile.max-loads-per-projectile", 10, "Controls how many chunks a projectile", "can load in its lifetime before it gets", "automatically removed."); -+ -+ setComment("projectile", "Optimizes projectile settings"); -+ } -+ -+ -+ public static boolean dearEnabled; -+ public static int startDistance; -+ public static int startDistanceSquared; -+ public static int maximumActivationPrio; -+ public static int activationDistanceMod; -+ -+ private static void dynamicActivationOfBrains() throws IOException { -+ dearEnabled = getBoolean("dab.enabled", "activation-range.enabled", true); -+ startDistance = getInt("dab.start-distance", "activation-range.start-distance", 12, -+ "This value determines how far away an entity has to be", -+ "from the player to start being effected by DEAR."); -+ startDistanceSquared = startDistance * startDistance; -+ maximumActivationPrio = getInt("dab.max-tick-freq", "activation-range.max-tick-freq", 20, -+ "This value defines how often in ticks, the furthest entity", -+ "will get their pathfinders and behaviors ticked. 20 = 1s"); -+ activationDistanceMod = getInt("dab.activation-dist-mod", "activation-range.activation-dist-mod", 8, -+ "This value defines how much distance modifies an entity's", -+ "tick frequency. freq = (distanceToPlayer^2) / (2^value)", -+ "If you want further away entities to tick less often, use 7.", -+ "If you want further away entities to tick more often, try 9."); -+ -+ for (EntityType entityType : BuiltInRegistries.ENTITY_TYPE) { -+ entityType.dabEnabled = true; // reset all, before setting the ones to true -+ } -+ getStringList("dab.blacklisted-entities", "activation-range.blacklisted-entities", Collections.emptyList(), "A list of entities to ignore for activation") -+ .forEach(name -> EntityType.byString(name).ifPresentOrElse(entityType -> { -+ entityType.dabEnabled = false; -+ }, () -> MinecraftServer.LOGGER.warn("Unknown entity \"" + name + "\""))); -+ -+ setComment("dab", "Optimizes entity brains when", "they're far away from the player"); -+ } -+ -+ public static Map projectileTimeouts; -+ private static void projectileTimeouts() { -+ // Set some defaults -+ getInt("entity_timeouts.SNOWBALL", -1); -+ getInt("entity_timeouts.LLAMA_SPIT", -1); -+ setComment("entity_timeouts", -+ "These values define a entity's maximum lifespan. If an", -+ "entity is in this list and it has survived for longer than", -+ "that number of ticks, then it will be removed. Setting a value to", -+ "-1 disables this feature."); -+ -+ for (EntityType entityType : BuiltInRegistries.ENTITY_TYPE) { -+ String type = EntityType.getKey(entityType).getPath().toUpperCase(Locale.ROOT); -+ entityType.ttl = config.getInt("entity_timeouts." + type, -1); -+ } -+ } -+ -+ public static boolean throttleInactiveGoalSelectorTick; -+ private static void inactiveGoalSelectorThrottle() { -+ throttleInactiveGoalSelectorTick = getBoolean("inactive-goal-selector-throttle", "inactive-goal-selector-disable", true, -+ "Throttles the AI goal selector in entity inactive ticks.", -+ "This can improve performance by a few percent, but has minor gameplay implications."); -+ } -+ -+ public static boolean allowEndCrystalRespawn; -+ private static void allowEndCrystalRespawn() { -+ allowEndCrystalRespawn = getBoolean("allow-end-crystal-respawn", true, -+ "Allows end crystals to respawn the ender dragon.", -+ "On servers that expect end crystal fights in the end dimension, disabling this", -+ "will prevent the server from performing an expensive search to attempt respawning", -+ "the ender dragon whenever a player places an end crystal."); -+ } -+ -+ public static boolean disableMethodProfiler; -+ private static void miscSettings() { -+ disableMethodProfiler = getBoolean("misc.disable-method-profiler", true); -+ setComment("misc", "Settings for things that don't belong elsewhere"); -+ } -+ -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishLogger.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishLogger.java -new file mode 100644 -index 0000000000000000000000000000000000000000..53f2df00c6809618a9ee3d2ea72e85e8052fbcf1 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishLogger.java -@@ -0,0 +1,16 @@ -+package gg.pufferfish.pufferfish; -+ -+import java.util.logging.Level; -+import java.util.logging.Logger; -+import org.bukkit.Bukkit; -+ -+public class PufferfishLogger extends Logger { -+ public static final PufferfishLogger LOGGER = new PufferfishLogger(); -+ -+ private PufferfishLogger() { -+ super("Pufferfish", null); -+ -+ setParent(Bukkit.getLogger()); -+ setLevel(Level.ALL); -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishVersionFetcher.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishVersionFetcher.java -new file mode 100644 -index 0000000000000000000000000000000000000000..06323dcc745aed16123980fc559d7b65c42f1e1c ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishVersionFetcher.java -@@ -0,0 +1,132 @@ -+package gg.pufferfish.pufferfish; -+ -+import com.destroystokyo.paper.VersionHistoryManager; -+import com.destroystokyo.paper.util.VersionFetcher; -+import com.google.gson.Gson; -+import com.google.gson.JsonObject; -+import io.papermc.paper.ServerBuildInfo; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.JoinConfiguration; -+import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.format.TextDecoration; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+import java.io.IOException; -+import java.net.URI; -+import java.net.http.HttpClient; -+import java.net.http.HttpRequest; -+import java.net.http.HttpResponse; -+import java.nio.charset.StandardCharsets; -+import java.util.concurrent.TimeUnit; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+ -+import static net.kyori.adventure.text.Component.text; -+import static net.kyori.adventure.text.format.NamedTextColor.GREEN; -+import static net.kyori.adventure.text.format.NamedTextColor.RED; -+ -+public class PufferfishVersionFetcher implements VersionFetcher { -+ -+ private static final Logger LOGGER = Logger.getLogger("PufferfishVersionFetcher"); -+ private static final HttpClient client = HttpClient.newHttpClient(); -+ -+ private static final URI JENKINS_URI = URI.create("https://ci.pufferfish.host/job/Pufferfish-1.21/lastSuccessfulBuild/buildNumber"); -+ private static final String GITHUB_FORMAT = "https://api.github.com/repos/pufferfish-gg/Pufferfish/compare/ver/1.21...%s"; -+ -+ private static final HttpResponse.BodyHandler JSON_OBJECT_BODY_HANDLER = responseInfo -> HttpResponse.BodySubscribers -+ .mapping( -+ HttpResponse.BodySubscribers.ofString(StandardCharsets.UTF_8), -+ string -> new Gson().fromJson(string, JsonObject.class) -+ ); -+ -+ @Override -+ public long getCacheTime() { -+ return TimeUnit.MINUTES.toMillis(30); -+ } -+ -+ @Override -+ public @NotNull Component getVersionMessage(final @NotNull String serverVersion) { -+ @NotNull Component component; -+ -+ if (ServerBuildInfo.buildInfo().buildNumber().isPresent()) { -+ component = this.fetchJenkinsVersion(ServerBuildInfo.buildInfo().buildNumber().getAsInt()); -+ } else if (ServerBuildInfo.buildInfo().gitCommit().isPresent()) { -+ component = this.fetchGithubVersion(ServerBuildInfo.buildInfo().gitCommit().get()); -+ } else { -+ component = text("Unknown server version.", RED); -+ } -+ -+ final @Nullable Component history = this.getHistory(); -+ return history != null ? Component -+ .join(JoinConfiguration.noSeparators(), component, Component.newline(), this.getHistory()) : component; -+ } -+ -+ private @NotNull Component fetchJenkinsVersion(final int versionNumber) { -+ final HttpRequest request = HttpRequest.newBuilder(JENKINS_URI).build(); -+ try { -+ final HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); -+ if (response.statusCode() != 200) { -+ return text("Received invalid status code (" + response.statusCode() + ") from server.", RED); -+ } -+ -+ int latestVersionNumber; -+ try { -+ latestVersionNumber = Integer.parseInt(response.body()); -+ } catch (NumberFormatException e) { -+ LOGGER.log(Level.WARNING, "Received invalid response from Jenkins \"" + response.body() + "\"."); -+ return text("Received invalid response from server.", RED); -+ } -+ -+ final int versionDiff = latestVersionNumber - versionNumber; -+ return this.getResponseMessage(versionDiff); -+ } catch (IOException | InterruptedException e) { -+ LOGGER.log(Level.WARNING, "Failed to look up version from Jenkins", e); -+ return text("Failed to retrieve version from server.", RED); -+ } -+ } -+ -+ // Based off code contributed by Techcable in Paper/GH-65 -+ private @NotNull Component fetchGithubVersion(final @NotNull String hash) { -+ final URI uri = URI.create(String.format(GITHUB_FORMAT, hash)); -+ final HttpRequest request = HttpRequest.newBuilder(uri).build(); -+ try { -+ final HttpResponse response = client.send(request, JSON_OBJECT_BODY_HANDLER); -+ if (response.statusCode() != 200) { -+ return text("Received invalid status code (" + response.statusCode() + ") from server.", RED); -+ } -+ -+ final JsonObject obj = response.body(); -+ final int versionDiff = obj.get("behind_by").getAsInt(); -+ -+ return this.getResponseMessage(versionDiff); -+ } catch (IOException | InterruptedException e) { -+ LOGGER.log(Level.WARNING, "Failed to look up version from GitHub", e); -+ return text("Failed to retrieve version from server.", RED); -+ } -+ } -+ -+ private @NotNull Component getResponseMessage(final int versionDiff) { -+ return switch (Math.max(-1, Math.min(1, versionDiff))) { -+ case -1 -> text("You are running an unsupported version of Pufferfish.", RED); -+ case 0 -> text("You are on the latest version!", GREEN); -+ default -> text("You are running " + versionDiff + " version" + (versionDiff == 1 ? "" : "s") + " behind. " + -+ "Please update your server when possible to maintain stability and security, and to receive the latest optimizations.", -+ RED); -+ }; -+ } -+ -+ private @Nullable Component getHistory() { -+ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); -+ if (data == null) { -+ return null; -+ } -+ -+ final String oldVersion = data.getOldVersion(); -+ if (oldVersion == null) { -+ return null; -+ } -+ -+ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); -+ } -+} -\ No newline at end of file -diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java b/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java -new file mode 100644 -index 0000000000000000000000000000000000000000..731ef11c7a025ae95ed8a757b530d834733d0621 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/PufferfishSentryAppender.java -@@ -0,0 +1,135 @@ -+package gg.pufferfish.pufferfish.sentry; -+ -+import com.google.common.reflect.TypeToken; -+import com.google.gson.Gson; -+import io.sentry.Breadcrumb; -+import io.sentry.Sentry; -+import io.sentry.SentryEvent; -+import io.sentry.SentryLevel; -+import io.sentry.protocol.Message; -+import io.sentry.protocol.User; -+import java.util.Map; -+import org.apache.logging.log4j.Level; -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Marker; -+import org.apache.logging.log4j.core.LogEvent; -+import org.apache.logging.log4j.core.Logger; -+import org.apache.logging.log4j.core.appender.AbstractAppender; -+import org.apache.logging.log4j.core.filter.AbstractFilter; -+ -+public class PufferfishSentryAppender extends AbstractAppender { -+ -+ private static final org.apache.logging.log4j.Logger logger = LogManager.getLogger(PufferfishSentryAppender.class); -+ private static final Gson GSON = new Gson(); -+ -+ public PufferfishSentryAppender() { -+ super("PufferfishSentryAdapter", new SentryFilter(), null); -+ } -+ -+ @Override -+ public void append(LogEvent logEvent) { -+ if (logEvent.getThrown() != null && logEvent.getLevel().isMoreSpecificThan(Level.WARN)) { -+ try { -+ logException(logEvent); -+ } catch (Exception e) { -+ logger.warn("Failed to log event with sentry", e); -+ } -+ } else { -+ try { -+ logBreadcrumb(logEvent); -+ } catch (Exception e) { -+ logger.warn("Failed to log event with sentry", e); -+ } -+ } -+ } -+ -+ private void logException(LogEvent e) { -+ SentryEvent event = new SentryEvent(e.getThrown()); -+ -+ Message sentryMessage = new Message(); -+ sentryMessage.setMessage(e.getMessage().getFormattedMessage()); -+ -+ event.setThrowable(e.getThrown()); -+ event.setLevel(getLevel(e.getLevel())); -+ event.setLogger(e.getLoggerName()); -+ event.setTransaction(e.getLoggerName()); -+ event.setExtra("thread_name", e.getThreadName()); -+ -+ boolean hasContext = e.getContextData() != null; -+ -+ if (hasContext && e.getContextData().containsKey("pufferfishsentry_playerid")) { -+ User user = new User(); -+ user.setId(e.getContextData().getValue("pufferfishsentry_playerid")); -+ user.setUsername(e.getContextData().getValue("pufferfishsentry_playername")); -+ event.setUser(user); -+ } -+ -+ if (hasContext && e.getContextData().containsKey("pufferfishsentry_pluginname")) { -+ event.setExtra("plugin.name", e.getContextData().getValue("pufferfishsentry_pluginname")); -+ event.setExtra("plugin.version", e.getContextData().getValue("pufferfishsentry_pluginversion")); -+ event.setTransaction(e.getContextData().getValue("pufferfishsentry_pluginname")); -+ } -+ -+ if (hasContext && e.getContextData().containsKey("pufferfishsentry_eventdata")) { -+ Map eventFields = GSON.fromJson((String) e.getContextData().getValue("pufferfishsentry_eventdata"), new TypeToken>() {}.getType()); -+ if (eventFields != null) { -+ event.setExtra("event", eventFields); -+ } -+ } -+ -+ Sentry.captureEvent(event); -+ } -+ -+ private void logBreadcrumb(LogEvent e) { -+ Breadcrumb breadcrumb = new Breadcrumb(); -+ -+ breadcrumb.setLevel(getLevel(e.getLevel())); -+ breadcrumb.setCategory(e.getLoggerName()); -+ breadcrumb.setType(e.getLoggerName()); -+ breadcrumb.setMessage(e.getMessage().getFormattedMessage()); -+ -+ Sentry.addBreadcrumb(breadcrumb); -+ } -+ -+ private SentryLevel getLevel(Level level) { -+ switch (level.getStandardLevel()) { -+ case TRACE: -+ case DEBUG: -+ return SentryLevel.DEBUG; -+ case WARN: -+ return SentryLevel.WARNING; -+ case ERROR: -+ return SentryLevel.ERROR; -+ case FATAL: -+ return SentryLevel.FATAL; -+ case INFO: -+ default: -+ return SentryLevel.INFO; -+ } -+ } -+ -+ private static class SentryFilter extends AbstractFilter { -+ -+ @Override -+ public Result filter(Logger logger, org.apache.logging.log4j.Level level, Marker marker, String msg, -+ Object... params) { -+ return this.filter(logger.getName()); -+ } -+ -+ @Override -+ public Result filter(Logger logger, org.apache.logging.log4j.Level level, Marker marker, Object msg, Throwable t) { -+ return this.filter(logger.getName()); -+ } -+ -+ @Override -+ public Result filter(LogEvent event) { -+ return this.filter(event == null ? null : event.getLoggerName()); -+ } -+ -+ private Result filter(String loggerName) { -+ return loggerName != null && loggerName.startsWith("gg.castaway.pufferfish.sentry") ? Result.DENY -+ : Result.NEUTRAL; -+ } -+ -+ } -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..1b29210ad0bbb4ada150f23357f0c80d331c996d ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java -@@ -0,0 +1,40 @@ -+package gg.pufferfish.pufferfish.sentry; -+ -+import gg.pufferfish.pufferfish.PufferfishConfig; -+import io.sentry.Sentry; -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+ -+public class SentryManager { -+ -+ private static final Logger logger = LogManager.getLogger(SentryManager.class); -+ -+ private SentryManager() { -+ -+ } -+ -+ private static boolean initialized = false; -+ -+ public static synchronized void init() { -+ if (initialized) { -+ return; -+ } -+ try { -+ initialized = true; -+ -+ Sentry.init(options -> { -+ options.setDsn(PufferfishConfig.sentryDsn); -+ options.setMaxBreadcrumbs(100); -+ }); -+ -+ PufferfishSentryAppender appender = new PufferfishSentryAppender(); -+ appender.start(); -+ ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()).addAppender(appender); -+ logger.info("Sentry logging started!"); -+ } catch (Exception e) { -+ logger.warn("Failed to initialize sentry!", e); -+ initialized = false; -+ } -+ } -+ -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/util/AsyncExecutor.java b/src/main/java/gg/pufferfish/pufferfish/util/AsyncExecutor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..8e5323d5d9af25c8a85c4b34a6be76cfc54384cf ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/util/AsyncExecutor.java -@@ -0,0 +1,73 @@ -+package gg.pufferfish.pufferfish.util; -+ -+import com.google.common.collect.Queues; -+import gg.pufferfish.pufferfish.PufferfishLogger; -+import java.util.Queue; -+import java.util.concurrent.locks.Condition; -+import java.util.concurrent.locks.Lock; -+import java.util.concurrent.locks.ReentrantLock; -+import java.util.logging.Level; -+ -+public class AsyncExecutor implements Runnable { -+ -+ private final Queue jobs = Queues.newArrayDeque(); -+ private final Lock mutex = new ReentrantLock(); -+ private final Condition cond = mutex.newCondition(); -+ private final Thread thread; -+ private volatile boolean killswitch = false; -+ -+ public AsyncExecutor(String threadName) { -+ this.thread = new Thread(this, threadName); -+ } -+ -+ public void start() { -+ thread.start(); -+ } -+ -+ public void kill() { -+ killswitch = true; -+ cond.signalAll(); -+ } -+ -+ public void submit(Runnable runnable) { -+ mutex.lock(); -+ try { -+ jobs.offer(runnable); -+ cond.signalAll(); -+ } finally { -+ mutex.unlock(); -+ } -+ } -+ -+ @Override -+ public void run() { -+ while (!killswitch) { -+ try { -+ Runnable runnable = takeRunnable(); -+ if (runnable != null) { -+ runnable.run(); -+ } -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); -+ } catch (Exception e) { -+ PufferfishLogger.LOGGER.log(Level.SEVERE, e, () -> "Failed to execute async job for thread " + thread.getName()); -+ } -+ } -+ } -+ -+ private Runnable takeRunnable() throws InterruptedException { -+ mutex.lock(); -+ try { -+ while (jobs.isEmpty() && !killswitch) { -+ cond.await(); -+ } -+ -+ if (jobs.isEmpty()) return null; // We've set killswitch -+ -+ return jobs.remove(); -+ } finally { -+ mutex.unlock(); -+ } -+ } -+ -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/util/IterableWrapper.java b/src/main/java/gg/pufferfish/pufferfish/util/IterableWrapper.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c1929840254a3e6d721816f4a20415bea1742580 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/util/IterableWrapper.java -@@ -0,0 +1,20 @@ -+package gg.pufferfish.pufferfish.util; -+ -+import java.util.Iterator; -+import org.jetbrains.annotations.NotNull; -+ -+public class IterableWrapper implements Iterable { -+ -+ private final Iterator iterator; -+ -+ public IterableWrapper(Iterator iterator) { -+ this.iterator = iterator; -+ } -+ -+ @NotNull -+ @Override -+ public Iterator iterator() { -+ return iterator; -+ } -+ -+} -diff --git a/src/main/java/gg/pufferfish/pufferfish/util/Long2ObjectOpenHashMapWrapper.java b/src/main/java/gg/pufferfish/pufferfish/util/Long2ObjectOpenHashMapWrapper.java -new file mode 100644 -index 0000000000000000000000000000000000000000..facd55463d44cb7e3d2ca6892982f5497b8dded1 ---- /dev/null -+++ b/src/main/java/gg/pufferfish/pufferfish/util/Long2ObjectOpenHashMapWrapper.java -@@ -0,0 +1,40 @@ -+package gg.pufferfish.pufferfish.util; -+ -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import java.util.Map; -+import org.jetbrains.annotations.Nullable; -+ -+public class Long2ObjectOpenHashMapWrapper extends Long2ObjectOpenHashMap { -+ -+ private final Map backingMap; -+ -+ public Long2ObjectOpenHashMapWrapper(Map map) { -+ backingMap = map; -+ } -+ -+ @Override -+ public V put(Long key, V value) { -+ return backingMap.put(key, value); -+ } -+ -+ @Override -+ public V get(Object key) { -+ return backingMap.get(key); -+ } -+ -+ @Override -+ public V remove(Object key) { -+ return backingMap.remove(key); -+ } -+ -+ @Nullable -+ @Override -+ public V putIfAbsent(Long key, V value) { -+ return backingMap.putIfAbsent(key, value); -+ } -+ -+ @Override -+ public int size() { -+ return backingMap.size(); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 696d075ca2883f3c37e35f983c4d020e5db89d16..e63721261258dba60b1eef2eee011e0aa18b0fd2 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -322,6 +322,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { - AtomicReference atomicreference = new AtomicReference(); -@@ -1312,6 +1313,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop needsChangeBroadcasting = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); -+// public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap = new gg.pufferfish.pufferfish.util.AsyncPlayerAreaMap(this.pooledLinkedPlayerHashSets); // Pufferfish -+ // Paper end - optimise chunk tick iteration - - public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { - super(new RegionStorageInfo(session.getLevelId(), world.dimension(), "chunk"), session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, dsync); -@@ -1282,8 +1286,28 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return ChunkMap.this.level.getServer().getScaledTrackingDistance(initialDistance); - } - -+ private static int getHighestRange(Entity parent, int highest) { -+ List passengers = parent.getPassengers(); -+ -+ for (int i = 0, size = passengers.size(); i < size; i++) { -+ Entity entity = passengers.get(i); -+ int range = entity.getType().clientTrackingRange() * 16; -+ range = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, range); // Paper -+ -+ if (range > highest) { // Paper - we need the lowest range thanks to the fact that our tracker doesn't account for passenger logic // Tuinity - not anymore! -+ highest = range; -+ } -+ -+ highest = getHighestRange(entity, highest); -+ } -+ -+ return highest; -+ } -+ - private int getEffectiveRange() { - int i = this.range; -+ // Pufferfish start - remove iterators and streams -+ /* - Iterator iterator = this.entity.getIndirectPassengers().iterator(); - - while (iterator.hasNext()) { -@@ -1295,6 +1319,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - i = j; - } - } -+ */ -+ i = getHighestRange(this.entity, i); -+ // Pufferfish end - - return this.scaledRange(i); - } -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index dcb5651d1d9b10b40430fb2f713beedf68336704..dbc62bf37a9e6e1936558338521938a47a51e2d6 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -128,6 +128,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - // Paper end - rewrite chunk system - private ServerChunkCache.ChunkAndHolder[] iterationCopy; // Paper - 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); -@@ -461,6 +464,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - int naturalSpawnChunkCount = k; - NaturalSpawner.SpawnState spawnercreature_d; // moved down - if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled -+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning) { // Pufferfish - moved down when async processing - // re-set mob counts - for (ServerPlayer player : this.level.players) { - // Paper start - per player mob spawning backoff -@@ -475,14 +479,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 - gameprofilerfiller.popPush("spawnAndTick"); - boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit - -@@ -507,8 +515,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - - if (true && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) { // Paper - rewrite chunk system - chunk1.incrementInhabitedTime(j); -- if (flag && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot -- NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1); -+ if (flag && (this.spawnEnemies || this.spawnFriendlies) && (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning || _pufferfish_spawnCountsReady.get()) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot -+ NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1); // Pufferfish - } - - if (true) { // Paper - rewrite chunk system -@@ -552,6 +560,40 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - gameprofilerfiller.pop(); - gameprofilerfiller.pop(); - } -+ -+ // Pufferfish start - optimize mob spawning -+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning) { -+ for (ServerPlayer player : this.level.players) { -+ // Paper start - per player mob spawning backoff -+ for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) { -+ player.mobCounts[ii] = 0; -+ -+ int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm? -+ if (newBackoff < 0) { -+ newBackoff = 0; -+ } -+ player.mobBackoffCounts[ii] = newBackoff; -+ } -+ // Paper end - per player mob spawning backoff -+ } -+ if (firstRunSpawnCounts) { -+ firstRunSpawnCounts = false; -+ _pufferfish_spawnCountsReady.set(true); -+ } -+ if (_pufferfish_spawnCountsReady.getAndSet(false)) { -+ net.minecraft.server.MinecraftServer.getServer().mobSpawnExecutor.submit(() -> { -+ int mapped = distanceManager.getNaturalSpawnChunkCount(); -+ ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.Iterator objectiterator = -+ level.entityTickList.entities.iterator(ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); -+ gg.pufferfish.pufferfish.util.IterableWrapper wrappedIterator = -+ new gg.pufferfish.pufferfish.util.IterableWrapper<>(objectiterator); -+ lastSpawnState = NaturalSpawner.createState(mapped, wrappedIterator, this::getFullChunk, null, true); -+ objectiterator.finishedIterating(); -+ _pufferfish_spawnCountsReady.set(true); -+ }); -+ } -+ } -+ // Pufferfish end - } - - private void getFullChunk(long pos, Consumer chunkConsumer) { -diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 8ea2f24695f5dad55e21f238b69442513e7a90c6..5a2f7f7cf79dcbb996574e18cad86ebb54bd718e 100644 ---- a/src/main/java/net/minecraft/server/level/ServerEntity.java -+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -193,6 +193,7 @@ public class ServerEntity { - boolean flag6 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; - - if (!this.forceStateResync && !flag6 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()) { // Paper - fix desync when a player is added to the tracker -+ if (flag2 || flag3 || this.entity instanceof AbstractArrow) { // Pufferfish - if ((!flag2 || !flag3) && !(this.entity instanceof AbstractArrow)) { - if (flag2) { - packet1 = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) ((int) k), (short) ((int) l), (short) ((int) i1), this.entity.onGround()); -@@ -206,6 +207,7 @@ public class ServerEntity { - flag4 = true; - flag5 = true; - } -+ } // Pufferfish - } else { - this.wasOnGround = this.entity.onGround(); - this.teleportDelay = 0; -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index f9abf63e12ea930275121b470e4e4906cff0fc12..2a8ffcdd262ea73844500846c6401cdda7153d61 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -715,6 +715,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - 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(); -@@ -734,7 +735,20 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - } - - gameprofilerfiller.push("tick"); -- this.guardEntityTick(this::tickNonPassenger, entity); -+ // Pufferfish start - copied from this.guardEntityTick -+ try { -+ this.tickNonPassenger(entity); // Pufferfish - changed -+ } catch (Throwable throwable) { -+ if (throwable instanceof ThreadDeath) throw throwable; // Paper -+ // Paper start - Prevent tile entity and entity crashes -+ final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ()); -+ MinecraftServer.LOGGER.error(msg, throwable); -+ getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable))); -+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); -+ // Paper end -+ } -+ this.moonrise$midTickTasks(); // Paper - rewrite chunk system -+ // Pufferfish end - gameprofilerfiller.pop(); - } - } -@@ -861,9 +875,9 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - int j = chunkcoordintpair.getMinBlockX(); - int k = chunkcoordintpair.getMinBlockZ(); - ProfilerFiller gameprofilerfiller = this.getProfiler(); -- - gameprofilerfiller.push("thunder"); -- if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - Option to disable thunder -+ -+ if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && /*this.random.nextInt(this.spigotConfig.thunderChance) == 0 &&*/ chunk.shouldDoLightning(this.random)) { // Spigot // Paper - Option to disable thunder // Pufferfish - replace random with shouldDoLightning - BlockPos blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); - - if (this.isRainingAt(blockposition)) { -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 064d52d4479727c6a32bf357be8da32d1760e7fc..8f2214008d76d00267152b5db0cf0fbdd3fbbfb7 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1157,6 +1157,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - - @Override - public void handleEditBook(ServerboundEditBookPacket packet) { -+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableBooks && !this.player.getBukkitEntity().hasPermission("pufferfish.usebooks")) return; // Pufferfish - // Paper start - Book size limits - final io.papermc.paper.configuration.type.number.IntOr.Disabled pageMax = io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.bookSize.pageMax; - if (!this.cserver.isPrimaryThread() && pageMax.enabled()) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..8492421ed2186c0eab517a67f3140b9988f65250 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -429,6 +429,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - private UUID originWorld; - public boolean freezeLocked = false; // Paper - Freeze Tick Lock API - public boolean fixedPose = false; // Paper - Expand Pose API -+ public boolean activatedPriorityReset = false; // Pufferfish - DAB -+ public int activatedPriority = gg.pufferfish.pufferfish.PufferfishConfig.maximumActivationPrio; // Pufferfish - DAB (golf score) -+ public final BlockPos.MutableBlockPos cachedBlockPos = new BlockPos.MutableBlockPos(); // Pufferfish - reduce entity allocations - - public void setOrigin(@javax.annotation.Nonnull Location location) { - this.origin = location.toVector(); -@@ -845,6 +848,12 @@ 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(); -+ return; -+ } -+ // Pufferfish end - entity TTL - this.baseTick(); - } - -@@ -4452,16 +4461,18 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - } - - public boolean updateFluidHeightAndDoFluidPushing(TagKey tag, double speed) { -- if (this.touchingUnloadedChunk()) { -+ if (false && this.touchingUnloadedChunk()) { // Pufferfish - cost of a lookup here is the same cost as below, so skip - return false; - } else { - AABB axisalignedbb = this.getBoundingBox().deflate(0.001D); -- int i = Mth.floor(axisalignedbb.minX); -- int j = Mth.ceil(axisalignedbb.maxX); -- int k = Mth.floor(axisalignedbb.minY); -- int l = Mth.ceil(axisalignedbb.maxY); -- int i1 = Mth.floor(axisalignedbb.minZ); -- int j1 = Mth.ceil(axisalignedbb.maxZ); -+ // Pufferfish start - rename -+ int minBlockX = Mth.floor(axisalignedbb.minX); -+ int maxBlockX = Mth.ceil(axisalignedbb.maxX); -+ int minBlockY = Mth.floor(axisalignedbb.minY); -+ int maxBlockY = Mth.ceil(axisalignedbb.maxY); -+ int minBlockZ = Mth.floor(axisalignedbb.minZ); -+ int maxBlockZ = Mth.ceil(axisalignedbb.maxZ); -+ // Pufferfish end - double d1 = 0.0D; - boolean flag = this.isPushedByFluid(); - boolean flag1 = false; -@@ -4469,14 +4480,61 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - int k1 = 0; - BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); - -- for (int l1 = i; l1 < j; ++l1) { -- for (int i2 = k; i2 < l; ++i2) { -- for (int j2 = i1; j2 < j1; ++j2) { -- blockposition_mutableblockposition.set(l1, i2, j2); -- FluidState fluid = this.level().getFluidState(blockposition_mutableblockposition); -+ // Pufferfish start - based off CollisionUtil.getCollisionsForBlocksOrWorldBorder -+ final int minSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection(this.level()); -+ final int maxSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMaxSection(this.level()); -+ final int minBlock = minSection << 4; -+ final int maxBlock = (maxSection << 4) | 15; -+ -+ // special cases: -+ if (minBlockY > maxBlock || maxBlockY < minBlock) { -+ // no point in checking -+ return false; -+ } -+ -+ int minYIterate = Math.max(minBlock, minBlockY); -+ int maxYIterate = Math.min(maxBlock, maxBlockY); -+ -+ int minChunkX = minBlockX >> 4; -+ int maxChunkX = maxBlockX >> 4; -+ -+ int minChunkZ = minBlockZ >> 4; -+ int maxChunkZ = maxBlockZ >> 4; -+ -+ for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) { -+ int minZ = currChunkZ == minChunkZ ? minBlockZ & 15 : 0; // coordinate in chunk -+ int maxZ = currChunkZ == maxChunkZ ? maxBlockZ & 15 : 16; // coordinate in chunk -+ -+ for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) { -+ int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk -+ int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 16; // coordinate in chunk -+ -+ net.minecraft.world.level.chunk.ChunkAccess chunk = this.level().getChunkIfLoadedImmediately(currChunkX, currChunkZ); -+ if (chunk == null) { -+ return false; // if we're touching an unloaded chunk then it's false -+ } -+ -+ net.minecraft.world.level.chunk.LevelChunkSection[] sections = chunk.getSections(); -+ -+ for (int currY = minYIterate; currY < maxYIterate; ++currY) { -+ net.minecraft.world.level.chunk.LevelChunkSection section = sections[(currY >> 4) - minSection]; -+ -+ if (section == null || section.hasOnlyAir() || section.fluidStateCount == 0) { // if no fluids, nothing in this section -+ // empty -+ // skip to next section -+ currY = (currY & ~(15)) + 15; // increment by 15: iterator loop increments by the extra one -+ continue; -+ } -+ -+ net.minecraft.world.level.chunk.PalettedContainer blocks = section.states; -+ -+ for (int currZ = minZ; currZ < maxZ; ++currZ) { -+ for (int currX = minX; currX < maxX; ++currX) { -+ FluidState fluid = blocks.get(currX & 15, currY & 15, currZ & 15).getFluidState(); - - if (fluid.is(tag)) { -- double d2 = (double) ((float) i2 + fluid.getHeight(this.level(), blockposition_mutableblockposition)); -+ blockposition_mutableblockposition.set((currChunkX << 4) + currX, currY, (currChunkZ << 4) + currZ); -+ double d2 = (double) ((float) currY + fluid.getHeight(this.level(), blockposition_mutableblockposition)); - - if (d2 >= axisalignedbb.minY) { - flag1 = true; -@@ -4498,9 +4556,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - // CraftBukkit end - } - } -+ } -+ } - } - } - } -+ // Pufferfish end - - if (vec3d.length() > 0.0D) { - if (k1 > 0) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index cb61462d4691a055a4b25f7b953609d8a154fdfe..f9440014ab2fe753c16b9383f5fffbb8adb76e79 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -316,6 +316,8 @@ public class EntityType implements FeatureElement, EntityTypeT - private final boolean canSpawnFarFromPlayer; - private final int clientTrackingRange; - private final int updateInterval; -+ public boolean dabEnabled = false; // Pufferfish -+ public int ttl = -1; // Pufferfish - @Nullable - private String descriptionId; - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..5132e108df37ca97ba94b8b72c0ef292cbb2ec94 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -157,7 +157,6 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class LivingEntity extends Entity implements Attackable { - -@@ -449,7 +448,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - boolean flag = this instanceof net.minecraft.world.entity.player.Player; - - if (!this.level().isClientSide) { -- if (this.isInWall()) { -+ if (shouldCheckForSuffocation() && this.isInWall()) { // Pufferfish - optimize suffocation - this.hurt(this.damageSources().inWall(), 1.0F); - } else if (flag && !this.level().getWorldBorder().isWithinBounds(this.getBoundingBox())) { - double d0 = this.level().getWorldBorder().getDistanceToBorder(this) + this.level().getWorldBorder().getDamageSafeZone(); -@@ -1409,6 +1408,19 @@ public abstract class LivingEntity extends Entity implements Attackable { - return this.getHealth() <= 0.0F; - } - -+ // Pufferfish start - optimize suffocation -+ public boolean couldPossiblyBeHurt(float amount) { -+ if ((float) this.invulnerableTime > (float) this.invulnerableDuration / 2.0F && amount <= this.lastHurt) { -+ return false; -+ } -+ return true; -+ } -+ -+ public boolean shouldCheckForSuffocation() { -+ return !gg.pufferfish.pufferfish.PufferfishConfig.enableSuffocationOptimization || (tickCount % 10 == 0 && couldPossiblyBeHurt(1.0F)); -+ } -+ // Pufferfish end -+ - @Override - public boolean hurt(DamageSource source, float amount) { - if (this.isInvulnerableTo(source)) { -@@ -2065,6 +2077,20 @@ public abstract class LivingEntity extends Entity implements Attackable { - return this.lastClimbablePos; - } - -+ -+ // Pufferfish start -+ private boolean cachedOnClimable = false; -+ private BlockPos lastClimbingPosition = null; -+ -+ public boolean onClimableCached() { -+ if (!this.blockPosition().equals(this.lastClimbingPosition)) { -+ this.cachedOnClimable = this.onClimbable(); -+ this.lastClimbingPosition = this.blockPosition(); -+ } -+ return this.cachedOnClimable; -+ } -+ // Pufferfish end -+ - public boolean onClimbable() { - if (this.isSpectator()) { - return false; -diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 763abeea3f14f15c27d600e0bdae44b387687bb4..1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff 100644 ---- a/src/main/java/net/minecraft/world/entity/Mob.java -+++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -232,14 +232,16 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab - return this.lookControl; - } - -+ int _pufferfish_inactiveTickDisableCounter = 0; // Pufferfish - throttle inactive goal selector ticking - // Paper start - @Override - public void inactiveTick() { - super.inactiveTick(); -- if (this.goalSelector.inactiveTick()) { -+ boolean isThrottled = gg.pufferfish.pufferfish.PufferfishConfig.throttleInactiveGoalSelectorTick && _pufferfish_inactiveTickDisableCounter++ % 20 != 0; // Pufferfish - throttle inactive goal selector ticking -+ if (this.goalSelector.inactiveTick(this.activatedPriority, true) && !isThrottled) { // Pufferfish - pass activated priroity // Pufferfish - throttle inactive goal selector ticking - this.goalSelector.tick(); - } -- if (this.targetSelector.inactiveTick()) { -+ if (this.targetSelector.inactiveTick(this.activatedPriority, true)) { // Pufferfish - pass activated priority - this.targetSelector.tick(); - } - } -@@ -929,16 +931,20 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab - - if (i % 2 != 0 && this.tickCount > 1) { - gameprofilerfiller.push("targetSelector"); -+ if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking - this.targetSelector.tickRunningGoals(false); - gameprofilerfiller.pop(); - gameprofilerfiller.push("goalSelector"); -+ if (this.goalSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking - this.goalSelector.tickRunningGoals(false); - gameprofilerfiller.pop(); - } else { - gameprofilerfiller.push("targetSelector"); -+ if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking - this.targetSelector.tick(); - gameprofilerfiller.pop(); - gameprofilerfiller.push("goalSelector"); -+ if (this.goalSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking - this.goalSelector.tick(); - gameprofilerfiller.pop(); - } -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 69992ebc999ea3ff9e47e4e049bcc514c01150ca..2c9aab24b51d2f0a50100089fe72093b501d383a 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 -@@ -23,9 +23,11 @@ public class AttributeMap { - private final Set attributesToSync = new ObjectOpenHashSet<>(); - private final Set attributesToUpdate = new ObjectOpenHashSet<>(); - private final AttributeSupplier supplier; -+ private final java.util.function.Function, AttributeInstance> createInstance; // Pufferfish - - public AttributeMap(AttributeSupplier defaultAttributes) { - this.supplier = defaultAttributes; -+ this.createInstance = attributex -> this.supplier.createInstance(this::onAttributeModified, attributex); // Pufferfish - } - - private void onAttributeModified(AttributeInstance instance) { -@@ -47,9 +49,10 @@ public class AttributeMap { - return this.attributes.values().stream().filter(attribute -> attribute.getAttribute().value().isClientSyncable()).collect(Collectors.toList()); - } - -+ - @Nullable - public AttributeInstance getInstance(Holder attribute) { -- return this.attributes.computeIfAbsent(attribute, attributex -> this.supplier.createInstance(this::onAttributeModified, attributex)); -+ return this.attributes.computeIfAbsent(attribute, this.createInstance); // Pufferfish - cache lambda, as for some reason java allocates it anyways - } - - public boolean hasAttribute(Holder attribute) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java b/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java -index 758f62416ca9c02351348ac0d41deeb4624abc0e..69130969c9a434ec2361e573c9a1ec9f462dfda2 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java -@@ -36,7 +36,11 @@ public class VillagerPanicTrigger extends Behavior { - - @Override - protected void tick(ServerLevel world, Villager entity, long time) { -- if (time % 100L == 0L) { -+ // Pufferfish start -+ if (entity.nextGolemPanic < 0) entity.nextGolemPanic = time + 100; -+ if (--entity.nextGolemPanic < time) { -+ entity.nextGolemPanic = -1; -+ // Pufferfish end - entity.spawnGolemIfNeeded(world, time, 3); - } - } -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 9bdbf3e9453bc3ce96d52d04b8cde0d05f7356d8..e32c3120f9c5ddf429d8428c370ff61320a38de6 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 -@@ -43,9 +43,12 @@ public class GoalSelector { - } - - // Paper start -- public boolean inactiveTick() { -+ public boolean inactiveTick(int tickRate, boolean inactive) { // Pufferfish start -+ if (inactive && !gg.pufferfish.pufferfish.PufferfishConfig.dearEnabled) tickRate = 4; // reset to Paper's -+ tickRate = Math.min(tickRate, 3); - this.curRate++; -- return this.curRate % 3 == 0; // TODO newGoalRate was already unused in 1.20.4, check if this is correct -+ return this.curRate % tickRate == 0; // TODO newGoalRate was already unused in 1.20.4, check if this is correct -+ // Pufferfish end - } - public boolean hasTasks() { - for (WrappedGoal task : this.availableGoals) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -index aee0147649d458b87d92496eda0c1723ebe570d2..89e9ea999d2fbd81a1d74382ef3fcd675fc8b94e 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -@@ -121,6 +121,7 @@ public abstract class MoveToBlockGoal extends Goal { - for (int m = 0; m <= l; m = m > 0 ? -m : 1 - m) { - for (int n = m < l && m > -l ? l : 0; n <= l; n = n > 0 ? -n : 1 - n) { - mutableBlockPos.setWithOffset(blockPos, m, k - 1, n); -+ if (!this.mob.level().hasChunkAt(mutableBlockPos)) continue; // Pufferfish - if this block isn't loaded, continue - if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level(), mutableBlockPos)) { - this.blockPos = mutableBlockPos; - this.mob.movingTarget = mutableBlockPos == BlockPos.ZERO ? null : mutableBlockPos.immutable(); // Paper -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 aecb0ad814586bfc5e56755ee14379a69388b38c..00ef7f6d60bcaee2506cf111461f2c2f8eedd59a 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 -@@ -76,9 +76,18 @@ public class TargetingConditions { - } - - if (this.range > 0.0) { -- double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0; -- double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0); // Paper - Fix MC-145656 -+ // Pufferfish start - check range before getting visibility -+ // d = invisibility percent, e = follow range adjusted for invisibility, f = distance - double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); -+ double followRangeRaw = this.useFollowRange ? this.getFollowRange(baseEntity) : this.range; -+ -+ if (f > followRangeRaw * followRangeRaw) { // the actual follow range will always be this value or smaller, so if the distance is larger then it never will return true after getting invis -+ return false; -+ } -+ -+ double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0; -+ double e = Math.max((followRangeRaw) * d, 2.0); // Paper - Fix MC-145656 -+ // Pufferfish end - if (f > e * e) { - return false; - } -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 dc27ddf5131e7398a5390a5187261d4c7fb6ccaa..e44af851263f27aa0009b14a60bb2d0642a5ce74 100644 ---- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java -+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java -@@ -239,13 +239,22 @@ public class Bat extends AmbientCreature { - } - } - -+ // Pufferfish start - only check for spooky season once an hour -+ private static boolean isSpookySeason = false; -+ private static final int ONE_HOUR = 20 * 60 * 60; -+ private static int lastSpookyCheck = -ONE_HOUR; - private static boolean isHalloween() { -+ if (net.minecraft.server.MinecraftServer.currentTick - lastSpookyCheck > ONE_HOUR) { - LocalDate localdate = LocalDate.now(); - int i = localdate.get(ChronoField.DAY_OF_MONTH); - int j = localdate.get(ChronoField.MONTH_OF_YEAR); - -- return j == 10 && i >= 20 || j == 11 && i <= 3; -+ isSpookySeason = j == 10 && i >= 20 || j == 11 && i <= 3; -+ lastSpookyCheck = net.minecraft.server.MinecraftServer.currentTick; -+ } -+ return isSpookySeason; - } -+ // Pufferfish end - - private void setupAnimationStates() { - if (this.isResting()) { -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 69986f75d3cf729204cca0c7e5428536af31f695..98a759dbe46e2ead39af0f340c9b73c8f4ddce1e 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,9 +217,11 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS - return 0.4F; - } - -+ private int behaviorTick = 0; // Pufferfish - @Override - protected void customServerAiStep() { - this.level().getProfiler().push("allayBrain"); -+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel) this.level(), this); - this.level().getProfiler().pop(); - this.level().getProfiler().push("allayActivityUpdate"); -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 01a0731e92d39c8718538244e34a271fb8717fc2..44937570f8e968ba4fe2822f69ca8f09679da89d 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,9 +269,11 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder> { - .ifPresent(this::setVariant); - } - -+ private int behaviorTick = 0; // Pufferfish - @Override - protected void customServerAiStep() { - this.level().getProfiler().push("frogBrain"); -+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel)this.level(), this); - this.level().getProfiler().pop(); - this.level().getProfiler().push("frogActivityUpdate"); -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 43046f4a0cff620834ac4647efdcde227185b2ff..90393485ebcf8a4c8c74802fff942b1af8cfbf00 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,9 +83,11 @@ public class Tadpole extends AbstractFish { - return SoundEvents.TADPOLE_FLOP; - } - -+ private int behaviorTick = 0; // Pufferfish - @Override - protected void customServerAiStep() { - this.level().getProfiler().push("tadpoleBrain"); -+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel) this.level(), this); - this.level().getProfiler().pop(); - this.level().getProfiler().push("tadpoleActivityUpdate"); -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 376bcbc189008464f4d518c1e07643431ba96306..07bdea8a7d6706839a758afe0242202c7e841416 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,9 +190,11 @@ public class Goat extends Animal { - return (Brain) super.getBrain(); // CraftBukkit - decompile error - } - -+ private int behaviorTick = 0; // Pufferfish - @Override - protected void customServerAiStep() { - this.level().getProfiler().push("goatBrain"); -+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel) this.level(), this); - this.level().getProfiler().pop(); - this.level().getProfiler().push("goatActivityUpdate"); -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..82921c56c49edb0ca07425da563aa4876d4e6fb1 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 -@@ -154,6 +154,13 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob - this.bossEvent.setName(this.getDisplayName()); - } - -+ // Pufferfish start - optimize suffocation -+ @Override -+ public boolean shouldCheckForSuffocation() { -+ return true; -+ } -+ // Pufferfish end -+ - @Override - protected SoundEvent getAmbientSound() { - return SoundEvents.WITHER_AMBIENT; -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 828c51477cd8f35d591367b30bf4feef6a250292..ace4959f818bf56882b290d109b8b97f2c145631 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -320,11 +320,17 @@ public class EnderMan extends Monster implements NeutralMob { - private boolean teleport(double x, double y, double z) { - BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(x, y, z); - -- while (blockposition_mutableblockposition.getY() > this.level().getMinBuildHeight() && !this.level().getBlockState(blockposition_mutableblockposition).blocksMotion()) { -+ // Pufferfish start - single chunk lookup -+ net.minecraft.world.level.chunk.LevelChunk chunk = this.level().getChunkIfLoaded(blockposition_mutableblockposition); -+ if (chunk == null) { -+ return false; -+ } -+ // Pufferfish end -+ while (blockposition_mutableblockposition.getY() > this.level().getMinBuildHeight() && !chunk.getBlockState(blockposition_mutableblockposition).blocksMotion()) { // Pufferfish - blockposition_mutableblockposition.move(Direction.DOWN); - } - -- BlockState iblockdata = this.level().getBlockState(blockposition_mutableblockposition); -+ BlockState iblockdata = chunk.getBlockState(blockposition_mutableblockposition); // Pufferfish - boolean flag = iblockdata.blocksMotion(); - boolean flag1 = iblockdata.getFluidState().is(FluidTags.WATER); - -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 d5e0c493f4c348724958193795ceb987765a465f..7de73564bc73d6504e18977e97a2ef5f46189e15 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,9 +153,11 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { - return (Brain)super.getBrain(); - } - -+ private int behaviorTick; // Pufferfish - @Override - protected void customServerAiStep() { - this.level().getProfiler().push("hoglinBrain"); -+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel)this.level(), this); - this.level().getProfiler().pop(); - HoglinAi.updateActivity(this); -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 bc58323801ee16fe9b63c21332144ec002a902f2..b2ae7088f90bf3cd04a59c6ddfdba60c58c6e1c8 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,9 +293,11 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento - return !this.cannotHunt; - } - -+ private int behaviorTick; // Pufferfish - @Override - protected void customServerAiStep() { - this.level().getProfiler().push("piglinBrain"); -+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick((ServerLevel) this.level(), this); - this.level().getProfiler().pop(); - PiglinAi.updateActivity(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 38bf417a9ad4647f4af24d969f3bf4fed9c4bad7..40bbd80b1ed4afede6f0769e7f3fcfc61200452f 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,11 +272,13 @@ public class Warden extends Monster implements VibrationSystem { - - } - -+ private int behaviorTick = 0; // Pufferfish - @Override - protected void customServerAiStep() { - ServerLevel worldserver = (ServerLevel) this.level(); - - worldserver.getProfiler().push("wardenBrain"); -+ if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick(worldserver, this); - this.level().getProfiler().pop(); - super.customServerAiStep(); -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 7e1871401ec5e3e9a85232053490259f132aec0a..a16d9c1661690de0374a4a3c31b119293d8fa52b 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 - return holder.is(PoiTypes.MEETING); - }); - -+ public long nextGolemPanic = -1; // Pufferfish -+ - public Villager(EntityType entityType, Level world) { - this(entityType, world, VillagerType.PLAINS); - } -@@ -246,6 +248,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(final boolean inactive) { - // Paper end - this.level().getProfiler().push("villagerBrain"); -- if (!inactive) this.getBrain().tick((ServerLevel) this.level(), this); // Paper -+ // Pufferfish start -+ if (!inactive && this.behaviorTick++ % this.activatedPriority == 0) { -+ this.getBrain().tick((ServerLevel) this.level(), this); // Paper -+ } -+ // Pufferfish end - this.level().getProfiler().pop(); - if (this.assignProfessionWhenSpawned) { - this.assignProfessionWhenSpawned = false; -diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java -index 6e66141dca61f777b354854b5d0bac2570b8bf3b..abf231e6099cda766d73e67f31234e9f4cbc9545 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Inventory.java -+++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java -@@ -643,6 +643,8 @@ public class Inventory implements Container, Nameable { - } - - public boolean contains(ItemStack stack) { -+ // Pufferfish start - don't allocate iterators -+ /* - Iterator iterator = this.compartments.iterator(); - - while (iterator.hasNext()) { -@@ -657,6 +659,18 @@ public class Inventory implements Container, Nameable { - } - } - } -+ */ -+ for (int i = 0; i < this.compartments.size(); i++) { -+ List list = this.compartments.get(i); -+ for (int j = 0; j < list.size(); j++) { -+ ItemStack itemstack1 = list.get(j); -+ -+ if (!itemstack1.isEmpty() && ItemStack.isSameItemSameComponents(itemstack1, stack)) { -+ return true; -+ } -+ } -+ } -+ // Pufferfish end - - return false; - } -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 10ade433c083851d9ea4797c6ec618db122229f9..091ca20cc7e495dbff90f2fcaae51fb1b2bb33d5 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -52,6 +52,36 @@ public abstract class Projectile extends Entity implements TraceableEntity { - super(type, world); - } - -+ // Pufferfish start -+ private static int loadedThisTick = 0; -+ private static int loadedTick; -+ -+ private int loadedLifetime = 0; -+ @Override -+ public void setPos(double x, double y, double z) { -+ int currentTick = net.minecraft.server.MinecraftServer.currentTick; -+ if (loadedTick != currentTick) { -+ loadedTick = currentTick; -+ loadedThisTick = 0; -+ } -+ int previousX = Mth.floor(this.getX()) >> 4, previousZ = Mth.floor(this.getZ()) >> 4; -+ int newX = Mth.floor(x) >> 4, newZ = Mth.floor(z) >> 4; -+ if (previousX != newX || previousZ != newZ) { -+ boolean isLoaded = ((net.minecraft.server.level.ServerChunkCache) this.level().getChunkSource()).getChunkAtIfLoadedImmediately(newX, newZ) != null; -+ if (!isLoaded) { -+ if (Projectile.loadedThisTick > gg.pufferfish.pufferfish.PufferfishConfig.maxProjectileLoadsPerTick) { -+ if (++this.loadedLifetime > gg.pufferfish.pufferfish.PufferfishConfig.maxProjectileLoadsPerProjectile) { -+ this.discard(); -+ } -+ return; -+ } -+ Projectile.loadedThisTick++; -+ } -+ } -+ super.setPos(x, y, z); -+ } -+ // Pufferfish end -+ - public void setOwner(@Nullable Entity entity) { - if (entity != null) { - this.ownerUUID = entity.getUUID(); -diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java -index 5f51e64cb0611a4ba6bdcdcacbcba1063a7f3a5c..cc1e5882bee94864ad189d7f01ce78223411e51d 100644 ---- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java -+++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java -@@ -57,7 +57,7 @@ public class EndCrystalItem extends Item { - world.gameEvent((Entity) context.getPlayer(), (Holder) GameEvent.ENTITY_PLACE, blockposition1); - EndDragonFight enderdragonbattle = ((ServerLevel) world).getDragonFight(); - -- if (enderdragonbattle != null) { -+ if (enderdragonbattle != null && gg.pufferfish.pufferfish.PufferfishConfig.allowEndCrystalRespawn) { // Pufferfish - enderdragonbattle.tryRespawn(aboveBlockPosition); // Paper - Perf: Do crystal-portal proximity check before entity lookup - } - } -diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java -index 213ee4aa988dd4c2a5a7be99b1d13f67338e5209..8e46753af60aa9fd8e4b4c0f955f7a55a77de314 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java -+++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java -@@ -10,6 +10,7 @@ import net.minecraft.core.HolderLookup; - import net.minecraft.core.NonNullList; - import net.minecraft.network.RegistryFriendlyByteBuf; - import net.minecraft.network.codec.StreamCodec; -+import net.minecraft.world.inventory.CraftingContainer; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.Level; - // CraftBukkit start -@@ -25,8 +26,13 @@ public class ShapelessRecipe extends io.papermc.paper.inventory.recipe.RecipeBoo - final CraftingBookCategory category; - final ItemStack result; - final NonNullList ingredients; -+ private final boolean isBukkit; // Pufferfish - -+ // Pufferfish start - public ShapelessRecipe(String group, CraftingBookCategory category, ItemStack result, NonNullList ingredients) { -+ this(group, category, result, ingredients, false); -+ } -+ public ShapelessRecipe(String group, CraftingBookCategory category, ItemStack result, NonNullList ingredients, boolean isBukkit) { this.isBukkit = isBukkit; // Pufferfish end - this.group = group; - this.category = category; - this.result = result; -@@ -76,6 +82,28 @@ public class ShapelessRecipe extends io.papermc.paper.inventory.recipe.RecipeBoo - } - - public boolean matches(CraftingInput input, Level world) { -+ // Pufferfish start -+ if (!this.isBukkit) { -+ java.util.List ingredients = com.google.common.collect.Lists.newArrayList(this.ingredients.toArray(new Ingredient[0])); -+ -+ inventory: for (int index = 0; index < input.size(); index++) { -+ ItemStack itemStack = input.getItem(index); -+ -+ if (!itemStack.isEmpty()) { -+ for (int i = 0; i < ingredients.size(); i++) { -+ if (ingredients.get(i).test(itemStack)) { -+ ingredients.remove(i); -+ continue inventory; -+ } -+ } -+ return false; -+ } -+ } -+ -+ return ingredients.isEmpty(); -+ } -+ // Pufferfish end -+ - // Paper start - unwrap ternary & better exact choice recipes - if (input.ingredientCount() != this.ingredients.size()) { - return false; -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 507671476c3d2d92a2fdb05be24443af27d26dcf..2479b47186202de40cdb4ae773c696a4adee9bad 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1418,16 +1418,16 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - public void guardEntityTick(Consumer tickConsumer, T entity) { - try { - tickConsumer.accept(entity); -- } catch (Throwable throwable) { -+ } catch (Throwable throwable) { // Pufferfish - diff on change ServerLevel.tick - if (throwable instanceof ThreadDeath) throw throwable; // Paper - // Paper start - Prevent block entity and entity crashes - final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ()); - MinecraftServer.LOGGER.error(msg, throwable); - getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable))); // Paper - ServerExceptionEvent -- entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); -+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); // Pufferfish - diff on change ServerLevel.tick - // Paper end - Prevent block entity and entity crashes - } -- this.moonrise$midTickTasks(); // Paper - rewrite chunk system -+ this.moonrise$midTickTasks(); // Paper - rewrite chunk system // Pufferfish - diff on change ServerLevel.tick - } - // Paper start - Option to prevent armor stands from doing entity lookups - @Override -@@ -1961,6 +1961,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - } - - public ProfilerFiller getProfiler() { -+ if (gg.pufferfish.pufferfish.PufferfishConfig.disableMethodProfiler) return net.minecraft.util.profiling.InactiveProfiler.INSTANCE; // Pufferfish - return (ProfilerFiller) this.profiler.get(); - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..00987d0e1ee8a9541b0610616ace1c84d50e5f1a 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -86,6 +86,18 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - private final LevelChunkTicks blockTicks; - private final LevelChunkTicks fluidTicks; - -+ // Pufferfish start - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively -+ private int lightningTick; -+ // shouldDoLightning compiles down to 29 bytes, which with the default of 35 byte inlining should guarantee an inline -+ public final boolean shouldDoLightning(net.minecraft.util.RandomSource random) { -+ if (this.lightningTick-- <= 0) { -+ this.lightningTick = random.nextInt(this.level.spigotConfig.thunderChance) << 1; -+ return true; -+ } -+ return false; -+ } -+ // Pufferfish end -+ - public LevelChunk(Level world, ChunkPos pos) { - this(world, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, (LevelChunkSection[]) null, (LevelChunk.PostLoadProcessor) null, (BlendingData) null); - } -@@ -117,6 +129,8 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - this.debug = !empty && this.level.isDebug(); - this.defaultBlockState = empty ? VOID_AIR_BLOCKSTATE : AIR_BLOCKSTATE; - // Paper end - get block chunk optimisation -+ -+ this.lightningTick = new java.util.Random().nextInt(100000) << 1; // Pufferfish - initialize lightning tick - } - - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index c3b1caa352b988ec44fa2b2eb0536517711f5460..a28366b8ed0da356dad6941e0a817d0b7ec43738 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -22,6 +22,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_ - short nonEmptyBlockCount; // Paper - package private - private short tickingBlockCount; - private short tickingFluidCount; -+ public short fluidStateCount; // Pufferfish - public final PalettedContainer states; - // CraftBukkit start - read/write - private PalettedContainer> biomes; -@@ -104,6 +105,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_ - - if (!fluid.isEmpty()) { - --this.tickingFluidCount; -+ --this.fluidStateCount; // Pufferfish - } - - if (!state.isAir()) { -@@ -115,6 +117,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_ - - if (!fluid1.isEmpty()) { - ++this.tickingFluidCount; -+ ++this.fluidStateCount; // Pufferfish - } - - // Paper start - block counting -@@ -208,6 +211,7 @@ public class LevelChunkSection implements ca.spottedleaf.moonrise.patches.block_ - if (fluid.isRandomlyTicking()) { - this.tickingFluidCount += paletteCount; - } -+ this.fluidStateCount++; // Pufferfish - } - } - } -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 -+++ b/src/main/java/net/minecraft/world/level/entity/EntityTickList.java -@@ -9,7 +9,7 @@ import javax.annotation.Nullable; - import net.minecraft.world.entity.Entity; - - public class EntityTickList { -- private final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system -+ public final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system // Pufferfish - private->public - - private void ensureActiveIsNotIterated() { - // Paper - rewrite chunk system -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..6785baf574f233ed1c3bea8d406be8a524d9ff82 100644 ---- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -@@ -45,6 +45,8 @@ public abstract class FlowingFluid extends Fluid { - public static final BooleanProperty FALLING = BlockStateProperties.FALLING; - public static final IntegerProperty LEVEL = BlockStateProperties.LEVEL_FLOWING; - private static final int CACHE_SIZE = 200; -+ // Pufferfish start - use our own cache -+ /* - private static final ThreadLocal> OCCLUSION_CACHE = ThreadLocal.withInitial(() -> { - Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap = new Object2ByteLinkedOpenHashMap(200) { - protected void rehash(int i) {} -@@ -53,6 +55,14 @@ public abstract class FlowingFluid extends Fluid { - object2bytelinkedopenhashmap.defaultReturnValue((byte) 127); - return object2bytelinkedopenhashmap; - }); -+ */ -+ -+ private static final ThreadLocal> localFluidDirectionCache = ThreadLocal.withInitial(() -> { -+ // Pufferfish todo - mess with this number for performance -+ // with 2048 it seems very infrequent on a small world that it has to remove old entries -+ return new gg.airplane.structs.FluidDirectionCache<>(2048); -+ }); -+ // Pufferfish end - private final Map shapes = Maps.newIdentityHashMap(); - - public FlowingFluid() {} -@@ -240,6 +250,8 @@ public abstract class FlowingFluid extends Fluid { - } - - private boolean canPassThroughWall(Direction face, BlockGetter world, BlockPos pos, BlockState state, BlockPos fromPos, BlockState fromState) { -+ // Pufferfish start - modify to use our cache -+ /* - Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap; - - if (!state.getBlock().hasDynamicShape() && !fromState.getBlock().hasDynamicShape()) { -@@ -247,9 +259,16 @@ public abstract class FlowingFluid extends Fluid { - } else { - object2bytelinkedopenhashmap = null; - } -+ */ -+ gg.airplane.structs.FluidDirectionCache cache = null; -+ -+ if (!state.getBlock().hasDynamicShape() && !fromState.getBlock().hasDynamicShape()) { -+ cache = localFluidDirectionCache.get(); -+ } - - Block.BlockStatePairKey block_a; - -+ /* - if (object2bytelinkedopenhashmap != null) { - block_a = new Block.BlockStatePairKey(state, fromState, face); - byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a); -@@ -260,11 +279,22 @@ public abstract class FlowingFluid extends Fluid { - } else { - block_a = null; - } -+ */ -+ if (cache != null) { -+ block_a = new Block.BlockStatePairKey(state, fromState, face); -+ Boolean flag = cache.getValue(block_a); -+ if (flag != null) { -+ return flag; -+ } -+ } else { -+ block_a = null; -+ } - - VoxelShape voxelshape = state.getCollisionShape(world, pos); - VoxelShape voxelshape1 = fromState.getCollisionShape(world, fromPos); - boolean flag = !Shapes.mergedFaceOccludes(voxelshape, voxelshape1, face); - -+ /* - if (object2bytelinkedopenhashmap != null) { - if (object2bytelinkedopenhashmap.size() == 200) { - object2bytelinkedopenhashmap.removeLastByte(); -@@ -272,6 +302,11 @@ public abstract class FlowingFluid extends Fluid { - - object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0)); - } -+ */ -+ if (cache != null) { -+ cache.putValue(block_a, flag); -+ } -+ // Pufferfish end - - return flag; - } -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/LootParams.java b/src/main/java/net/minecraft/world/level/storage/loot/LootParams.java -index 37a0002bbe6539648db5219bb373e0404ae48dc0..ca0571d232e102c4b177a1ea44b96f5f0f440211 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/LootParams.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/LootParams.java -@@ -21,8 +21,10 @@ public class LootParams { - - public LootParams(ServerLevel world, Map, Object> parameters, Map dynamicDrops, float luck) { - this.level = world; -- this.params = parameters; -- this.dynamicDrops = dynamicDrops; -+ // Pufferfish start - use unmodifiable maps instead of immutable ones to skip the copy -+ this.params = java.util.Collections.unmodifiableMap(parameters); -+ this.dynamicDrops = java.util.Collections.unmodifiableMap(dynamicDrops); -+ // Pufferfish end - this.luck = luck; - } - -diff --git a/src/main/java/net/minecraft/world/phys/shapes/EntityCollisionContext.java b/src/main/java/net/minecraft/world/phys/shapes/EntityCollisionContext.java -index 88a4a72bb390947dc17e5da09a99b2d1b3ac4621..284c76ddb9724b44bb2e93f590685c728e843e6d 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/EntityCollisionContext.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/EntityCollisionContext.java -@@ -17,50 +17,69 @@ public class EntityCollisionContext implements CollisionContext { - return defaultValue; - } - }; -- private final boolean descending; -- private final double entityBottom; -- private final ItemStack heldItem; -- private final Predicate canStandOnFluid; -+ // Pufferfish start - remove these and pray no plugin uses them -+ // private final boolean descending; -+ // private final double entityBottom; -+ // private final ItemStack heldItem; -+ // private final Predicate canStandOnFluid; -+ // Pufferfish end - @Nullable - private final Entity entity; - - protected EntityCollisionContext(boolean descending, double minY, ItemStack heldItem, Predicate walkOnFluidPredicate, @Nullable Entity entity) { -- this.descending = descending; -- this.entityBottom = minY; -- this.heldItem = heldItem; -- this.canStandOnFluid = walkOnFluidPredicate; -+ // Pufferfish start - remove these -+ // this.descending = descending; -+ // this.entityBottom = minY; -+ // this.heldItem = heldItem; -+ // this.canStandOnFluid = walkOnFluidPredicate; -+ // Pufferfish end - this.entity = entity; - } - - @Deprecated - protected EntityCollisionContext(Entity entity) { -- this( -- entity.isDescending(), -- entity.getY(), -- entity instanceof LivingEntity ? ((LivingEntity)entity).getMainHandItem() : ItemStack.EMPTY, -- entity instanceof LivingEntity ? ((LivingEntity)entity)::canStandOnFluid : fluidState -> false, -- entity -- ); -+ // Pufferfish start - remove this -+ // this( -+ // entity.isDescending(), -+ // entity.getY(), -+ // entity instanceof LivingEntity ? ((LivingEntity)entity).getMainHandItem() : ItemStack.EMPTY, -+ // entity instanceof LivingEntity ? ((LivingEntity)entity)::canStandOnFluid : fluidState -> false, -+ // entity -+ // ); -+ // Pufferfish end -+ this.entity = entity; - } - - @Override - public boolean isHoldingItem(Item item) { -- return this.heldItem.is(item); -+ // Pufferfish start -+ Entity entity = this.entity; -+ if (entity instanceof LivingEntity livingEntity) { -+ return livingEntity.getMainHandItem().is(item); -+ } -+ return ItemStack.EMPTY.is(item); -+ // Pufferfish end - } - - @Override - public boolean canStandOnFluid(FluidState stateAbove, FluidState state) { -- return this.canStandOnFluid.test(state) && !stateAbove.getType().isSame(state.getType()); -+ // Pufferfish start -+ Entity entity = this.entity; -+ if (entity instanceof LivingEntity livingEntity) { -+ return livingEntity.canStandOnFluid(state) && !stateAbove.getType().isSame(state.getType()); -+ } -+ return false; -+ // Pufferfish end - } - - @Override - public boolean isDescending() { -- return this.descending; -+ return this.entity != null && this.entity.isDescending(); // Pufferfish - } - - @Override - public boolean isAbove(VoxelShape shape, BlockPos pos, boolean defaultValue) { -- return this.entityBottom > (double)pos.getY() + shape.max(Direction.Axis.Y) - 1.0E-5F; -+ return (this.entity == null ? -Double.MAX_VALUE : entity.getY()) > (double)pos.getY() + shape.max(Direction.Axis.Y) - 1.0E-5F; // Pufferfish - } - - @Nullable -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java -index 96d772eb02f79f8c478f5e6f065e387aa7665b18..c5ce412f321b8b4f31cc042893659e213b081f29 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java -@@ -45,6 +45,6 @@ public class CraftShapelessRecipe extends ShapelessRecipe implements CraftRecipe - data.set(i, this.toNMS(ingred.get(i), true)); - } - -- MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.ShapelessRecipe(this.getGroup(), CraftRecipe.getCategory(this.getCategory()), CraftItemStack.asNMSCopy(this.getResult()), data))); -+ MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.ShapelessRecipe(this.getGroup(), CraftRecipe.getCategory(this.getCategory()), CraftItemStack.asNMSCopy(this.getResult()), data, true))); // Pufferfish - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index d06aab9bd5cd901c8367f9680f5d27ddb17b3dc4..8fa2b2a67891d34ec95f7eed2a4118ddd8a5be15 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 { - - @Override - public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -- return new com.destroystokyo.paper.PaperVersionFetcher(); -+ return new gg.pufferfish.pufferfish.PufferfishVersionFetcher(); // Pufferfish - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 774556a62eb240da42e84db4502e2ed43495be17..80553face9c70c2a3d897681e7761df85b22d464 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -@@ -11,7 +11,7 @@ public final class Versioning { - public static String getBukkitVersion() { - String result = "Unknown-Version"; - -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/io.papermc.paper/paper-api/pom.properties"); -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/gg.pufferfish.pufferfish/pufferfish-api/pom.properties"); // Pufferfish - Properties properties = new Properties(); - - if (stream != null) { -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index bf2d18f74b0f0da7c3c30310c74224a1c0853564..1461daa08c5b671b8556f29f90400b7e98285a44 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -38,6 +38,10 @@ import co.aikar.timings.MinecraftTimings; - import net.minecraft.world.entity.schedule.Activity; - import net.minecraft.world.level.Level; - import net.minecraft.world.phys.AABB; -+// Pufferfish start -+import net.minecraft.world.phys.Vec3; -+import java.util.List; -+// Pufferfish end - - public class ActivationRange - { -@@ -223,6 +227,25 @@ public class ActivationRange - } - // Paper end - Configurable marker ticking - ActivationRange.activateEntity(entity); -+ -+ // Pufferfish start -+ if (gg.pufferfish.pufferfish.PufferfishConfig.dearEnabled && entity.getType().dabEnabled) { -+ if (!entity.activatedPriorityReset) { -+ entity.activatedPriorityReset = true; -+ entity.activatedPriority = gg.pufferfish.pufferfish.PufferfishConfig.maximumActivationPrio; -+ } -+ Vec3 playerVec = player.position(); -+ Vec3 entityVec = entity.position(); -+ double diffX = playerVec.x - entityVec.x, diffY = playerVec.y - entityVec.y, diffZ = playerVec.z - entityVec.z; -+ int squaredDistance = (int) (diffX * diffX + diffY * diffY + diffZ * diffZ); -+ entity.activatedPriority = squaredDistance > gg.pufferfish.pufferfish.PufferfishConfig.startDistanceSquared ? -+ Math.max(1, Math.min(squaredDistance >> gg.pufferfish.pufferfish.PufferfishConfig.activationDistanceMod, entity.activatedPriority)) : -+ 1; -+ } else { -+ entity.activatedPriority = 1; -+ } -+ // Pufferfish end -+ - } - // Paper end - } -@@ -239,12 +262,12 @@ public class ActivationRange - if ( MinecraftServer.currentTick > entity.activatedTick ) - { - if ( entity.defaultActivationState ) -- { -+ { // Pufferfish - diff on change - entity.activatedTick = MinecraftServer.currentTick; - return; - } - if ( entity.activationType.boundingBox.intersects( entity.getBoundingBox() ) ) -- { -+ { // Pufferfish - diff on change - entity.activatedTick = MinecraftServer.currentTick; - } - } -@@ -298,7 +321,7 @@ public class ActivationRange - if ( entity instanceof LivingEntity ) - { - LivingEntity living = (LivingEntity) entity; -- if ( living.onClimbable() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 || living.isFreezing()) // Paper -+ if ( living.onClimableCached() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 || living.isFreezing() ) // Paper // Pufferfish - use cached - { - return 1; // Paper - } diff --git a/patches/server/0002-Purpur-Server-Changes.patch b/patches/server/0001-Purpur-Server-Changes.patch similarity index 85% rename from patches/server/0002-Purpur-Server-Changes.patch rename to patches/server/0001-Purpur-Server-Changes.patch index 955596f..46bbe9a 100644 --- a/patches/server/0002-Purpur-Server-Changes.patch +++ b/patches/server/0001-Purpur-Server-Changes.patch @@ -1,6 +1,6 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: granny -Date: Tue, 22 Oct 2024 07:33:52 +0900 +Date: Wed, 30 Oct 2024 13:25:10 +0900 Subject: [PATCH] Purpur Server Changes PurpurMC @@ -25,27 +25,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/build.gradle.kts b/build.gradle.kts -index 6cfa3f9994de36e135658841aa3c091b90a14424..535b0c6a750cc77fb9340d6e080932f3eb3bde17 100644 +index 9b3a6b336cb1344d4e74e0e4f7c50ffd1e1b8955..ccb31eb5993db028d0cbf104261205c9462f8734 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { val alsoShade: Configuration by configurations.creating dependencies { -- implementation(project(":pufferfish-api")) // Pufferfish // Paper +- implementation(project(":paper-api")) + implementation(project(":purpur-api")) // Pufferfish // Paper // Purpur // Paper start implementation("org.jline:jline-terminal-jansi:3.21.0") implementation("net.minecrell:terminalconsoleappender:1.3.0") -@@ -49,11 +49,15 @@ dependencies { - - // Pufferfish start - implementation("org.yaml:snakeyaml:1.32") -- implementation ("me.carleslc.Simple-YAML:Simple-Yaml:1.8.4") { -+ implementation ("com.github.carleslc.Simple-YAML:Simple-Yaml:1.8.4") { // Purpur - exclude(group="org.yaml", module="snakeyaml") - } - // Pufferfish end +@@ -47,6 +47,10 @@ 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") + implementation("org.mozilla:rhino-runtime:1.7.14") // Purpur + implementation("org.mozilla:rhino-engine:1.7.14") // Purpur @@ -54,27 +48,27 @@ index 6cfa3f9994de36e135658841aa3c091b90a14424..535b0c6a750cc77fb9340d6e080932f3 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") -@@ -100,14 +104,14 @@ tasks.jar { +@@ -85,14 +89,14 @@ tasks.jar { val gitBranch = git("rev-parse", "--abbrev-ref", "HEAD").getText().trim() // Paper attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", -- "Implementation-Title" to "Pufferfish", // Pufferfish +- "Implementation-Title" to "Paper", + "Implementation-Title" to "Purpur", // Pufferfish // Purpur "Implementation-Version" to implementationVersion, "Implementation-Vendor" to date, // Paper -- "Specification-Title" to "Pufferfish", // Pufferfish +- "Specification-Title" to "Paper", + "Specification-Title" to "Purpur", // Pufferfish // Purpur "Specification-Version" to project.version, -- "Specification-Vendor" to "Pufferfish Studios LLC", // Pufferfish -- "Brand-Id" to "pufferfish:pufferfish", // Pufferfish -- "Brand-Name" to "Pufferfish", // Pufferfish +- "Specification-Vendor" to "Paper Team", +- "Brand-Id" to "papermc:paper", +- "Brand-Name" to "Paper", + "Specification-Vendor" to "Purpur Team", // Pufferfish // Purpur + "Brand-Id" to "purpurmc:purpur", // Pufferfish // Purpur + "Brand-Name" to "Purpur", // Pufferfish // Purpur "Build-Number" to (build ?: ""), "Build-Time" to Instant.now().toString(), "Git-Branch" to gitBranch, // Paper -@@ -168,7 +172,7 @@ fun TaskContainer.registerRunTask( +@@ -153,7 +157,7 @@ fun TaskContainer.registerRunTask( name: String, block: JavaExec.() -> Unit ): TaskProvider = register(name) { @@ -175,14 +169,14 @@ index 0000000000000000000000000000000000000000..15a226e3854d731f7724025ea3459c8a + } +} diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 692c962193cf9fcc6801fc93f3220bdc673d527b..8cde30544e14f8fc2dac32966ae3c21f8cf3a551 100644 +index 4b002e8b75d117b726b0de274a76d3596fce015b..8cde30544e14f8fc2dac32966ae3c21f8cf3a551 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 { boolean logFailedRequests = config.getBoolean("logFailedRequests", false); // Only start Metrics, if it's enabled in the config if (config.getBoolean("enabled", true)) { -- Metrics metrics = new Metrics("Pufferfish", serverUUID, logFailedRequests, Bukkit.getLogger()); // Pufferfish +- Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); + Metrics metrics = new Metrics("Purpur", serverUUID, logFailedRequests, Bukkit.getLogger()); // Pufferfish // Purpur metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { @@ -196,11 +190,11 @@ index 692c962193cf9fcc6801fc93f3220bdc673d527b..8cde30544e14f8fc2dac32966ae3c21f - final String implVersion = org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion(); - if (implVersion != null) { - final String buildOrHash = implVersion.substring(implVersion.lastIndexOf('-') + 1); -- paperVersion = "git-Pufferfish-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash); // Pufferfish +- paperVersion = "git-Paper-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash); - } else { - paperVersion = "unknown"; - } -- metrics.addCustomChart(new Metrics.SimplePie("pufferfish_version", () -> paperVersion)); // Pufferfish +- metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> paperVersion)); + metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() ? "bungee" : "offline"))); // Purpur + metrics.addCustomChart(new Metrics.SimplePie("purpur_version", () -> (org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion() != null) ? org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion() : "unknown")); // Purpur @@ -300,7 +294,7 @@ index 6ee39b534b8d992655bc0cef3c299d12cbae0034..90b3526479320064378f2cde6c2f2b8e .completer(new ConsoleCommandCompleter(this.server)) .option(LineReader.Option.COMPLETE_IN_WORD, true); 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 { @@ -335,59 +329,19 @@ index 12b327eea95e0de9e9c39b7d039badee8ec46508..849ecc5af70901f1e40cb6c419f33f1c setListData(vector); } -diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -index 11075b0b4d4c5591850704999868c678348170ff..8f1645573780d12bf29d441d31eab1b76cd9e70f 100644 ---- a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -+++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -@@ -28,6 +28,7 @@ public class PufferfishConfig { - - private static final YamlFile config = new YamlFile(); - private static int updates = 0; -+ public static File pufferfishFile; // Purpur - - private static ConfigurationSection convertToBukkit(org.simpleyaml.configuration.ConfigurationSection section) { - ConfigurationSection newSection = new MemoryConfiguration(); -@@ -50,7 +51,7 @@ public class PufferfishConfig { - } - - public static void load() throws IOException { -- File configFile = new File("pufferfish.yml"); -+ File configFile = pufferfishFile; // Purpur - - if (configFile.exists()) { - try { -@@ -232,7 +233,7 @@ public class PufferfishConfig { - public static int activationDistanceMod; - - private static void dynamicActivationOfBrains() throws IOException { -- dearEnabled = getBoolean("dab.enabled", "activation-range.enabled", true); -+ dearEnabled = getBoolean("dab.enabled", "activation-range.enabled", false); // Purpur - startDistance = getInt("dab.start-distance", "activation-range.start-distance", 12, - "This value determines how far away an entity has to be", - "from the player to start being effected by DEAR."); -@@ -276,7 +277,7 @@ public class PufferfishConfig { - - public static boolean throttleInactiveGoalSelectorTick; - private static void inactiveGoalSelectorThrottle() { -- throttleInactiveGoalSelectorTick = getBoolean("inactive-goal-selector-throttle", "inactive-goal-selector-disable", true, -+ throttleInactiveGoalSelectorTick = getBoolean("inactive-goal-selector-throttle", "inactive-goal-selector-disable", false, // Purpur - "Throttles the AI goal selector in entity inactive ticks.", - "This can improve performance by a few percent, but has minor gameplay implications."); - } diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java -index 790bad0494454ca12ee152e3de6da3da634d9b20..3099c21ee589acf6edff5903a23673adf489024f 100644 +index 790bad0494454ca12ee152e3de6da3da634d9b20..a6e5950b5875cafd734300cdfbf58f5d3736f3c8 100644 --- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java +++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java -@@ -31,6 +31,8 @@ public record ServerBuildInfoImpl( +@@ -31,6 +31,7 @@ public record ServerBuildInfoImpl( private static final String ATTRIBUTE_GIT_COMMIT = "Git-Commit"; private static final String BRAND_PAPER_NAME = "Paper"; -+ private static final String BRAND_PUFFERFISH_NAME = "Pufferfish"; // Purpur + private static final String BRAND_PURPUR_NAME = "Purpur"; // Purpur private static final String BUILD_DEV = "DEV"; -@@ -42,9 +44,9 @@ public record ServerBuildInfoImpl( +@@ -42,9 +43,9 @@ public record ServerBuildInfoImpl( this( getManifestAttribute(manifest, ATTRIBUTE_BRAND_ID) .map(Key::key) @@ -399,12 +353,12 @@ index 790bad0494454ca12ee152e3de6da3da634d9b20..3099c21ee589acf6edff5903a23673ad SharedConstants.getCurrentVersion().getId(), SharedConstants.getCurrentVersion().getName(), getManifestAttribute(manifest, ATTRIBUTE_BUILD_NUMBER) -@@ -61,7 +63,7 @@ public record ServerBuildInfoImpl( +@@ -61,7 +62,7 @@ public record ServerBuildInfoImpl( @Override public boolean isBrandCompatible(final @NotNull Key brandId) { - return brandId.equals(this.brandId); -+ return brandId.equals(this.brandId) || brandId.equals(BRAND_PAPER_ID) || brandId.equals(BRAND_PUFFERFISH_ID); // Purpur ++ return brandId.equals(this.brandId) || brandId.equals(BRAND_PAPER_ID); // Purpur } @Override @@ -536,30 +490,6 @@ index f0fce4113fb07c64adbec029d177c236cbdcbae8..865dc183276720d54d31d2a54d1bb5c8 sender.sendMessage(component); } -diff --git a/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java b/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -index 0c3c82b28e581286b798ee58ca4193efc2faff4a..24121a43aeb5e9bce013f30c92dddd15f99736c6 100644 ---- a/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -+++ b/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -@@ -80,16 +80,16 @@ public class BukkitCommandNode extends LiteralCommandNode { - - // Plugins do weird things to workaround normal registration - if (this.command.timings == null) { -- this.command.timings = co.aikar.timings.TimingsManager.getCommandTiming(null, this.command); -+ //this.command.timings = co.aikar.timings.TimingsManager.getCommandTiming(null, this.command); // Purpur - } - - String content = context.getRange().get(context.getInput()); - String[] args = org.apache.commons.lang3.StringUtils.split(content, ' '); // fix adjacent spaces (from console/plugins) causing empty array elements - -- try (Timing ignored = this.command.timings.startTiming()) { -+ //try (Timing ignored = this.command.timings.startTiming()) { // Purpur - // Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false) - this.command.execute(sender, this.literal, Arrays.copyOfRange(args, 1, args.length)); -- } -+ //} // Purpur - - // return true as command was handled - return 1; diff --git a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java index 1029b6de6f36b08bf634b4056ef5701383f6f258..ee0d1df78838e05450ad1a06ce70eab2d5e5d3b8 100644 --- a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java @@ -573,10 +503,10 @@ index 1029b6de6f36b08bf634b4056ef5701383f6f258..ee0d1df78838e05450ad1a06ce70eab2 final ConfigurationTransformation.VersionedBuilder versionedBuilder = Transformations.versionedBuilder(); diff --git a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java -index fd3b1c10695634f65c7291016bf671c084bc4d57..c867796f625813797f167610ad443c4be5a7561e 100644 +index a81a332ffb80e67d7f886295099b5cd2ae8994c5..1d18cad6c32815854ff8dace256b59022200c842 100644 --- a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java -@@ -401,6 +401,7 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -400,6 +400,7 @@ public class WorldConfiguration extends ConfigurationPart { public boolean useVanillaWorldScoreboardNameColoring = false; } @@ -584,7 +514,7 @@ index fd3b1c10695634f65c7291016bf671c084bc4d57..c867796f625813797f167610ad443c4b public Environment environment; public class Environment extends ConfigurationPart { -@@ -410,7 +411,9 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -409,7 +410,9 @@ public class WorldConfiguration extends ConfigurationPart { public boolean disableExplosionKnockback = false; public boolean generateFlatBedrock = false; public FrostedIce frostedIce; @@ -641,10 +571,10 @@ index b24265573fdef5d9a964bcd76146f34542c420cf..710477ae27ebc5afdf0012ef0867d05e public SystemReport getSystemReport() { 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 { -+ /*commandlistenerwrapper.getServer().getProfiler().push(() -> { // Purpur +- Profiler.get().push(() -> { ++ /*Profiler.get().push(() -> { // Purpur return "/" + s; - }); + });*/ // Purpur ContextChain contextchain = this.finishParsing(parseresults, s, commandlistenerwrapper, label); // CraftBukkit // Paper - Add UnknownCommandEvent try { -@@ -372,7 +380,7 @@ public class Commands { +@@ -377,7 +385,7 @@ public class Commands { Commands.LOGGER.error("'/{}' threw an exception", s, exception); } } finally { -- commandlistenerwrapper.getServer().getProfiler().pop(); -+ //commandlistenerwrapper.getServer().getProfiler().pop(); // Purpur +- Profiler.get().pop(); ++ //Profiler.get().pop(); // Purpur } } -@@ -509,6 +517,7 @@ public class Commands { +@@ -514,6 +522,7 @@ public class Commands { private void runSync(ServerPlayer player, Collection bukkit, RootCommandNode rootcommandnode) { // Paper end - Perf: Async command map building new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(player.getBukkitEntity(), (RootCommandNode) rootcommandnode, true).callEvent(); // Paper - Brigadier API @@ -763,7 +693,7 @@ index 5af48400f87500166dd889c57a8df0aadb08d43d..ac93dcca5576b9d4e7d15305f5d0dbaf PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit)); event.getPlayer().getServer().getPluginManager().callEvent(event); -@@ -519,6 +528,7 @@ public class Commands { +@@ -524,6 +533,7 @@ public class Commands { } } // CraftBukkit end @@ -910,11 +840,11 @@ index 7b118a92a6eb779f800ae8f5d8f6e3c861fc4f6a..057a038e8dcacd7496a0b2373de2c202 register(registry, "template_rotation", TemplateRotationArgument.class, SingletonArgumentInfo.contextFree(TemplateRotationArgument::templateRotation)); register(registry, "heightmap", HeightmapTypeArgument.class, SingletonArgumentInfo.contextFree(HeightmapTypeArgument::heightmap)); diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 2767d6f97e8b314d23a8e62f22dfd396f5660d31..a64e5997b94cc8173f0512d1e282355f14f098ec 100644 +index f58a94efafbc01d402cd03a108bb90f60930a316..21ea63da99c5b3e2e1ab9cc1049c903bba6cf288 100644 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -61,6 +61,12 @@ public class BlockPos extends Vec3i { - private static final int X_OFFSET = 38; +@@ -62,6 +62,12 @@ public class BlockPos extends Vec3i { + public static final int MAX_HORIZONTAL_COORDINATE = 33554431; // Paper end - Optimize Bit Operations by inlining + // Purpur start @@ -927,13 +857,13 @@ index 2767d6f97e8b314d23a8e62f22dfd396f5660d31..a64e5997b94cc8173f0512d1e282355f super(x, y, z); } diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -index 60d3319016beb4f60cbc26dde165f64cf7577602..bd07743817f2510c179614a6215434e7b333824a 100644 +index a09b089565f9167e1a2d53116ae879d9f868342e..2f79c958eae8592ebf758016b36e5822d1020136 100644 --- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -@@ -1015,5 +1015,22 @@ public interface DispenseItemBehavior { - } - } - }); +@@ -922,5 +922,22 @@ public interface DispenseItemBehavior { + DispenserBlock.registerBehavior(Items.TNT_MINECART, new MinecartDispenseItemBehavior(EntityType.TNT_MINECART)); + DispenserBlock.registerBehavior(Items.HOPPER_MINECART, new MinecartDispenseItemBehavior(EntityType.HOPPER_MINECART)); + DispenserBlock.registerBehavior(Items.COMMAND_BLOCK_MINECART, new MinecartDispenseItemBehavior(EntityType.COMMAND_BLOCK_MINECART)); + // Purpur start + DispenserBlock.registerBehavior(Items.ANVIL, (new OptionalDispenseItemBehavior() { + @Override @@ -953,19 +883,19 @@ index 60d3319016beb4f60cbc26dde165f64cf7577602..bd07743817f2510c179614a6215434e7 + // Purpur end } } -diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -index 44b79a7c2f8b95a484d1999fa2167ce588f7985b..68632372c8704058f35f12e0ae6cdd98ebd55937 100644 ---- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -+++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -@@ -104,7 +104,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { - if (ishearable.readyForShearing()) { - // CraftBukkit start - // Paper start - Add drops to shear events -- org.bukkit.event.block.BlockShearEntityEvent event = CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem, ishearable.generateDefaultDrops()); -+ org.bukkit.event.block.BlockShearEntityEvent event = CraftEventFactory.callBlockShearEntityEvent(entityliving, bukkitBlock, craftItem, ishearable.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.LOOTING, CraftItemStack.asNMSCopy(craftItem)))); // Purpur - if (event.isCancelled()) { - // Paper end - Add drops to shear events - continue; +diff --git a/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java +index a43ea83dbbd5946096cdde31af766674bda6c3be..8077334c24c3bf17404f24a8c5f22134ea01274d 100644 +--- a/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java +@@ -41,7 +41,7 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior { + return false; + } else { + LivingEntity entityliving = (LivingEntity) list.getFirst(); +- EquipmentSlot enumitemslot = entityliving.getEquipmentSlotForItem(stack); ++ EquipmentSlot enumitemslot = pointer.level().purpurConfig.dispenserApplyCursedArmor ? entityliving.getEquipmentSlotForItem(stack) : entityliving.getEquipmentSlotForDispenserItem(stack); if (enumitemslot == null) return false; // Purpur - Dispenser curse of binding protection + ItemStack itemstack1 = stack.split(1); + + // CraftBukkit start diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java index 4a8356a714ed50d4a32bcf046a2e16491bef014b..56e47c5709c765943407d2065b25bd512d1f9388 100644 --- a/src/main/java/net/minecraft/network/Connection.java @@ -1004,34 +934,8 @@ index 300929a406905f5ff1ede664d5b99fb0938d4d2e..a4e9ac0e07f08e0b6aa682e8c1587d9c this.setChainBroken(); throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.OUT_OF_ORDER_CHAT, org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event causes } else { -diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index e2c24813f59c2fd075c740ac1842a38f20ed8554..01efbc507b3d58f13f78ee286f93df40cdc3f0cb 100644 ---- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -@@ -52,7 +52,7 @@ public class PacketUtils { - if (listener instanceof ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // CraftBukkit - Don't handle sync packets for kicked players - if (listener.shouldHandleMessage(packet)) { - co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings -- try (co.aikar.timings.Timing ignored = timing.startTiming()) { // Paper - timings -+ try { // Paper - timings // Purpur - packet.handle(listener); - } catch (Exception exception) { - if (exception instanceof ReportedException) { -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 -@@ -314,10 +315,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { + //this.metricsRecorder = InactiveMetricsRecorder.INSTANCE; // Purpur -+ //this.profiler = this.metricsRecorder.getProfiler(); // Purpur + /*this.onMetricsRecordingStopped = (methodprofilerresults) -> { // Purpur this.stopRecordingMetrics(); - }; @@ -1093,7 +995,7 @@ index e63721261258dba60b1eef2eee011e0aa18b0fd2..d78cb68c3a53b277aa26186062efc716 this.random = RandomSource.create(); this.port = -1; this.levels = Maps.newLinkedHashMap(); -@@ -1033,14 +1036,23 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { - return false; - } : this::haveTime); -@@ -1310,11 +1349,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { + return false; +@@ -1337,9 +1376,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { - return !this.canOversleep(); - }); -- isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -+ //isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); // Purpur - // Paper end - this.server.spark.tickStart(); // Paper - spark - new com.destroystokyo.paper.event.server.ServerTickStartEvent(this.tickCount+1).callEvent(); // Paper - Server Tick Events -@@ -1612,7 +1651,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0; - try { - this.isSaving = true; -@@ -1627,12 +1666,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { - entityplayer.connection.suspendFlushing(); - }); -- MinecraftTimings.bukkitSchedulerTimer.startTiming(); // Spigot // Paper -+ //MinecraftTimings.bukkitSchedulerTimer.startTiming(); // Spigot // Paper // Purpur - this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit -- MinecraftTimings.bukkitSchedulerTimer.stopTiming(); // Spigot // Paper -+ //MinecraftTimings.bukkitSchedulerTimer.stopTiming(); // Spigot // Paper // Purpur - // Paper start - Folia scheduler API - ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).tick(); - getAllLevels().forEach(level -> { -@@ -1745,22 +1784,22 @@ 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.hasRidableMoveEvent = org.purpurmc.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur -- this.profiler.push(() -> { -+ /*this.profiler.push(() -> { // Purpur +- gameprofilerfiller.push(() -> { ++ /*gameprofilerfiller.push(() -> { // Purpur String s = String.valueOf(worldserver); return s + " " + String.valueOf(worldserver.dimension().location()); @@ -1382,100 +1230,83 @@ index e63721261258dba60b1eef2eee011e0aa18b0fd2..d78cb68c3a53b277aa26186062efc716 + });*/ // Purpur /* Drop global time updates if (this.tickCount % 20 == 0) { -- this.profiler.push("timeSync"); -+ //this.profiler.push("timeSync"); // Purpur +- gameprofilerfiller.push("timeSync"); ++ //gameprofilerfiller.push("timeSync"); // Purpur this.synchronizeTime(worldserver); -- this.profiler.pop(); -+ //this.profiler.pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur } // CraftBukkit end */ -- this.profiler.push("tick"); -+ //this.profiler.push("tick"); // Purpur +- gameprofilerfiller.push("tick"); ++ //gameprofilerfiller.push("tick"); // Purpur try { -- worldserver.timings.doTick.startTiming(); // Spigot -+ //worldserver.timings.doTick.startTiming(); // Spigot // Purpur worldserver.tick(shouldKeepTicking); -- worldserver.timings.doTick.stopTiming(); // Spigot -+ //worldserver.timings.doTick.stopTiming(); // Spigot // Purpur - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world"); - -@@ -1817,33 +1857,33 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { this.executeBlocking(() -> { this.saveDebugReport(path.resolve("server")); -@@ -2839,40 +2879,40 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // 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/ServerFunctionManager.java b/src/main/java/net/minecraft/server/ServerFunctionManager.java -index 9cd4f7c6910727c849ac7f5d675dc6105c4bbba2..4e4b7f2a6d7ed92a2ce06e566186027cd9077fc8 100644 +index 0b348f701b61c7b7ed0190eff8b2d73f3a3d5c74..ebd4d2463f88535edd69a1b63a65a635a5592ca2 100644 --- a/src/main/java/net/minecraft/server/ServerFunctionManager.java +++ b/src/main/java/net/minecraft/server/ServerFunctionManager.java -@@ -53,10 +53,10 @@ public class ServerFunctionManager { +@@ -54,10 +54,10 @@ public class ServerFunctionManager { } private void executeTagFunctions(Collection> functions, ResourceLocation label) { -- ProfilerFiller gameprofilerfiller = this.server.getProfiler(); -+ //ProfilerFiller gameprofilerfiller = this.server.getProfiler(); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur Objects.requireNonNull(label); - gameprofilerfiller.push(label::toString); @@ -1611,17 +1428,17 @@ index 9cd4f7c6910727c849ac7f5d675dc6105c4bbba2..4e4b7f2a6d7ed92a2ce06e566186027c Iterator iterator = functions.iterator(); while (iterator.hasNext()) { -@@ -65,15 +65,15 @@ public class ServerFunctionManager { +@@ -66,15 +66,15 @@ public class ServerFunctionManager { this.execute(commandfunction, this.getGameLoopSender()); } -- this.server.getProfiler().pop(); -+ //this.server.getProfiler().pop(); // Purpur +- Profiler.get().pop(); ++ //Profiler.get().pop(); // Purpur } public void execute(CommandFunction function, CommandSourceStack source) { -- ProfilerFiller gameprofilerfiller = this.server.getProfiler(); -+ //ProfilerFiller gameprofilerfiller = this.server.getProfiler(); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur - gameprofilerfiller.push(() -> { + /*gameprofilerfiller.push(() -> { // Purpur @@ -1631,7 +1448,7 @@ index 9cd4f7c6910727c849ac7f5d675dc6105c4bbba2..4e4b7f2a6d7ed92a2ce06e566186027c try { InstantiatedFunction instantiatedfunction = function.instantiate((CompoundTag) null, this.getDispatcher()); -@@ -86,7 +86,7 @@ public class ServerFunctionManager { +@@ -87,7 +87,7 @@ public class ServerFunctionManager { } catch (Exception exception) { ServerFunctionManager.LOGGER.warn("Failed to execute function {}", function.id(), exception); } finally { @@ -1641,7 +1458,7 @@ index 9cd4f7c6910727c849ac7f5d675dc6105c4bbba2..4e4b7f2a6d7ed92a2ce06e566186027c } 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 { @@ -1737,10 +1554,10 @@ index 8c587f829c5e8c6b6df3150024c4ae704988c47b..8ac4d5dbe7f8febf4226f26a6b035282 String string = String.format( Locale.ROOT, "%s-%s-%s", Util.getFilenameFormattedDateTime(), server.getWorldData().getLevelName(), SharedConstants.getCurrentVersion().getId() diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 18bf9c42e76c8c35f57d74ea4adfa5b3bb53762f..6e6f4dffceb0032153c5be119303c5809629cfcc 100644 +index 17a158ff6ce6520b69a5a0032ba4c05449dd0cf8..e9ad8e2ac267c46df80e884308df8bb12d0deeff 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 @@ -1748,7 +1565,7 @@ index 18bf9c42e76c8c35f57d74ea4adfa5b3bb53762f..6e6f4dffceb0032153c5be119303c580 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. @@ -1764,15 +1581,7 @@ index 18bf9c42e76c8c35f57d74ea4adfa5b3bb53762f..6e6f4dffceb0032153c5be119303c580 // Paper start - initialize global and world-defaults configuration this.paperConfigurations.initializeGlobalConfiguration(this.registryAccess()); this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess()); -@@ -239,6 +249,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark - com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now -+ gg.pufferfish.pufferfish.PufferfishConfig.pufferfishFile = (java.io.File) options.valueOf("pufferfish-settings"); // Purpur - gg.pufferfish.pufferfish.PufferfishConfig.load(); // Pufferfish - gg.pufferfish.pufferfish.PufferfishCommand.init(); // Pufferfish - -@@ -288,6 +299,30 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -283,6 +293,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; } @@ -1803,35 +1612,17 @@ index 18bf9c42e76c8c35f57d74ea4adfa5b3bb53762f..6e6f4dffceb0032153c5be119303c580 // CraftBukkit start // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // Spigot - moved up -@@ -362,6 +397,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -356,6 +390,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + DedicatedServer.LOGGER.info("JMX monitoring enabled"); } - if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning) mobSpawnExecutor.start(); // Pufferfish + org.purpurmc.purpur.task.BossBarTask.startAll(); // Purpur + if (org.purpurmc.purpur.PurpurConfig.beeCountPayload) org.purpurmc.purpur.task.BeehiveTask.instance().register(); // Purpur return true; } } -@@ -513,7 +550,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - } - - public void handleConsoleInputs() { -- MinecraftTimings.serverCommandTimer.startTiming(); // Spigot -+ //MinecraftTimings.serverCommandTimer.startTiming(); // Spigot // Purpur - // Paper start - Perf: use proper queue - ConsoleInput servercommand; - while ((servercommand = this.serverCommandQueue.poll()) != null) { -@@ -530,7 +567,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - // CraftBukkit end - } - -- MinecraftTimings.serverCommandTimer.stopTiming(); // Spigot -+ //MinecraftTimings.serverCommandTimer.stopTiming(); // Spigot // Purpur - } - - @Override 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 52e61f75f922a075ccc745198f4ba6ad8fa58ea2..b97d8f43f24baf36eca9064b2b48bf6c092f848c 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 list = Lists.newArrayList(); - List list1 = this.level.players(); - ObjectIterator objectiterator = this.entityMap.values().iterator(); -- level.timings.tracker1.startTiming(); // Paper -+ //this.level.timings.tracker1.startTiming(); // Paper // Purpur - - ChunkMap.TrackedEntity playerchunkmap_entitytracker; - -@@ -987,17 +987,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - playerchunkmap_entitytracker.serverEntity.sendChanges(); - } - } -- level.timings.tracker1.stopTiming(); // Paper -+ //this.level.timings.tracker1.stopTiming(); // Paper // Purpur - - if (!list.isEmpty()) { - objectiterator = this.entityMap.values().iterator(); - -- level.timings.tracker2.startTiming(); // Paper -+ //this.level.timings.tracker2.startTiming(); // Paper // Purpur - while (objectiterator.hasNext()) { - playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); - playerchunkmap_entitytracker.updatePlayers(list); - } -- level.timings.tracker2.stopTiming(); // Paper -+ //this.level.timings.tracker2.stopTiming(); // Paper // Purpur - } - - } diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index dbc62bf37a9e6e1936558338521938a47a51e2d6..ebe872c4643038f0c99b289d4d5afdbedd76c6ef 100644 +index 3c711e1df57ac5b0f8795ebb12299d275792b1d4..bb168636cbf23b5b0c7232529e390f434546dc37 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -359,9 +359,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - - public void save(boolean flush) { - // Paper - rewrite chunk system -- try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings -+ //try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings // Purpur - this.chunkMap.saveAllChunks(flush); -- } // Paper - Timings -+ //} // Paper - Timings // Purpur - } - - @Override -@@ -385,39 +385,39 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -442,38 +442,38 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + // CraftBukkit start - modelled on below public void purgeUnload() { if (true) return; // Paper - rewrite chunk system - this.level.getProfiler().push("purge"); -+ //this.level.getProfiler().push("purge"); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("purge"); ++ //gameprofilerfiller.push("purge"); // Purpur this.distanceManager.purgeStaleTickets(); this.runDistanceManagerUpdates(); -- this.level.getProfiler().popPush("unload"); -+ //this.level.getProfiler().popPush("unload"); // Purpur +- gameprofilerfiller.popPush("unload"); ++ //gameprofilerfiller.popPush("unload"); // Purpur this.chunkMap.tick(() -> true); -- this.level.getProfiler().pop(); -+ //this.level.getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur this.clearCache(); } // CraftBukkit end @Override public void tick(BooleanSupplier shouldKeepTicking, boolean tickChunks) { -- this.level.getProfiler().push("purge"); -- this.level.timings.doChunkMap.startTiming(); // Spigot -+ //this.level.getProfiler().push("purge"); // Purpur -+ //this.level.timings.doChunkMap.startTiming(); // Spigot // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("purge"); ++ //gameprofilerfiller.push("purge"); // Purpur if (this.level.tickRateManager().runsNormally() || !tickChunks || this.level.spigotConfig.unloadFrozenChunks) { // Spigot this.distanceManager.purgeStaleTickets(); } -- + this.runDistanceManagerUpdates(); -- this.level.timings.doChunkMap.stopTiming(); // Spigot -- this.level.getProfiler().popPush("chunks"); -+ //this.level.timings.doChunkMap.stopTiming(); // Spigot // Purpur -+ //this.level.getProfiler().popPush("chunks"); // Purpur +- gameprofilerfiller.popPush("chunks"); ++ //gameprofilerfiller.popPush("chunks"); // Purpur if (tickChunks) { -- this.level.timings.chunks.startTiming(); // Paper - timings -+ //this.level.timings.chunks.startTiming(); // Paper - timings // Purpur ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getPlayerChunkLoader().tick(); // Paper - rewrite chunk system this.tickChunks(); -- this.level.timings.chunks.stopTiming(); // Paper - timings -+ //this.level.timings.chunks.stopTiming(); // Paper - timings // Purpur this.chunkMap.tick(); } -- this.level.timings.doChunkUnload.startTiming(); // Spigot -- this.level.getProfiler().popPush("unload"); -+ //this.level.timings.doChunkUnload.startTiming(); // Spigot // Purpur -+ //this.level.getProfiler().popPush("unload"); // Purpur +- gameprofilerfiller.popPush("unload"); ++ //gameprofilerfiller.popPush("unload"); // Purpur this.chunkMap.tick(shouldKeepTicking); -- this.level.timings.doChunkUnload.stopTiming(); // Spigot -- this.level.getProfiler().pop(); -+ //this.level.timings.doChunkUnload.stopTiming(); // Spigot // Purpur -+ //this.level.getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur this.clearCache(); } -@@ -428,10 +428,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -483,34 +483,34 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon this.lastInhabitedUpdate = i; if (!this.level.isDebug()) { -- ProfilerFiller gameprofilerfiller = this.level.getProfiler(); -+ //ProfilerFiller gameprofilerfiller = this.level.getProfiler(); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur - gameprofilerfiller.push("pollingChunks"); -- gameprofilerfiller.push("filteringLoadedChunks"); + //gameprofilerfiller.push("pollingChunks"); // Purpur -+ //gameprofilerfiller.push("filteringLoadedChunks"); // Purpur - // Paper start - chunk tick iteration optimisations - List list; - { -@@ -452,13 +452,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - } - // Paper end - chunk tick iteration optimisations - Iterator iterator = null; // Paper - chunk tick iteration optimisations -- if (this.level.getServer().tickRateManager().runsNormally()) this.level.timings.chunkTicks.startTiming(); // Paper -+ //if (this.level.getServer().tickRateManager().runsNormally()) this.level.timings.chunkTicks.startTiming(); // Paper // Purpur - - // Paper - chunk tick iteration optimisations - if (this.level.tickRateManager().runsNormally()) { -- gameprofilerfiller.popPush("naturalSpawnCount"); -- this.level.timings.countNaturalMobs.startTiming(); // Paper - timings -+ //gameprofilerfiller.popPush("naturalSpawnCount"); // Purpur -+ //this.level.timings.countNaturalMobs.startTiming(); // Paper - timings // Purpur - int k = this.distanceManager.getNaturalSpawnChunkCount(); - // Paper start - Optional per player mob spawns - int naturalSpawnChunkCount = k; -@@ -488,10 +488,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - // Pufferfish end - } - // Paper end - Optional per player mob spawns -- this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings -+ // this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings // Purpur + List list = this.tickingChunks; - // this.lastSpawnState = spawnercreature_d; // Pufferfish - this is managed asynchronously -- gameprofilerfiller.popPush("spawnAndTick"); -+ //gameprofilerfiller.popPush("spawnAndTick"); // Purpur - boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit - - if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.level.random); // Paper - per player mob spawns - do not need this when per-player is enabled -@@ -529,19 +529,19 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - } - } - } -- this.level.timings.chunkTicks.stopTiming(); // Paper -+ //this.level.timings.chunkTicks.stopTiming(); // Paper // Purpur - -- gameprofilerfiller.popPush("customSpawners"); -+ //gameprofilerfiller.popPush("customSpawners"); // Purpur - if (flag) { -- try (co.aikar.timings.Timing ignored = this.level.timings.miscMobSpawning.startTiming()) { // Paper - timings -+ //try (co.aikar.timings.Timing ignored = this.level.timings.miscMobSpawning.startTiming()) { // Paper - timings // Purpur - this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); -- } // Paper - timings -+ //} // Paper - timings // Purpur + try { +- gameprofilerfiller.push("filteringTickingChunks"); ++ //gameprofilerfiller.push("filteringTickingChunks"); // Purpur + this.collectTickingChunks(list); +- gameprofilerfiller.popPush("shuffleChunks"); ++ //gameprofilerfiller.popPush("shuffleChunks"); // Purpur + // Paper start - chunk tick iteration optimisation + this.shuffleRandom.setSeed(this.level.random.nextLong()); + if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled + // Paper end - chunk tick iteration optimisation +- this.tickChunks(gameprofilerfiller, j, list); +- gameprofilerfiller.pop(); ++ this.tickChunks(null, j, list); // Purpur ++ //gameprofilerfiller.pop(); // Purpur + } finally { + list.clear(); } } -- gameprofilerfiller.popPush("broadcast"); -+ //gameprofilerfiller.popPush("broadcast"); // Purpur - // Paper start - chunk tick iteration optimisations -- this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing -+ //this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing // Purpur - { - final it.unimi.dsi.fastutil.objects.ObjectArrayList chunks = (it.unimi.dsi.fastutil.objects.ObjectArrayList)list; - final ServerChunkCache.ChunkAndHolder[] raw = chunks.elements(); -@@ -555,10 +555,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - holder.holder().broadcastChanges(holder.chunk()); - } - } -- this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing -+ //this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing // Purpur - // Paper end - chunk tick iteration optimisations +- this.broadcastChangedChunks(gameprofilerfiller); - gameprofilerfiller.pop(); -- gameprofilerfiller.pop(); -+ //gameprofilerfiller.pop(); // Purpur ++ this.broadcastChangedChunks(null); // Purpur + //gameprofilerfiller.pop(); // Purpur } - - // Pufferfish start - optimize mob spawning -@@ -773,7 +773,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } + +- private void broadcastChangedChunks(ProfilerFiller profiler) { +- profiler.push("broadcast"); ++ private void broadcastChangedChunks(ProfilerFiller profiler) { // Purpur ++ //profiler.push("broadcast"); // Purpur + Iterator iterator = this.chunkHoldersToBroadcast.iterator(); + + while (iterator.hasNext()) { +@@ -523,7 +523,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } + + this.chunkHoldersToBroadcast.clear(); +- profiler.pop(); ++ //profiler.pop(); // Purpur + } + + private void collectTickingChunks(List chunks) { +@@ -550,7 +550,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } + + private void tickChunks(ProfilerFiller profiler, long timeDelta, List chunks) { +- profiler.popPush("naturalSpawnCount"); ++ //profiler.popPush("naturalSpawnCount"); // Purpur + int j = this.distanceManager.getNaturalSpawnChunkCount(); + // Paper start - Optional per player mob spawns + final int naturalSpawnChunkCount = j; +@@ -577,7 +577,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + // Paper end - Optional per player mob spawns + + this.lastSpawnState = spawnercreature_d; +- profiler.popPush("spawnAndTick"); ++ //profiler.popPush("spawnAndTick"); // Purpur + boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit + int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); + List list1; +@@ -615,7 +615,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } + } + +- profiler.popPush("customSpawners"); ++ //profiler.popPush("customSpawners"); // Purpur + if (flag) { + this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); + } +@@ -813,7 +813,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Override protected void doRunTask(Runnable task) { -- ServerChunkCache.this.level.getProfiler().incrementCounter("runTask"); -+ //ServerChunkCache.this.level.getProfiler().incrementCounter("runTask"); // Purpur +- Profiler.get().incrementCounter("runTask"); ++ //Profiler.get().incrementCounter("runTask"); // Purpur super.doRunTask(task); } diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 5a2f7f7cf79dcbb996574e18cad86ebb54bd718e..dfd09004063a8d8d93357633c8d23b6acff67b73 100644 +index 90eb4927fa51ce3df86aa7b6c71f49150a03e337..d8717af85f539da807ddf866e17f1e643c83d3f6 100644 --- a/src/main/java/net/minecraft/server/level/ServerEntity.java +++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -77,7 +77,7 @@ public class ServerEntity { +@@ -81,7 +81,7 @@ public class ServerEntity { @Nullable private List> trackedDataValues; // CraftBukkit start @@ -2223,10 +1964,10 @@ index 5a2f7f7cf79dcbb996574e18cad86ebb54bd718e..dfd09004063a8d8d93357633c8d23b6a 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 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905211e8b63 100644 +index e65cfb1132f5f0c9e1fa5ae4a46a8abed0c56be1..4c11f0a23ee897691d8a8022baa134ef6f5e3d89 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -221,6 +221,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -223,6 +223,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe private final StructureManager structureManager; private final StructureCheck structureCheck; private final boolean tickTime; @@ -2235,16 +1976,16 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 private final RandomSequences randomSequences; // CraftBukkit start -@@ -229,6 +231,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -230,6 +232,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + public final UUID uuid; 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) + public boolean hasRidableMoveEvent = false; // Purpur public LevelChunk getChunkIfLoaded(int x, int z) { return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately -@@ -519,7 +522,24 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - this.dragonParts = new Int2ObjectOpenHashMap(); +@@ -597,7 +600,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + // CraftBukkit end this.tickTime = flag1; this.server = minecraftserver; - this.customSpawners = list; @@ -2269,20 +2010,20 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 this.serverLevelData = iworlddataserver; ChunkGenerator chunkgenerator = worlddimension.generator(); // CraftBukkit start -@@ -590,6 +610,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); +@@ -669,6 +689,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 -@@ -624,23 +645,23 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -703,24 +724,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } public void tick(BooleanSupplier shouldKeepTicking) { -- ProfilerFiller gameprofilerfiller = this.getProfiler(); -+ //ProfilerFiller gameprofilerfiller = this.getProfiler(); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur this.handlingTick = true; TickRateManager tickratemanager = this.tickRateManager(); @@ -2295,6 +2036,8 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 - gameprofilerfiller.popPush("weather"); + //gameprofilerfiller.popPush("weather"); // Purpur this.advanceWeatherCycle(); +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur } int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); @@ -2305,14 +2048,12 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 // CraftBukkit start j = this.levelData.getDayTime() + 24000L; TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (j - j % 24000L) - this.getDayTime()); -@@ -665,38 +686,38 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -745,30 +766,30 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.tickTime(); } -- gameprofilerfiller.popPush("tickPending"); -- this.timings.scheduledBlocks.startTiming(); // Paper -+ //gameprofilerfiller.popPush("tickPending"); // Purpur -+ //this.timings.scheduledBlocks.startTiming(); // Paper // Purpur +- gameprofilerfiller.push("tickPending"); ++ //gameprofilerfiller.push("tickPending"); // Purpur if (!this.isDebug() && flag) { j = this.getGameTime(); - gameprofilerfiller.push("blockTicks"); @@ -2324,34 +2065,20 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 - gameprofilerfiller.pop(); + //gameprofilerfiller.pop(); // Purpur } -- this.timings.scheduledBlocks.stopTiming(); // Paper -+ //this.timings.scheduledBlocks.stopTiming(); // Paper // Purpur - gameprofilerfiller.popPush("raid"); + //gameprofilerfiller.popPush("raid"); // Purpur if (flag) { -- this.timings.raids.startTiming(); // Paper - timings -+ // this.timings.raids.startTiming(); // Paper - timings // Purpur this.raids.tick(); -- this.timings.raids.stopTiming(); // Paper - timings -+ // this.timings.raids.stopTiming(); // Paper - timings // Purpur } - gameprofilerfiller.popPush("chunkSource"); -- this.timings.chunkProviderTick.startTiming(); // Paper - timings + //gameprofilerfiller.popPush("chunkSource"); // Purpur -+ //this.timings.chunkProviderTick.startTiming(); // Paper - timings // Purpur this.getChunkSource().tick(shouldKeepTicking, true); -- this.timings.chunkProviderTick.stopTiming(); // Paper - timings - gameprofilerfiller.popPush("blockEvents"); -+ //this.timings.chunkProviderTick.stopTiming(); // Paper - timings // Purpur + //gameprofilerfiller.popPush("blockEvents"); // Purpur if (flag) { -- this.timings.doSounds.startTiming(); // Spigot -+ // this.timings.doSounds.startTiming(); // Spigot // Purpur this.runBlockEvents(); -- this.timings.doSounds.stopTiming(); // Spigot -+ // this.timings.doSounds.stopTiming(); // Spigot // Purpur } this.handlingTick = false; @@ -2360,14 +2087,12 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 boolean flag1 = !paperConfig().unsupportedSettings.disableWorldTickingWhenEmpty || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players // Paper - restore this if (flag1) { -@@ -704,25 +725,25 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -776,20 +797,20 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } if (flag1 || this.emptyTime++ < 300) { - gameprofilerfiller.push("entities"); -- this.timings.tickEntities.startTiming(); // Spigot + //gameprofilerfiller.push("entities"); // Purpur -+ //this.timings.tickEntities.startTiming(); // Spigot // Purpur if (this.dragonFight != null && flag) { - gameprofilerfiller.push("dragonFight"); + //gameprofilerfiller.push("dragonFight"); // Purpur @@ -2377,46 +2102,31 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 } org.spigotmc.ActivationRange.activateEntities(this); // Spigot -- this.timings.entityTick.startTiming(); // Spigot -+ //this.timings.entityTick.startTiming(); // Spigot // Purpur 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(); - } else if (!tickratemanager.isEntityFrozen(entity)) { + if (!tickratemanager.isEntityFrozen(entity)) { - gameprofilerfiller.push("checkDespawn"); + //gameprofilerfiller.push("checkDespawn"); // Purpur entity.checkDespawn(); - gameprofilerfiller.pop(); + //gameprofilerfiller.pop(); // Purpur - if (true || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { // Paper - rewrite chunk system + if (true) { // Paper - rewrite chunk system Entity entity1 = entity.getVehicle(); -@@ -734,7 +755,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -801,20 +822,20 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe entity.stopRiding(); } - gameprofilerfiller.push("tick"); + //gameprofilerfiller.push("tick"); // Purpur - // Pufferfish start - copied from this.guardEntityTick - try { - this.tickNonPassenger(entity); // Pufferfish - changed -@@ -749,20 +770,20 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - } - this.moonrise$midTickTasks(); // Paper - rewrite chunk system - // Pufferfish end + this.guardEntityTick(this::tickNonPassenger, entity); - gameprofilerfiller.pop(); + //gameprofilerfiller.pop(); // Purpur } } } }); -- this.timings.entityTick.stopTiming(); // Spigot -- this.timings.tickEntities.stopTiming(); // Spigot - gameprofilerfiller.pop(); -+ //this.timings.entityTick.stopTiming(); // Spigot // Purpur -+ //this.timings.tickEntities.stopTiming(); // Spigot // Purpur + //gameprofilerfiller.pop(); // Purpur this.tickBlockEntities(); } @@ -2429,10 +2139,10 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 } @Override -@@ -780,6 +801,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - this.serverLevelData.setGameTime(i); +@@ -834,6 +855,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.serverLevelData.getScheduledEvents().tick(this.server, i); - if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + Profiler.get().pop(); + if (this.serverLevelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + // Purpur start + int incrementTicks = isDay() ? this.purpurConfig.daytimeTicks : this.purpurConfig.nighttimeTicks; + if (incrementTicks != 12000) { @@ -2443,14 +2153,14 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 this.setDayTime(this.levelData.getDayTime() + 1L); } -@@ -788,7 +816,21 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -842,7 +870,21 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public void setDayTime(long timeOfDay) { this.serverLevelData.setDayTime(timeOfDay); + // Purpur start + this.preciseTime = timeOfDay; + this.forceTime = false; - } ++ } + public void setDayTime(double i) { + this.serverLevelData.setDayTime((long) i); + this.forceTime = true; @@ -2460,33 +2170,34 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 + // Purpur start + public boolean isForceTime() { + return this.forceTime; -+ } + } + // Purpur end public void tickCustomSpawners(boolean spawnMonsters, boolean spawnAnimals) { Iterator iterator = this.customSpawners.iterator(); -@@ -874,8 +916,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -920,9 +962,9 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe boolean flag = this.isRaining(); int j = chunkcoordintpair.getMinBlockX(); int k = chunkcoordintpair.getMinBlockZ(); -- ProfilerFiller gameprofilerfiller = this.getProfiler(); -- gameprofilerfiller.push("thunder"); -+ //ProfilerFiller gameprofilerfiller = this.getProfiler(); // Purpur -+ //gameprofilerfiller.push("thunder"); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur - if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && /*this.random.nextInt(this.spigotConfig.thunderChance) == 0 &&*/ chunk.shouldDoLightning(this.random)) { // Spigot // Paper - Option to disable thunder // Pufferfish - replace random with shouldDoLightning +- gameprofilerfiller.push("thunder"); ++ //gameprofilerfiller.push("thunder"); // Purpur + if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && simpleRandom.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - Option to disable thunder // Paper - optimise random ticking BlockPos blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); -@@ -885,10 +927,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + +@@ -931,10 +973,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 @@ -2497,7 +2208,7 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 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 -@@ -905,7 +955,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -951,7 +1001,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } } @@ -2506,26 +2217,22 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 if (!this.paperConfig().environment.disableIceAndSnow) { // Paper - Option to disable ice and snow for (int l = 0; l < randomTickSpeed; ++l) { -@@ -915,14 +965,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -961,12 +1011,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } } // Paper - Option to disable ice and snow - gameprofilerfiller.popPush("tickBlocks"); -- timings.chunkTicksBlocks.startTiming(); // Paper + //gameprofilerfiller.popPush("tickBlocks"); // Purpur -+ //timings.chunkTicksBlocks.startTiming(); // Paper // Purpur if (randomTickSpeed > 0) { this.optimiseRandomTick(chunk, randomTickSpeed); // Paper - optimise random ticking } -- timings.chunkTicksBlocks.stopTiming(); // Paper - gameprofilerfiller.pop(); -+ //timings.chunkTicksBlocks.stopTiming(); // Paper // Purpur + //gameprofilerfiller.pop(); // Purpur } @VisibleForTesting -@@ -971,7 +1021,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1015,7 +1065,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; @@ -2534,7 +2241,7 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 return optional.map((blockposition1) -> { return blockposition1.above(1); -@@ -1020,11 +1070,27 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1064,11 +1114,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); @@ -2563,7 +2270,7 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 ichatmutablecomponent = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(i)); } -@@ -1164,6 +1230,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1208,6 +1274,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @VisibleForTesting public void resetWeatherCycle() { // CraftBukkit start @@ -2571,7 +2278,7 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 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.... -@@ -1171,6 +1238,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1215,6 +1282,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.serverLevelData.setRainTime(0); } // CraftBukkit end @@ -2579,52 +2286,36 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 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. -@@ -1246,24 +1314,24 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1287,18 +1355,18 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // Spigot end - // Paper start- timings - final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); -- timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper -- try { -+ //timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper // Purpur -+ //try { // Purpur - // Paper end - timings + final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); // Paper - EAR 2 entity.setOldPosAndRot(); -- ProfilerFiller gameprofilerfiller = this.getProfiler(); -+ //ProfilerFiller gameprofilerfiller = this.getProfiler(); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur ++entity.tickCount; -- this.getProfiler().push(() -> { -+ /*this.getProfiler().push(() -> { // Purpur +- gameprofilerfiller.push(() -> { ++ /*gameprofilerfiller.push(() -> { // Purpur return BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString(); - }); - gameprofilerfiller.incrementCounter("tickNonPassenger"); + });*/ // Purpur + //gameprofilerfiller.incrementCounter("tickNonPassenger"); // Purpur if (isActive) { // Paper - EAR 2 - TimingHistory.activatedEntityTicks++; entity.tick(); entity.postTick(); // CraftBukkit } else { entity.inactiveTick(); } // Paper - EAR 2 -- this.getProfiler().pop(); -- } finally { timer.stopTiming(); } // Paper - timings -+ //this.getProfiler().pop(); // Purpur -+ //} finally { timer.stopTiming(); } // Paper - timings // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur Iterator iterator = entity.getPassengers().iterator(); while (iterator.hasNext()) { -@@ -1286,17 +1354,17 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1321,12 +1389,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe if (passenger instanceof Player || this.entityTickList.contains(passenger)) { - // Paper - EAR 2 - final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); -- co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper -- try { -+ //co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper // Purpur -+ //try { // Purpur - // Paper end passenger.setOldPosAndRot(); ++passenger.tickCount; -- ProfilerFiller gameprofilerfiller = this.getProfiler(); -+ //ProfilerFiller gameprofilerfiller = this.getProfiler(); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur - gameprofilerfiller.push(() -> { + /*gameprofilerfiller.push(() -> { // Purpur @@ -2636,8 +2327,8 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 // Paper start - EAR 2 if (isActive) { passenger.rideTick(); -@@ -1308,7 +1376,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - vehicle.positionRider(passenger); +@@ -1338,7 +1406,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + vehicle.positionRider(passenger); } // Paper end - EAR 2 - gameprofilerfiller.pop(); @@ -2645,57 +2336,7 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 Iterator iterator = passenger.getPassengers().iterator(); while (iterator.hasNext()) { -@@ -1317,7 +1385,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - this.tickPassenger(passenger, entity2); - } - -- } finally { timer.stopTiming(); }// Paper - EAR2 timings -+ //} finally { timer.stopTiming(); }// Paper - EAR2 timings // Purpur - } - } else { - passenger.stopRiding(); -@@ -1337,7 +1405,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); - } - -- try (co.aikar.timings.Timing ignored = this.timings.worldSave.startTiming()) { -+ //try (co.aikar.timings.Timing ignored = this.timings.worldSave.startTiming()) { // Purpur - if (doFull) { - this.saveLevelData(true); - } -@@ -1354,7 +1422,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); - } - // CraftBukkit end -- } -+ //} // Purpur - } - // Paper end - Incremental chunk and player saving - -@@ -1368,7 +1436,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - - if (!savingDisabled) { - org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(this.getWorld())); // CraftBukkit -- try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper -+ //try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper // Purpur // Purpur - if (progressListener != null) { - progressListener.progressStartNoAbort(Component.translatable("menu.savingLevel")); - } -@@ -1378,10 +1446,10 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - progressListener.progressStage(Component.translatable("menu.savingChunks")); - } - -- timings.worldSaveChunks.startTiming(); // Paper -+ //timings.worldSaveChunks.startTiming(); // Paper // Purpur - if (!close) { chunkproviderserver.save(flush); } // Paper - add close param -- timings.worldSaveChunks.stopTiming(); // Paper -- }// Paper -+ //timings.worldSaveChunks.stopTiming(); // Paper // Purpur -+ //}// Paper // Purpur - // Paper - rewrite chunk system - - } -@@ -2613,7 +2681,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2734,7 +2802,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 @@ -2705,10 +2346,10 @@ index 2a8ffcdd262ea73844500846c6401cdda7153d61..067b10134b087626e05596225744b905 } // 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 c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3bb802e635 100644 +index 4e4e5b7e8c387cf13cf5bc5e39d334c3222c9103..627b69f08f609dc0a4d87327a187009651046cf4 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -302,6 +302,10 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -329,6 +329,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 @@ -2719,7 +2360,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b // Paper start - rewrite chunk system private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader; -@@ -599,6 +603,9 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -691,6 +695,9 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple }); } @@ -2729,17 +2370,17 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b } @Override -@@ -675,6 +682,9 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple - }); +@@ -743,6 +750,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 -@@ -804,6 +814,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); @@ -2755,7 +2396,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b } private void updatePlayerAttributes() { -@@ -1069,6 +1088,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(); @@ -2763,8 +2404,8 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b if (scoreboardteam != null && scoreboardteam.getDeathMessageVisibility() != Team.Visibility.ALWAYS) { if (scoreboardteam.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { this.server.getPlayerList().broadcastSystemToTeam(this, ichatbasecomponent); -@@ -1172,6 +1192,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 @@ -2780,42 +2421,42 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b boolean flag = this.server.isDedicatedServer() && this.isPvpAllowed() && source.is(DamageTypeTags.IS_FALL); if (!flag && this.spawnInvulnerableTime > 0 && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) { -@@ -1371,7 +1401,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -1642,15 +1672,15 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple this.unsetRemoved(); */ // CraftBukkit end -- worldserver1.getProfiler().push("moving"); -+ //worldserver1.getProfiler().push("moving"); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("moving"); ++ //gameprofilerfiller.push("moving"); // Purpur if (worldserver != null && resourcekey == LevelStem.OVERWORLD && worldserver.getTypeKey() == LevelStem.NETHER) { // CraftBukkit - empty to fall through to null to event this.enteredNetherPosition = this.position(); } -@@ -1387,8 +1417,8 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple - worldserver = ((CraftWorld) exit.getWorld()).getHandle(); - // CraftBukkit end -- worldserver1.getProfiler().pop(); -- worldserver1.getProfiler().push("placing"); -+ //worldserver1.getProfiler().pop(); // Purpur -+ //worldserver1.getProfiler().push("placing"); // Purpur +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("placing"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("placing"); // Purpur // CraftBukkit start this.isChangingDimension = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds LevelData worlddata = worldserver.getLevelData(); -@@ -1401,11 +1431,12 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -1663,11 +1693,12 @@ 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(); worldserver.addDuringTeleport(this); -- worldserver1.getProfiler().pop(); -+ //worldserver1.getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur this.triggerDimensionChangeTriggers(worldserver1); + this.stopUsingItem(); this.connection.send(new ClientboundPlayerAbilitiesPacket(this.getAbilities())); - playerlist.sendLevelInfo(this, worldserver); -@@ -1505,7 +1536,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple - return entitymonster.isPreventingPlayerRest(this); +@@ -1773,7 +1804,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple + return entitymonster.isPreventingPlayerRest(this.serverLevel(), this); }); - if (!list.isEmpty()) { @@ -2823,7 +2464,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b return Either.left(net.minecraft.world.entity.player.Player.BedSleepingProblem.NOT_SAFE); } } -@@ -1545,7 +1576,19 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -1813,7 +1844,19 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple }); if (!this.serverLevel().canSleepThroughNights()) { @@ -2844,7 +2485,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b } ((ServerLevel) this.level()).updateSleepingPlayerList(); -@@ -1667,6 +1710,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -1935,6 +1978,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple @Override public void openTextEdit(SignBlockEntity sign, boolean front) { @@ -2852,7 +2493,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b this.connection.send(new ClientboundBlockUpdatePacket(this.level(), sign.getBlockPos())); this.connection.send(new ClientboundOpenSignEditorPacket(sign.getBlockPos(), front)); } -@@ -2007,6 +2051,26 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -2251,6 +2295,26 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple this.lastSentExp = -1; // CraftBukkit - Added to reset } @@ -2879,7 +2520,28 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b @Override public void displayClientMessage(Component message, boolean overlay) { this.sendSystemMessage(message, overlay); -@@ -2341,8 +2405,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); + } +@@ -2599,8 +2677,68 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple public void resetLastActionTime() { this.lastActionTime = Util.getMillis(); @@ -2948,7 +2610,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b public ServerStatsCounter getStats() { return this.stats; } -@@ -2946,4 +3070,50 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -3307,4 +3445,50 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple return (CraftPlayer) super.getBukkitEntity(); } // CraftBukkit end @@ -2968,7 +2630,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b + + 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); + } @@ -3000,10 +2662,10 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..4f72ce384f4c0dbae98effa89aed5c3b + // 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; } @@ -3011,7 +2673,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) { @@ -3019,16 +2681,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; } @@ -3048,7 +2710,7 @@ index ee9e4521079137d7b72194e8789810e7a89b8e75..28731f0c5b0ba63fa8d5ce3ee580bf31 + // Purpur end } diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java -index 5a8a33638ceb1d980ffc3e6dd86e7eb11dfd9375..1c059f4698cfe944ab21cb62f9f3ccb7f7065e08 100644 +index e4b0dc3121101d54394a0c3a413dabf8103b2ea6..a8484b9659f175cc20985bf66082616ceb31df4d 100644 --- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java +++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java @@ -336,6 +336,7 @@ public class WorldGenRegion implements WorldGenLevel { @@ -3060,10 +2722,10 @@ index 5a8a33638ceb1d980ffc3e6dd86e7eb11dfd9375..1c059f4698cfe944ab21cb62f9f3ccb7 Util.logAndPauseIfInIde("Detected setBlock in a far chunk [" + i + ", " + j + "], pos: " + String.valueOf(pos) + ", status: " + String.valueOf(this.generatingStep.targetStatus()) + (this.currentlyGenerating == null ? "" : ", currently generating: " + (String) this.currentlyGenerating.get())); hasSetFarWarned = true; diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..a9d54c80f682d826ad272731bd6477eed0fd44d5 100644 +index b0bc66dc7248aae691dcab68b925b52a1695e63f..49cb116fd55e6d5cd36b9773b39191e4ab06b7e0 100644 --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -@@ -79,11 +79,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -80,11 +80,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack private long keepAliveChallenge; private long closedListenerTime; private boolean closed = false; @@ -3077,7 +2739,7 @@ index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..a9d54c80f682d826ad272731bd6477ee public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit this.server = minecraftserver; -@@ -129,6 +131,16 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -136,6 +138,16 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack @Override public void handleKeepAlive(ServerboundKeepAlivePacket packet) { @@ -3094,7 +2756,7 @@ index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..a9d54c80f682d826ad272731bd6477ee //PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // CraftBukkit // Paper - handle ServerboundKeepAlivePacket async if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) { int i = (int) (Util.getMillis() - this.keepAliveTime); -@@ -172,6 +184,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -179,6 +191,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 } @@ -3108,12 +2770,12 @@ index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..a9d54c80f682d826ad272731bd6477ee } else if (identifier.equals(ServerCommonPacketListenerImpl.CUSTOM_UNREGISTER)) { try { String channels = payload.toString(com.google.common.base.Charsets.UTF_8); -@@ -248,12 +267,27 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -255,12 +274,27 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } protected void keepConnectionAlive() { -- this.server.getProfiler().push("keepAlive"); -+ //this.server.getProfiler().push("keepAlive"); // Purpur +- Profiler.get().push("keepAlive"); ++ //Profiler.get().push("keepAlive"); // Purpur // Paper start - give clients a longer time to respond to pings as per pre 1.12.2 timings // This should effectively place the keepalive handling back to "as it was" before 1.12.2 long currentTime = Util.getMillis(); @@ -3137,20 +2799,20 @@ index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..a9d54c80f682d826ad272731bd6477ee if (!this.isSingleplayerOwner() && elapsedTime >= 15000L) { // Paper - use vanilla's 15000L between keep alive packets if (this.keepAlivePending && !this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // Paper - check keepalive limit, don't fire if already disconnected this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause -@@ -266,7 +300,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -273,7 +307,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } // Paper end - give clients a longer time to respond to pings as per pre 1.12.2 timings -- this.server.getProfiler().pop(); -+ //this.server.getProfiler().pop(); // Purpur +- Profiler.get().pop(); ++ //Profiler.get().pop(); // Purpur } private boolean checkIfClosed(long time) { diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b723af92f3d 100644 +index c4b016a2fb5c79fb3f191e243712bee7cbe5cd2c..61b19f52aeb371abdd29f41291099f35a9b4c258 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 @@ -3171,9 +2833,9 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 @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); @@ -3184,7 +2846,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 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(); @@ -3193,7 +2855,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 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) { @@ -3201,7 +2863,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 this.disconnect((Component) Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause return; } -@@ -1166,6 +1189,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1180,6 +1203,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; @@ -3212,7 +2874,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 for (final String page : pageList) { final int byteLength = page.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; byteTotal += byteLength; -@@ -1190,7 +1217,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1204,7 +1231,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } if (byteTotal > byteAllowed) { @@ -3222,10 +2884,10 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 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; } -@@ -1215,10 +1243,14 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - +@@ -1226,10 +1254,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"); @@ -3239,7 +2901,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 }; this.filterTextPacket((List) list).thenAcceptAsync(consumer, this.server); -@@ -1226,13 +1258,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1237,13 +1269,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } private void updateBookContents(List pages, int slotId) { @@ -3253,13 +2915,13 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 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) -@@ -1240,6 +1277,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1251,6 +1288,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } private void signBook(FilteredText title, List pages, int slotId) { @@ -3270,8 +2932,8 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 + // Purpur end ItemStack itemstack = this.player.getInventory().getItem(slotId); - if (itemstack.is(Items.WRITABLE_BOOK)) { -@@ -1247,10 +1289,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + if (itemstack.has(DataComponents.WRITABLE_BOOK_CONTENT)) { +@@ -1258,10 +1300,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl itemstack1.remove(DataComponents.WRITABLE_BOOK_CONTENT); List> list1 = (List>) (List) pages.stream().map((filteredtext1) -> { // CraftBukkit - decompile error @@ -3284,7 +2946,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 CraftEventFactory.handleEditBookEvent(this.player, slotId, itemstack, itemstack1); // CraftBukkit this.player.getInventory().setItem(slotId, itemstack); // CraftBukkit - event factory updates the hand book } -@@ -1260,6 +1302,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1271,6 +1313,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl return this.player.isTextFilteringEnabled() ? Filterable.passThrough(message.filteredOrEmpty()) : Filterable.from(message); } @@ -3301,7 +2963,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 @Override public void handleEntityTagQuery(ServerboundEntityTagQueryPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); -@@ -1309,7 +1361,15 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1320,7 +1372,15 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl @Override public void handleMovePlayer(ServerboundMovePlayerPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -3318,7 +2980,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 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(); -@@ -1489,7 +1549,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1500,7 +1560,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl movedWrongly = true; if (event.getLogWarning()) // Paper end @@ -3327,7 +2989,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 } // Paper } -@@ -1557,6 +1617,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1568,6 +1628,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.lastYaw = to.getYaw(); this.lastPitch = to.getPitch(); @@ -3336,7 +2998,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 Location oldTo = to.clone(); PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); this.cserver.getPluginManager().callEvent(event); -@@ -1601,6 +1663,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1613,6 +1675,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.player.tryResetCurrentImpulseContext(); } @@ -3350,7 +3012,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 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(); -@@ -1628,6 +1697,14 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1652,6 +1721,14 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } } @@ -3365,7 +3027,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 // 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<>(); -@@ -2007,6 +2084,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2024,6 +2101,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl boolean cancelled; if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) { @@ -3373,15 +3035,15 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemstack, enumhand); cancelled = event.useItemInHand() == Event.Result.DENY; } else { -@@ -2788,6 +2866,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2807,6 +2885,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); -@@ -2801,6 +2880,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2820,6 +2899,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl ServerGamePacketListenerImpl.this.cserver.getPluginManager().callEvent(event); @@ -3391,7 +3053,7 @@ index 8f2214008d76d00267152b5db0cf0fbdd3fbbfb7..fd22a6709c7ffd828fbab5b8723f2b72 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 40638b439966619e9c70a18a32abd95b2178fe9f..19d3423644a6a394743c09eb6935bb7633a329a2 100644 +index 033755682c61c889723c3669b5cff4de147f637e..16069b9cbf6c7679c28a2e9a54e77d23cd10e541 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -322,7 +322,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, @@ -3416,38 +3078,36 @@ index 532f09089b8d6798999cf3f83e852df7479e450e..43c63d203859eaa0999937e2f9254c22 // Paper end } diff --git a/src/main/java/net/minecraft/server/packs/resources/ResourceManagerReloadListener.java b/src/main/java/net/minecraft/server/packs/resources/ResourceManagerReloadListener.java -index f14113eef226e906c0d21641e74a27471254909d..0c25f3ed0a8a538edc7cadd3476100c9b3631f7a 100644 +index d2d82e4f22bfeac8881b6815e4bef56c254fded9..abc92e09b7bb636612f04ace8232947c8d454e68 100644 --- a/src/main/java/net/minecraft/server/packs/resources/ResourceManagerReloadListener.java +++ b/src/main/java/net/minecraft/server/packs/resources/ResourceManagerReloadListener.java -@@ -16,11 +16,11 @@ public interface ResourceManagerReloadListener extends PreparableReloadListener - Executor applyExecutor +@@ -12,10 +12,10 @@ public interface ResourceManagerReloadListener extends PreparableReloadListener + PreparableReloadListener.PreparationBarrier synchronizer, ResourceManager manager, Executor prepareExecutor, Executor applyExecutor ) { return synchronizer.wait(Unit.INSTANCE).thenRunAsync(() -> { -- applyProfiler.startTick(); -- applyProfiler.push("listener"); -+ //applyProfiler.startTick(); // Purpur -+ //applyProfiler.push("listener"); // Purpur +- ProfilerFiller profilerFiller = Profiler.get(); +- profilerFiller.push("listener"); ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur ++ //profilerFiller.push("listener"); // Purpur this.onResourceManagerReload(manager); -- applyProfiler.pop(); -- applyProfiler.endTick(); -+ //applyProfiler.pop(); // Purpur -+ //applyProfiler.endTick(); // Purpur +- profilerFiller.pop(); ++ //profilerFiller.pop(); // Purpur }, applyExecutor); } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 5e2c4969e77c669acbb4a13c07033cb267c3d586..0ea07da1b4bd420cd6765577b4719a2368b5740c 100644 +index cf42042c754b30e41c0ec8a6a15195369bdbd199..a32ab50f74ee75141d1d61b8052aa149121a3670 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -480,6 +480,7 @@ public abstract class PlayerList { +@@ -419,6 +419,7 @@ public abstract class PlayerList { scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); } // Paper end - Configurable player collision + org.purpurmc.purpur.task.BossBarTask.addToAll(player); // Purpur PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ()); - } - -@@ -591,6 +592,7 @@ public abstract class PlayerList { + // Paper start - Send empty chunk, so players aren't stuck in the world loading screen with our chunk system not sending chunks when dead + if (player.isDeadOrDying()) { +@@ -540,6 +541,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 @@ -3455,7 +3115,7 @@ index 5e2c4969e77c669acbb4a13c07033cb267c3d586..0ea07da1b4bd420cd6765577b4719a23 ServerLevel worldserver = entityplayer.serverLevel(); entityplayer.awardStat(Stats.LEAVE_GAME); -@@ -746,7 +748,7 @@ public abstract class PlayerList { +@@ -703,7 +705,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; @@ -3464,7 +3124,7 @@ index 5e2c4969e77c669acbb4a13c07033cb267c3d586..0ea07da1b4bd420cd6765577b4719a23 event.disallow(PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure } } -@@ -1026,6 +1028,20 @@ public abstract class PlayerList { +@@ -985,6 +987,20 @@ public abstract class PlayerList { } // CraftBukkit end @@ -3485,7 +3145,7 @@ index 5e2c4969e77c669acbb4a13c07033cb267c3d586..0ea07da1b4bd420cd6765577b4719a23 public void broadcastAll(Packet packet, ResourceKey dimension) { Iterator iterator = this.players.iterator(); -@@ -1129,6 +1145,7 @@ public abstract class PlayerList { +@@ -1088,6 +1104,7 @@ public abstract class PlayerList { } else { b0 = (byte) (24 + permissionLevel); } @@ -3493,7 +3153,7 @@ index 5e2c4969e77c669acbb4a13c07033cb267c3d586..0ea07da1b4bd420cd6765577b4719a23 player.connection.send(new ClientboundEntityEventPacket(player, b0)); } -@@ -1137,6 +1154,27 @@ public abstract class PlayerList { +@@ -1096,6 +1113,27 @@ public abstract class PlayerList { player.getBukkitEntity().recalculatePermissions(); // CraftBukkit this.server.getCommands().sendCommands(player); } // Paper - Add sendOpLevel API @@ -3521,24 +3181,6 @@ index 5e2c4969e77c669acbb4a13c07033cb267c3d586..0ea07da1b4bd420cd6765577b4719a23 } public boolean isWhiteListed(GameProfile profile) { -@@ -1200,7 +1238,7 @@ public abstract class PlayerList { - - public void saveAll(int interval) { - io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main -- MinecraftTimings.savePlayers.startTiming(); // Paper -+ //MinecraftTimings.savePlayers.startTiming(); // Paper // Purpur - int numSaved = 0; - long now = MinecraftServer.currentTick; - for (int i = 0; i < this.players.size(); ++i) { -@@ -1211,7 +1249,7 @@ public abstract class PlayerList { - } - // Paper end - Incremental chunk and player saving - } -- MinecraftTimings.savePlayers.stopTiming(); // Paper -+ //MinecraftTimings.savePlayers.stopTiming(); // Paper // Purpur - return null; }); // Paper - ensure main - } - diff --git a/src/main/java/net/minecraft/server/players/SleepStatus.java b/src/main/java/net/minecraft/server/players/SleepStatus.java index 823efad652d8ff9e96b99375b102fef6f017716e..caa8a69bde0c212c36dd990a67836ac2f95548c0 100644 --- a/src/main/java/net/minecraft/server/players/SleepStatus.java @@ -3562,19 +3204,19 @@ index 823efad652d8ff9e96b99375b102fef6f017716e..caa8a69bde0c212c36dd990a67836ac2 } // CraftBukkit start diff --git a/src/main/java/net/minecraft/stats/ServerRecipeBook.java b/src/main/java/net/minecraft/stats/ServerRecipeBook.java -index 8a2584deccbf19de8a18fcfcb9c65318b60afe57..6146ca9fef0e33601c132d4867c9399e7f8f807c 100644 +index 5c7484ce2850a2eb698a2183b81134b89b0bbcc7..fef09e71f73f6f24a01289ef05c20a5ffc5fadb1 100644 --- a/src/main/java/net/minecraft/stats/ServerRecipeBook.java +++ b/src/main/java/net/minecraft/stats/ServerRecipeBook.java -@@ -125,6 +125,7 @@ public class ServerRecipeBook extends RecipeBook { - Optional> optional = recipeManager.byKey(minecraftkey); +@@ -159,6 +159,7 @@ public class ServerRecipeBook extends RecipeBook { + ResourceKey> resourcekey = ResourceKey.create(Registries.RECIPE, ResourceLocation.parse(s)); - if (optional.isEmpty()) { + if (!validPredicate.test(resourcekey)) { + if (!org.purpurmc.purpur.PurpurConfig.loggerSuppressUnrecognizedRecipeErrors) // Purpur - ServerRecipeBook.LOGGER.error("Tried to load unrecognized recipe: {} removed now.", minecraftkey); + ServerRecipeBook.LOGGER.error("Tried to load unrecognized recipe: {} removed now.", resourcekey); } else { - handler.accept((RecipeHolder) optional.get()); + handler.accept(resourcekey); 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 { @@ -3636,10 +3278,10 @@ index bce2dac613d29083dd5fbb68739304cc5a6d4d27..600a7036b503f60cc9c95f189f73c2db private ActiveProfiler.PathEntry getCurrentEntry() { diff --git a/src/main/java/net/minecraft/util/profiling/ProfilerFiller.java b/src/main/java/net/minecraft/util/profiling/ProfilerFiller.java -index a715ecf4a8ac91d3e5e5c6269d89e54b2c1cd279..223c3665126c576eddb1a8f7c9f5bc60c6ff9818 100644 +index bc5c8879befe849ce81becf5e3fba6757b01cb70..ce81d6bd87f688a24003f2fbf6d5010ad6273917 100644 --- a/src/main/java/net/minecraft/util/profiling/ProfilerFiller.java +++ b/src/main/java/net/minecraft/util/profiling/ProfilerFiller.java -@@ -6,32 +6,44 @@ import net.minecraft.util.profiling.metrics.MetricCategory; +@@ -6,51 +6,68 @@ import net.minecraft.util.profiling.metrics.MetricCategory; public interface ProfilerFiller { String ROOT = "root"; @@ -3664,6 +3306,30 @@ index a715ecf4a8ac91d3e5e5c6269d89e54b2c1cd279..223c3665126c576eddb1a8f7c9f5bc60 + @io.papermc.paper.annotation.DoNotUse // Purpur void popPush(Supplier locationGetter); ++ @io.papermc.paper.annotation.DoNotUse // Purpur + default void addZoneText(String label) { + } + ++ @io.papermc.paper.annotation.DoNotUse // Purpur + default void addZoneValue(long value) { + } + ++ @io.papermc.paper.annotation.DoNotUse // Purpur + default void setZoneColor(int color) { + } + ++ @io.papermc.paper.annotation.DoNotUse // Purpur + default Zone zone(String name) { + this.push(name); + return new Zone(this); + } + ++ @io.papermc.paper.annotation.DoNotUse // Purpur + default Zone zone(Supplier nameSupplier) { + this.push(nameSupplier); + return new Zone(this); + } + + @io.papermc.paper.annotation.DoNotUse // Purpur void markForCharting(MetricCategory type); @@ -3685,90 +3351,114 @@ index a715ecf4a8ac91d3e5e5c6269d89e54b2c1cd279..223c3665126c576eddb1a8f7c9f5bc60 + @io.papermc.paper.annotation.DoNotUse // Purpur void incrementCounter(Supplier markerGetter, int num); - static ProfilerFiller tee(ProfilerFiller a, ProfilerFiller b) { -@@ -41,62 +53,62 @@ public interface ProfilerFiller { - return b == InactiveProfiler.INSTANCE ? a : new ProfilerFiller() { - @Override - public void startTick() { -- a.startTick(); -- b.startTick(); -+ //a.startTick(); // Purpur -+ //b.startTick(); // Purpur - } + static ProfilerFiller combine(ProfilerFiller first, ProfilerFiller second) { +@@ -72,80 +89,80 @@ public interface ProfilerFiller { - @Override - public void endTick() { -- a.endTick(); -- b.endTick(); -+ //a.endTick(); // Purpur -+ //b.endTick(); // Purpur - } - - @Override - public void push(String location) { -- a.push(location); -- b.push(location); -+ //a.push(location); // Purpur -+ //b.push(location); // Purpur - } - - @Override - public void push(Supplier locationGetter) { -- a.push(locationGetter); -- b.push(locationGetter); -+ //a.push(locationGetter); // Purpur -+ //b.push(locationGetter); // Purpur - } - - @Override - public void markForCharting(MetricCategory type) { -- a.markForCharting(type); -- b.markForCharting(type); -+ //a.markForCharting(type); // Purpur -+ //b.markForCharting(type); // Purpur - } - - @Override - public void pop() { -- a.pop(); -- b.pop(); -+ //a.pop(); // Purpur -+ //b.pop(); // Purpur - } - - @Override - public void popPush(String location) { -- a.popPush(location); -- b.popPush(location); -+ //a.popPush(location); // Purpur -+ //b.popPush(location); // Purpur - } - - @Override - public void popPush(Supplier locationGetter) { -- a.popPush(locationGetter); -- b.popPush(locationGetter); -+ //a.popPush(locationGetter); // Purpur -+ //b.popPush(locationGetter); // Purpur - } - - @Override - public void incrementCounter(String marker, int num) { -- a.incrementCounter(marker, num); -- b.incrementCounter(marker, num); -+ //a.incrementCounter(marker, num); // Purpur -+ //b.incrementCounter(marker, num); // Purpur - } - - @Override - public void incrementCounter(Supplier markerGetter, int num) { -- a.incrementCounter(markerGetter, num); -- b.incrementCounter(markerGetter, num); -+ //a.incrementCounter(markerGetter, num); // Purpur -+ //b.incrementCounter(markerGetter, num); // Purpur - } - }; + @Override + public void startTick() { +- this.first.startTick(); +- this.second.startTick(); ++ //this.first.startTick(); // Purpur ++ //this.second.startTick(); // Purpur } + + @Override + public void endTick() { +- this.first.endTick(); +- this.second.endTick(); ++ //this.first.endTick(); // Purpur ++ //this.second.endTick(); // Purpur + } + + @Override + public void push(String location) { +- this.first.push(location); +- this.second.push(location); ++ //this.first.push(location); // Purpur ++ //this.second.push(location); // Purpur + } + + @Override + public void push(Supplier locationGetter) { +- this.first.push(locationGetter); +- this.second.push(locationGetter); ++ //this.first.push(locationGetter); // Purpur ++ //this.second.push(locationGetter); // Purpur + } + + @Override + public void markForCharting(MetricCategory type) { +- this.first.markForCharting(type); +- this.second.markForCharting(type); ++ //this.first.markForCharting(type); // Purpur ++ //this.second.markForCharting(type); // Purpur + } + + @Override + public void pop() { +- this.first.pop(); +- this.second.pop(); ++ //this.first.pop(); // Purpur ++ //this.second.pop(); // Purpur + } + + @Override + public void popPush(String location) { +- this.first.popPush(location); +- this.second.popPush(location); ++ //this.first.popPush(location); // Purpur ++ //this.second.popPush(location); // Purpur + } + + @Override + public void popPush(Supplier locationGetter) { +- this.first.popPush(locationGetter); +- this.second.popPush(locationGetter); ++ //this.first.popPush(locationGetter); // Purpur ++ //this.second.popPush(locationGetter); // Purpur + } + + @Override + public void incrementCounter(String marker, int num) { +- this.first.incrementCounter(marker, num); +- this.second.incrementCounter(marker, num); ++ //this.first.incrementCounter(marker, num); // Purpur ++ //this.second.incrementCounter(marker, num); // Purpur + } + + @Override + public void incrementCounter(Supplier markerGetter, int num) { +- this.first.incrementCounter(markerGetter, num); +- this.second.incrementCounter(markerGetter, num); ++ //this.first.incrementCounter(markerGetter, num); // Purpur ++ //this.second.incrementCounter(markerGetter, num); // Purpur + } + + @Override + public void addZoneText(String label) { +- this.first.addZoneText(label); +- this.second.addZoneText(label); ++ //this.first.addZoneText(label); // Purpur ++ //this.second.addZoneText(label); // Purpur + } + + @Override + public void addZoneValue(long value) { +- this.first.addZoneValue(value); +- this.second.addZoneValue(value); ++ //this.first.addZoneValue(value); // Purpur ++ //this.second.addZoneValue(value); // Purpur + } + + @Override + public void setZoneColor(int color) { +- this.first.setZoneColor(color); +- this.second.setZoneColor(color); ++ //this.first.setZoneColor(color); // Purpur ++ //this.second.setZoneColor(color); // Purpur + } + } + } diff --git a/src/main/java/net/minecraft/world/damagesource/CombatRules.java b/src/main/java/net/minecraft/world/damagesource/CombatRules.java index 064c1e33f3feee77837bb57887877ae1ca39548d..ffd009bca3fdbfd0b14df78072ef8d472a57cd65 100644 --- a/src/main/java/net/minecraft/world/damagesource/CombatRules.java @@ -3889,10 +3579,10 @@ index bb1a60180e58c1333e7bb33e8acf1b0225eda8a8..4a96d914f8aa6f0c5f13fc85369a311f 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; @@ -3900,7 +3590,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 @@ -3908,7 +3598,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 @@ -3925,12 +3615,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 @@ -3938,27 +3628,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 @@ -3966,39 +3656,40 @@ 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 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225facca47d84 100644 +index 6817015f0cf39df03029e36cd845d590618031dc..6b32cd1391f39b6fe61c3c8c00249d1d4278cbd0 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; +@@ -176,7 +176,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 @@ -4010,8 +3701,8 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa public double zOld; + public float maxUpStep; // Purpur public boolean noPhysics; + private boolean wasOnFire; public final RandomSource random; - public int tickCount; @@ -383,7 +384,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess private final Set tags; private final double[] pistonDeltas; @@ -4021,15 +3712,15 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa private float eyeHeight; public boolean isInPowderSnow; public boolean wasInPowderSnow; -@@ -432,6 +433,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - public boolean activatedPriorityReset = false; // Pufferfish - DAB - public int activatedPriority = gg.pufferfish.pufferfish.PufferfishConfig.maximumActivationPrio; // Pufferfish - DAB (golf score) - public final BlockPos.MutableBlockPos cachedBlockPos = new BlockPos.MutableBlockPos(); // Pufferfish - reduce entity allocations +@@ -431,6 +432,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + private UUID originWorld; + public boolean freezeLocked = false; // Paper - Freeze Tick Lock API + public boolean fixedPose = false; // Paper - Expand Pose API + public @Nullable Boolean immuneToFire = null; // Purpur - Fire immune API public void setOrigin(@javax.annotation.Nonnull Location location) { this.origin = location.toVector(); -@@ -552,6 +554,27 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -610,6 +612,27 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } // Paper end - optimise entity tracker @@ -4057,7 +3748,7 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa public Entity(EntityType type, Level world) { this.id = Entity.ENTITY_COUNTER.incrementAndGet(); -@@ -560,7 +583,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -618,7 +641,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.bb = Entity.INITIAL_AABB; this.stuckSpeedMultiplier = Vec3.ZERO; this.nextStep = 1.0F; @@ -4066,34 +3757,28 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa this.remainingFireTicks = -this.getFireImmuneTicks(); this.fluidHeight = new Object2DoubleArrayMap(2); this.fluidOnEyes = new HashSet(); -@@ -850,7 +873,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 -@@ -867,7 +890,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -924,9 +947,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // CraftBukkit end public void baseTick() { -- this.level().getProfiler().push("entityBaseTick"); -+ //this.level().getProfiler().push("entityBaseTick"); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("entityBaseTick"); ++ //gameprofilerfiller.push("entityBaseTick"); // Purpur if (firstTick && this instanceof net.minecraft.world.entity.NeutralMob neutralMob) neutralMob.tickInitialPersistentAnger(level); // Paper - Prevent entity loading causing async lookups this.inBlockState = null; if (this.isPassenger() && this.getVehicle().isRemoved()) { -@@ -932,7 +955,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - Leashable.tickLeash((Entity & Leashable) this); // CraftBukkit - decompile error +@@ -995,7 +1018,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + } } -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur } public void setSharedFlagOnFire(boolean onFire) { -@@ -947,6 +970,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1009,6 +1032,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 @@ -4101,54 +3786,57 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa this.onBelowWorld(); } -@@ -1147,7 +1171,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1221,9 +1245,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } -- this.level().getProfiler().push("move"); -+ //this.level().getProfiler().push("move"); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("move"); ++ //gameprofilerfiller.push("move"); // Purpur if (this.stuckSpeedMultiplier.lengthSqr() > 1.0E-7D) { movement = movement.multiply(this.stuckSpeedMultiplier); this.stuckSpeedMultiplier = Vec3.ZERO; -@@ -1156,7 +1180,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1232,7 +1256,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // Paper start - ignore movement changes while inactive. - if (isTemporarilyActive && !(this instanceof ItemEntity) && movement == getDeltaMovement() && movementType == MoverType.SELF) { + if (isTemporarilyActive && !(this instanceof ItemEntity) && movement == getDeltaMovement() && type == MoverType.SELF) { setDeltaMovement(Vec3.ZERO); -- this.level.getProfiler().pop(); -+ //this.level.getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur return; } // Paper end -@@ -1177,8 +1201,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1253,8 +1277,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.setPos(this.getX() + vec3d1.x, this.getY() + vec3d1.y, this.getZ() + vec3d1.z); } -- this.level().getProfiler().pop(); -- this.level().getProfiler().push("rest"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("rest"); // Purpur +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("rest"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("rest"); // Purpur boolean flag = !Mth.equal(movement.x, vec3d1.x); boolean flag1 = !Mth.equal(movement.z, vec3d1.z); -@@ -1197,7 +1221,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1276,7 +1300,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + } - this.checkFallDamage(vec3d1.y, this.onGround(), iblockdata, blockposition); if (this.isRemoved()) { -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur } else { if (this.horizontalCollision) { Vec3 vec3d2 = this.getDeltaMovement(); -@@ -1300,7 +1324,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - this.setRemainingFireTicks(-this.getFireImmuneTicks()); - } +@@ -1325,7 +1349,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + float f = this.getBlockSpeedFactor(); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur + this.setDeltaMovement(this.getDeltaMovement().multiply((double) f, 1.0D, (double) f)); +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur } } // Paper start - detailed watchdog information -@@ -1858,7 +1882,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1970,7 +1994,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public boolean fireImmune() { @@ -4157,7 +3845,7 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa } public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) { -@@ -1931,7 +1955,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2043,7 +2067,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return this.isInWater() || flag; } @@ -4165,8 +3853,8 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa + public void updateInWaterStateAndDoWaterCurrentPushing() { // Purpur - package-private -> public Entity entity = this.getVehicle(); - if (entity instanceof Boat entityboat) { -@@ -2567,6 +2591,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + if (entity instanceof AbstractBoat abstractboat) { +@@ -2725,6 +2749,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess nbttagcompound.putBoolean("Paper.FreezeLock", true); } // Paper end @@ -4178,7 +3866,7 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa return nbttagcompound; } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); -@@ -2714,6 +2743,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2873,6 +2902,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess freezeLocked = nbt.getBoolean("Paper.FreezeLock"); } // Paper end @@ -4190,7 +3878,7 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); -@@ -2932,6 +2966,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3124,6 +3158,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess if (this.isAlive() && this instanceof Leashable leashable) { if (leashable.getLeashHolder() == player) { if (!this.level().isClientSide()) { @@ -4198,7 +3886,7 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa // CraftBukkit start - fire PlayerUnleashEntityEvent // Paper start - Expand EntityUnleashEvent org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand, !player.hasInfiniteMaterials()); -@@ -3135,6 +3170,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3329,6 +3364,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.passengers = ImmutableList.copyOf(list); } @@ -4212,7 +3900,7 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa this.gameEvent(GameEvent.ENTITY_MOUNT, passenger); } } -@@ -3174,6 +3216,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3368,6 +3410,14 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return false; } // CraftBukkit end @@ -4227,7 +3915,7 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa if (this.passengers.size() == 1 && this.passengers.get(0) == entity) { this.passengers = ImmutableList.of(); } else { -@@ -3252,13 +3302,16 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3448,14 +3498,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return Vec3.directionFromRotation(this.getRotationVector()); } @@ -4239,31 +3927,35 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa - } 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()); - } -@@ -3273,7 +3326,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3471,9 +3524,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.processPortalCooldown(); if (this.portalProcess != null) { if (this.portalProcess.processPortalTeleportation(worldserver, this, this.canUsePortal(false))) { -- worldserver.getProfiler().push("portal"); -+ //worldserver.getProfiler().push("portal"); // Purpur - this.setPortalCooldown(); - DimensionTransition dimensiontransition = this.portalProcess.getPortalDestination(worldserver, this); +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur -@@ -3285,7 +3338,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +- gameprofilerfiller.push("portal"); ++ //gameprofilerfiller.push("portal"); // Purpur + this.setPortalCooldown(); + TeleportTransition teleporttransition = this.portalProcess.getPortalDestination(worldserver, this); + +@@ -3485,7 +3538,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } -- worldserver.getProfiler().pop(); -+ //worldserver.getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur } else if (this.portalProcess.hasExpired()) { this.portalProcess = null; } -@@ -3468,7 +3521,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3672,7 +3725,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public int getMaxAirSupply() { @@ -4272,25 +3964,32 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa } public int getAirSupply() { -@@ -3788,7 +3841,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - } - } - -- worldserver.getProfiler().push("changeDimension"); -+ //worldserver.getProfiler().push("changeDimension"); // Purpur - Entity entity2 = worldserver1.dimension() == worldserver.dimension() ? this : this.getType().create(worldserver1); - - if (entity2 != null) { -@@ -3824,7 +3877,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - teleportTarget.postDimensionTransition().onTransition(entity2); - } - -- worldserver.getProfiler().pop(); -+ //worldserver.getProfiler().pop(); // Purpur - return entity2; +@@ -4036,12 +4089,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } -@@ -3880,7 +3933,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("teleportCrossDimension"); ++ //gameprofilerfiller.push("teleportCrossDimension"); // Purpur + entity = this.getType().create(world, EntitySpawnReason.DIMENSION_TRAVEL); + if (entity == null) { +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur + return null; + } else { + // Paper start - Fix item duplication and teleport issues +@@ -4067,7 +4120,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + + world.resetEmptyTime(); + teleportTarget.postTeleportTransition().onTransition(entity); +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur + return entity; + } + } +@@ -4168,7 +4221,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // CraftBukkit end public boolean canUsePortal(boolean allowVehicles) { @@ -4298,29 +3997,8 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa + 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) { -@@ -4189,6 +4242,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) {} - -@@ -4460,6 +4527,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + public boolean canTeleport(Level from, Level to) { +@@ -4727,6 +4780,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return Mth.lerp(delta, this.yRotO, this.yRot); } @@ -4330,10 +4008,10 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa + } + // Purpur end + - public boolean updateFluidHeightAndDoFluidPushing(TagKey tag, double speed) { - if (false && this.touchingUnloadedChunk()) { // Pufferfish - cost of a lookup here is the same cost as below, so skip - return false; -@@ -4861,7 +4934,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()) { +@@ -5128,7 +5187,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public float maxUpStep() { @@ -4342,7 +4020,7 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa } public void onExplosionHit(@Nullable Entity entity) {} -@@ -5053,4 +5126,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -5329,4 +5388,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return ((net.minecraft.server.level.ServerChunkCache) level.getChunkSource()).isPositionTicking(this); } // Paper end - Expose entity id counter @@ -4388,10 +4066,10 @@ index 8492421ed2186c0eab517a67f3140b9988f65250..7aadcaa1785c6560eb1ce2f1179225fa + // 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 @@ -4400,21 +4078,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 c8c2394558952d7ca57d29874485251b8f2b3400..c1a870fd22b193388513aad0ac4f3ce0ad7c8195 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; +@@ -388,7 +388,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 +@@ -404,6 +405,16 @@ public class EntityType implements FeatureElement, EntityTypeT + return EntityType.register(EntityType.vanillaEntityId(id), type); } + // Purpur start @@ -4423,14 +4101,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 +@@ -604,6 +615,16 @@ public class EntityType implements FeatureElement, EntityTypeT return this.category; } @@ -4445,9 +4123,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; + } +@@ -661,6 +682,12 @@ public class EntityType implements FeatureElement, EntityTypeT entity.load(nbt); }, () -> { EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id")); @@ -4461,10 +4139,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 @@ -4473,7 +4151,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) { @@ -4483,10 +4161,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); } @@ -4527,10 +4205,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 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b272c5b02d 100644 +index 0831d69d6ac1aa112dfe8243b01adcf5e8eba6a0..18648eed57dca05d89692064dcf4aa3172cd5914 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -236,9 +236,9 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -248,9 +248,9 @@ public abstract class LivingEntity extends Entity implements Attackable { protected int deathScore; public float lastHurt; public boolean jumping; @@ -4543,7 +4221,7 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 protected int lerpSteps; protected double lerpX; protected double lerpY; -@@ -285,6 +285,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -297,6 +297,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 @@ -4551,9 +4229,9 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 @Override public float getBukkitYaw() { -@@ -312,7 +313,8 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -325,7 +326,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 @@ -4561,7 +4239,7 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 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()); -@@ -327,6 +329,8 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -340,6 +342,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())))); } @@ -4570,7 +4248,7 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 public Brain getBrain() { return this.brain; } -@@ -362,6 +366,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -375,6 +379,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); } @@ -4578,24 +4256,27 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 @Override protected void checkFallDamage(double heightDifference, boolean onGround, BlockState state, BlockPos landedPosition) { -@@ -439,7 +444,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -452,9 +457,9 @@ public abstract class LivingEntity extends Entity implements Attackable { } super.baseTick(); -- this.level().getProfiler().push("livingEntityBaseTick"); -+ //this.level().getProfiler().push("livingEntityBaseTick"); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("livingEntityBaseTick"); ++ //gameprofilerfiller.push("livingEntityBaseTick"); // Purpur if (this.fireImmune() || this.level().isClientSide) { this.clearFire(); } -@@ -457,6 +462,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - double d1 = this.level().getWorldBorder().getDamagePerBlock(); - - if (d1 > 0.0D) { +@@ -475,6 +480,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))); } } -@@ -468,7 +474,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -486,7 +492,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (flag1) { this.setAirSupply(this.decreaseAirSupply(this.getAirSupply())); @@ -4604,8 +4285,8 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 this.setAirSupply(0); Vec3 vec3d = this.getDeltaMovement(); -@@ -480,7 +486,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); +@@ -498,7 +504,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); @@ -4613,16 +4294,16 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 } } -@@ -544,7 +550,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -561,7 +567,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.yHeadRotO = this.yHeadRot; this.yRotO = this.getYRot(); this.xRotO = this.getXRot(); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur } @Override -@@ -811,6 +817,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -834,6 +840,7 @@ public abstract class LivingEntity extends Entity implements Attackable { dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { nbt.put("Brain", nbtbase); }); @@ -4630,7 +4311,7 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 } @Override -@@ -899,6 +906,11 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -922,6 +929,11 @@ public abstract class LivingEntity extends Entity implements Attackable { this.brain = this.makeBrain(new Dynamic(NbtOps.INSTANCE, nbt.get("Brain"))); } @@ -4642,7 +4323,7 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 } // CraftBukkit start -@@ -1034,9 +1046,31 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1057,9 +1069,31 @@ public abstract class LivingEntity extends Entity implements Attackable { ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); EntityType entitytypes = entity.getType(); @@ -4676,15 +4357,15 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 } return d0; -@@ -1095,6 +1129,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - for (flag = false; iterator.hasNext(); flag = true) { - // CraftBukkit start - MobEffectInstance effect = (MobEffectInstance) iterator.next(); +@@ -1115,6 +1149,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; -@@ -1436,6 +1471,24 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1450,6 +1485,24 @@ public abstract class LivingEntity extends Entity implements Attackable { this.stopSleeping(); } @@ -4707,9 +4388,9 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 + // 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 -@@ -1527,13 +1580,13 @@ public abstract class LivingEntity extends Entity implements Attackable { + if (amount < 0.0F) { + amount = 0.0F; +@@ -1549,13 +1602,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; @@ -4725,7 +4406,7 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 LivingEntity entityliving2 = entitywolf.getOwner(); if (entityliving2 instanceof net.minecraft.world.entity.player.Player) { -@@ -1674,6 +1727,18 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1702,6 +1755,18 @@ public abstract class LivingEntity extends Entity implements Attackable { } } @@ -4744,26 +4425,24 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 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); -@@ -1840,7 +1905,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1867,7 +1932,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(); -@@ -1876,7 +1941,8 @@ public abstract class LivingEntity extends Entity implements Attackable { - boolean flag = this.lastHurtByPlayerTime > 0; +@@ -1904,6 +1969,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; -@@ -1885,6 +1951,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1912,6 +1978,7 @@ public abstract class LivingEntity extends Entity implements Attackable { // Paper end this.dropCustomDeathLoot(world, damageSource, flag); this.clearEquipmentSlots = prev; // Paper @@ -4771,100 +4450,106 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 } // 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, () -> { -@@ -3009,6 +3076,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3123,6 +3190,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); - } - } -@@ -3231,10 +3299,10 @@ 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); + } + } +@@ -3315,12 +3383,12 @@ public abstract class LivingEntity extends Entity implements Attackable { } this.run += (f3 - this.run) * 0.3F; -- this.level().getProfiler().push("headTurn"); -+ //this.level().getProfiler().push("headTurn"); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("headTurn"); ++ //gameprofilerfiller.push("headTurn"); // Purpur f2 = this.tickHeadTurn(f1, f2); -- this.level().getProfiler().pop(); -- this.level().getProfiler().push("rangeChecks"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("rangeChecks"); // Purpur +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("rangeChecks"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("rangeChecks"); // Purpur // Paper start - stop large pitch and yaw changes from crashing the server this.yRotO += Math.round((this.getYRot() - this.yRotO) / 360.0F) * 360.0F; -@@ -3246,7 +3314,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3332,7 +3400,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.yHeadRotO += Math.round((this.yHeadRot - this.yHeadRotO) / 360.0F) * 360.0F; // Paper end -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur this.animStep += f2; if (this.isFallFlying()) { ++this.fallFlyTicks; -@@ -3486,19 +3554,19 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3562,21 +3630,21 @@ public abstract class LivingEntity extends Entity implements Attackable { } this.setDeltaMovement(d0, d1, d2); -- this.level().getProfiler().push("ai"); -+ //this.level().getProfiler().push("ai"); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("ai"); ++ //gameprofilerfiller.push("ai"); // Purpur if (this.isImmobile()) { this.jumping = false; this.xxa = 0.0F; this.zza = 0.0F; } else if (this.isEffectiveAi()) { -- this.level().getProfiler().push("newAi"); -+ //this.level().getProfiler().push("newAi"); // Purpur +- gameprofilerfiller.push("newAi"); ++ //gameprofilerfiller.push("newAi"); // Purpur this.serverAiStep(); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur } -- this.level().getProfiler().pop(); -- this.level().getProfiler().push("jump"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("jump"); // Purpur +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("jump"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("jump"); // Purpur if (this.jumping && this.isAffectedByFluids()) { double d3; -@@ -3525,8 +3593,8 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3603,8 +3671,8 @@ public abstract class LivingEntity extends Entity implements Attackable { this.noJumpDelay = 0; } -- this.level().getProfiler().pop(); -- this.level().getProfiler().push("travel"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("travel"); // Purpur +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("travel"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("travel"); // Purpur this.xxa *= 0.98F; this.zza *= 0.98F; - this.updateFallFlying(); -@@ -3551,8 +3619,8 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.travel(vec3d1); + if (this.isFallFlying()) { +@@ -3637,8 +3705,8 @@ public abstract class LivingEntity extends Entity implements Attackable { } -- this.level().getProfiler().pop(); -- this.level().getProfiler().push("freezing"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("freezing"); // Purpur + this.calculateEntityAnimation(this instanceof FlyingAnimal); +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("freezing"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("freezing"); // Purpur if (!this.level().isClientSide && !this.isDeadOrDying() && !this.freezeLocked) { // Paper - Freeze Tick Lock API int i = this.getTicksFrozen(); -@@ -3569,18 +3637,20 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.hurt(this.damageSources().freeze(), 1.0F); +@@ -3659,18 +3727,20 @@ public abstract class LivingEntity extends Entity implements Attackable { + } } -- this.level().getProfiler().pop(); -- this.level().getProfiler().push("push"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("push"); // Purpur +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("push"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("push"); // Purpur if (this.autoSpinAttackTicks > 0) { --this.autoSpinAttackTicks; this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); } this.pushEntities(); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur // 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()) { @@ -4875,7 +4560,7 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 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()); -@@ -3590,12 +3660,55 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3680,6 +3750,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()); } } @@ -4896,8 +4581,9 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 + // Purpur end } // Paper end - Add EntityMoveEvent - if (!this.level().isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { - this.hurt(this.damageSources().drown(), 1.0F); + world = this.level(); +@@ -3689,6 +3774,34 @@ public abstract class LivingEntity extends Entity implements Attackable { + } } + // Purpur start - copied from Zombie - API for any mob to burn daylight @@ -4931,26 +4617,45 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 } public boolean isSensitiveToWater() { -@@ -3616,7 +3729,16 @@ public abstract class LivingEntity extends Entity implements Attackable { - int j = i / 10; +@@ -3715,7 +3828,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); -@@ -4576,6 +4698,12 @@ public abstract class LivingEntity extends Entity implements Attackable { - return EquipmentSlot.MAINHAND; + this.gameEvent(GameEvent.ELYTRA_GLIDE); +@@ -3724,7 +3847,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + + } + +- protected boolean canGlide() { ++ public boolean canGlide() { // Purpur + if (!this.onGround() && !this.isPassenger() && !this.hasEffect(MobEffects.LEVITATION)) { + Iterator iterator = EquipmentSlot.VALUES.iterator(); + +@@ -4646,7 +4769,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; + } +@@ -4671,6 +4794,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 @@ -4963,10 +4668,10 @@ index 5132e108df37ca97ba94b8b72c0ef292cbb2ec94..f714e2dc212a3b70977e93c55e94f8b2 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 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719aaf730318 100644 +index dbd321f3dc3cc80737830db63aed47a6935e8e89..ff9d23aef4658922692b43a859bd83632fe23612 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -146,6 +146,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -148,6 +148,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab private BlockPos restrictCenter; private float restrictRadius; @@ -4974,10 +4679,10 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a public boolean aware = true; // CraftBukkit protected Mob(EntityType type, Level world) { -@@ -160,8 +161,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -163,8 +164,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab this.restrictRadius = -1.0F; - this.goalSelector = new GoalSelector(world.getProfilerSupplier()); - this.targetSelector = new GoalSelector(world.getProfilerSupplier()); + this.goalSelector = new GoalSelector(); + this.targetSelector = new GoalSelector(); - this.lookControl = new LookControl(this); - this.moveControl = new MoveControl(this); + this.lookControl = new org.purpurmc.purpur.controller.LookControllerWASD(this); // Purpur @@ -4985,7 +4690,7 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a this.jumpControl = new JumpControl(this); this.bodyRotationControl = this.createBodyControl(); this.navigation = this.createNavigation(world); -@@ -333,6 +334,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -334,6 +335,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab entityliving = null; } } @@ -4993,19 +4698,22 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a this.target = entityliving; return true; // CraftBukkit end -@@ -368,15 +370,35 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -369,17 +371,37 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab @Override public void baseTick() { super.baseTick(); -- this.level().getProfiler().push("mobBaseTick"); -+ //this.level().getProfiler().push("mobBaseTick"); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("mobBaseTick"); ++ //gameprofilerfiller.push("mobBaseTick"); // Purpur if (this.isAlive() && this.random.nextInt(1000) < this.ambientSoundTime++) { this.resetAmbientSoundTime(); this.playAmbientSound(); } -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur + incrementTicksSinceLastInteraction(); // Purpur } @@ -5031,7 +4739,7 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a @Override protected void playHurtSound(DamageSource damageSource) { this.resetAmbientSoundTime(); -@@ -551,6 +573,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -547,6 +569,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab } nbt.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit @@ -5039,7 +4747,7 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a } @Override -@@ -628,6 +651,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -624,6 +647,11 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab this.aware = nbt.getBoolean("Bukkit.Aware"); } // CraftBukkit end @@ -5051,32 +4759,38 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a } @Override -@@ -678,8 +706,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -670,13 +698,13 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab @Override public void aiStep() { super.aiStep(); -- this.level().getProfiler().push("looting"); -- if (!this.level().isClientSide && this.canPickUpLoot() && this.isAlive() && !this.dead && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { -+ //this.level().getProfiler().push("looting"); // Purpur -+ 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(); -@@ -698,7 +726,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("looting"); ++ //gameprofilerfiller.push("looting"); // Purpur + 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(); +@@ -696,7 +724,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab } } -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur } protected Vec3i getPickupReach() { -@@ -922,48 +950,48 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -918,44 +946,44 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab return; } // Paper end - Allow nerfed mobs to jump and float -- ProfilerFiller gameprofilerfiller = this.level().getProfiler(); -+ //ProfilerFiller gameprofilerfiller = this.level().getProfiler(); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur - gameprofilerfiller.push("sensing"); + //gameprofilerfiller.push("sensing"); // Purpur @@ -5088,26 +4802,22 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a if (i % 2 != 0 && this.tickCount > 1) { - gameprofilerfiller.push("targetSelector"); + //gameprofilerfiller.push("targetSelector"); // Purpur - if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking this.targetSelector.tickRunningGoals(false); - gameprofilerfiller.pop(); - gameprofilerfiller.push("goalSelector"); + //gameprofilerfiller.pop(); // Purpur + //gameprofilerfiller.push("goalSelector"); // Purpur - if (this.goalSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking this.goalSelector.tickRunningGoals(false); - gameprofilerfiller.pop(); + //gameprofilerfiller.pop(); // Purpur } else { - gameprofilerfiller.push("targetSelector"); + //gameprofilerfiller.push("targetSelector"); // Purpur - if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking this.targetSelector.tick(); - gameprofilerfiller.pop(); - gameprofilerfiller.push("goalSelector"); + //gameprofilerfiller.pop(); // Purpur + //gameprofilerfiller.push("goalSelector"); // Purpur - if (this.goalSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking this.goalSelector.tick(); - gameprofilerfiller.pop(); + //gameprofilerfiller.pop(); // Purpur @@ -5120,7 +4830,7 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a - gameprofilerfiller.push("mob tick"); + //gameprofilerfiller.pop(); // Purpur + //gameprofilerfiller.push("mob tick"); // Purpur - this.customServerAiStep(); + this.customServerAiStep((ServerLevel) this.level()); - gameprofilerfiller.pop(); - gameprofilerfiller.push("controls"); - gameprofilerfiller.push("move"); @@ -5141,7 +4851,7 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a this.sendDebugPackets(); } -@@ -1413,7 +1441,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1394,7 +1422,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)); } @@ -5150,7 +4860,7 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a return entityData; } -@@ -1514,7 +1542,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1496,7 +1524,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab protected void onOffspringSpawnedFromEgg(Player player, Mob child) {} protected InteractionResult mobInteract(Player player, InteractionHand hand) { @@ -5159,7 +4869,7 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a } public boolean isWithinRestriction() { -@@ -1753,23 +1781,15 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1735,23 +1763,15 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab this.playAttackSound(); } @@ -5186,9 +4896,9 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a } @Override -@@ -1812,4 +1832,56 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab - - return itemmonsteregg == null ? null : new ItemStack(itemmonsteregg); +@@ -1813,4 +1833,58 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + public float[] getArmorDropChances() { + return this.armorDropChances; } + + // Purpur start @@ -5230,7 +4940,9 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a + } + } + 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()); @@ -5243,27 +4955,14 @@ index 1f3a55d34f58964fb1f642ad59c9d7b7aa6fa4ff..4b4bdaf8c43e15ba953c160a003a719a + } + // 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 2c9aab24b51d2f0a50100089fe72093b501d383a..00346f83e71193d1378937d51c5e846edcf7e7ba 100644 +index 94d04a20f97405e02d7cccaabadc7a7e86e336f7..06b890275d1a171d609b91a1d1a018c43b943ab2 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 -@@ -24,15 +24,22 @@ public class AttributeMap { +@@ -23,14 +23,21 @@ public class AttributeMap { + private final Set attributesToSync = new ObjectOpenHashSet<>(); private final Set attributesToUpdate = new ObjectOpenHashSet<>(); private final AttributeSupplier supplier; - private final java.util.function.Function, AttributeInstance> createInstance; // Pufferfish + private final net.minecraft.world.entity.LivingEntity entity; // Purpur public AttributeMap(AttributeSupplier defaultAttributes) { @@ -5274,7 +4973,6 @@ index 2c9aab24b51d2f0a50100089fe72093b501d383a..00346f83e71193d1378937d51c5e846e + this.entity = entity; + // Purpur end this.supplier = defaultAttributes; - this.createInstance = attributex -> this.supplier.createInstance(this::onAttributeModified, attributex); // Pufferfish } private void onAttributeModified(AttributeInstance instance) { @@ -5284,7 +4982,7 @@ index 2c9aab24b51d2f0a50100089fe72093b501d383a..00346f83e71193d1378937d51c5e846e this.attributesToSync.add(instance); } } -@@ -46,7 +53,7 @@ public class AttributeMap { +@@ -44,7 +51,7 @@ public class AttributeMap { } public Collection getSyncableAttributes() { @@ -5292,12 +4990,12 @@ index 2c9aab24b51d2f0a50100089fe72093b501d383a..00346f83e71193d1378937d51c5e846e + return this.attributes.values().stream().filter(attribute -> attribute.getAttribute().value().isClientSyncable() && (entity == null || entity.shouldSendAttribute(attribute.getAttribute().value()))).collect(Collectors.toList()); // Purpur } - + @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..157fe8979c780300b6f72cbaa17729031e3b386d 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()) @@ -5319,7 +5017,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 e1b6fe9ecda25f86431baf414f1bfd3a26a8b2bd..ecd1bbd17cb0134cf1f4e99a3fea9e205d38f46b 100644 +index e1b6fe9ecda25f86431baf414f1bfd3a26a8b2bd..3d7578605812021bc84b99d4db1672a682d897ad 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 @@ -73,7 +73,7 @@ public class AcquirePoi { @@ -5327,42 +5025,10 @@ index e1b6fe9ecda25f86431baf414f1bfd3a26a8b2bd..ecd1bbd17cb0134cf1f4e99a3fea9e20 // 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/Behavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java -index 9379dd4056018b52c93ed4888dcdc94579bd9691..612a14806ec63b0dcf31814396282f4b7f4a527c 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java -@@ -59,9 +59,9 @@ public abstract class Behavior implements BehaviorContro - this.status = Behavior.Status.RUNNING; - int i = this.minDuration + world.getRandom().nextInt(this.maxDuration + 1 - this.minDuration); - this.endTimestamp = time + (long)i; -- this.timing.startTiming(); // Paper - behavior timings -+ //this.timing.startTiming(); // Paper - behavior timings // Purpur - this.start(world, entity, time); -- this.timing.stopTiming(); // Paper - behavior timings -+ //this.timing.stopTiming(); // Paper - behavior timings // Purpur - return true; - } else { - return false; -@@ -73,13 +73,13 @@ public abstract class Behavior implements BehaviorContro - - @Override - public final void tickOrStop(ServerLevel world, E entity, long time) { -- this.timing.startTiming(); // Paper - behavior timings -+ //this.timing.startTiming(); // Paper - behavior timings // Purpur - if (!this.timedOut(time) && this.canStillUse(world, entity, time)) { - this.tick(world, entity, time); - } else { - this.doStop(world, entity, time); - } -- this.timing.stopTiming(); // Paper - behavior timings -+ //this.timing.stopTiming(); // Paper - behavior timings // Purpur - } - - protected void tick(ServerLevel world, E entity, long time) { 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 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/HarvestFarmland.java @@ -5491,7 +5157,7 @@ index 8508ac7de8cda3127b73e11ff4aee62502e65ead..b1544e028d5a9b84b944e1fb5a12bb16 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 { @@ -5574,28 +5240,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..4b7cfca51ced0f781561ecd68484de4adb23e082 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..f3697510974be0c3cfdb0e2179d89c8109152829 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); } @@ -5603,27 +5269,27 @@ 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); } 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 e32c3120f9c5ddf429d8428c370ff61320a38de6..c943a00b401c4e9f2d97113ffe1f7c344455d086 100644 +index 29ae74339a4831ccef3d01e8054931715ba192ad..74c5914bc51cff128d4b86853316e5e51e02b416 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 -@@ -90,8 +90,8 @@ public class GoalSelector { +@@ -82,8 +82,8 @@ public class GoalSelector { } public void tick() { -- ProfilerFiller profilerFiller = this.profiler.get(); +- ProfilerFiller profilerFiller = Profiler.get(); - profilerFiller.push("goalCleanup"); -+ //ProfilerFiller profilerFiller = this.profiler.get(); // Purpur ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur + //profilerFiller.push("goalCleanup"); // Purpur for (WrappedGoal wrappedGoal : this.availableGoals) { if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.goalTypes) || !wrappedGoal.canContinueToUse())) { // Paper - Perf: optimize goal types by removing streams -@@ -100,8 +100,8 @@ public class GoalSelector { +@@ -92,8 +92,8 @@ public class GoalSelector { } this.lockedFlags.entrySet().removeIf(entry -> !entry.getValue().isRunning()); @@ -5634,7 +5300,7 @@ index e32c3120f9c5ddf429d8428c370ff61320a38de6..c943a00b401c4e9f2d97113ffe1f7c34 for (WrappedGoal wrappedGoal2 : this.availableGoals) { // Paper start -@@ -121,13 +121,13 @@ public class GoalSelector { +@@ -113,13 +113,13 @@ public class GoalSelector { } } @@ -5644,14 +5310,14 @@ index e32c3120f9c5ddf429d8428c370ff61320a38de6..c943a00b401c4e9f2d97113ffe1f7c34 } public void tickRunningGoals(boolean tickAll) { -- ProfilerFiller profilerFiller = this.profiler.get(); +- ProfilerFiller profilerFiller = Profiler.get(); - profilerFiller.push("goalTick"); -+ //ProfilerFiller profilerFiller = this.profiler.get(); // Purpur ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur + //profilerFiller.push("goalTick"); // Purpur for (WrappedGoal wrappedGoal : this.availableGoals) { if (wrappedGoal.isRunning() && (tickAll || wrappedGoal.requiresUpdateEveryTick())) { -@@ -135,7 +135,7 @@ public class GoalSelector { +@@ -127,7 +127,7 @@ public class GoalSelector { } } @@ -5697,15 +5363,15 @@ index 515c1f671cb2c3a7cc23053aedf404bbbe77af3e..42a1e5b9c08a9245dd0ce6d4025e3bb5 if (this.mob.isUsingItem()) { if (!bl && this.seeTime < -60) { 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..d002acdac893e2744cde5f1145d29ac2c8ff6959 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((Entity) this.removerMob).purpurConfig.zombieBypassMobGriefing && !getServerLevel((Entity) this.removerMob).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { // Purpur return false; } else if (this.nextStartTick > 0) { --this.nextStartTick; @@ -5742,10 +5408,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) { @@ -5755,21 +5421,23 @@ index 13f8c2cb42334ba3b573ca44ace1d3df76e41ff7..baca552e52c728867fcb0527b6c3eb39 @Override diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index 2e9991e6b3c05584002744a2ee2579b1dba218b2..544920a31b649985333f82beafa94a3392f5853e 100644 +index 48c0de870a5bbf647309e69361dfb10ab56c65ab..a5289b6c453c24cb7b8b3a301b72c3adf92c1d13 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -172,12 +172,12 @@ public abstract class PathNavigation { +@@ -188,13 +188,13 @@ public abstract class PathNavigation { } } // Paper end - EntityPathfindEvent -- this.level.getProfiler().push("pathfind"); -+ //this.level.getProfiler().push("pathfind"); // Purpur +- ProfilerFiller profilerFiller = Profiler.get(); +- profilerFiller.push("pathfind"); ++ //ProfilerFiller profilerFiller = Profiler.get(); ++ //profilerFiller.push("pathfind"); // Purpur BlockPos blockPos = useHeadPos ? this.mob.blockPosition().above() : this.mob.blockPosition(); int i = (int)(followRange + (float)range); PathNavigationRegion pathNavigationRegion = new PathNavigationRegion(this.level, blockPos.offset(-i, -i, -i), blockPos.offset(i, i, i)); Path path = this.pathFinder.findPath(pathNavigationRegion, this.mob, positions, followRange, distance, this.maxVisitedNodesMultiplier); -- this.level.getProfiler().pop(); -+ //this.level.getProfiler().pop(); // Purpur +- profilerFiller.pop(); ++ //profilerFiller.pop(); // Purpur if (path != null && path.getTarget() != null) { this.targetPos = path.getTarget(); this.reachRange = distance; @@ -5814,58 +5482,43 @@ index a0e0692d17760f440fe81d52887284c787e562db..ab9bebc07b5228dbc0d3ba4b0f7d1bbe brain.setMemory(MemoryModuleType.SECONDARY_JOB_SITE, list); } else { diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensing.java b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensing.java -index 51772f03a3469b11e7166ec6f3a1b9c64a606221..02f2f46ccc48bb4d9bd08555818b0489f60d9f13 100644 +index 116b1e251ffe68bae5c404d0823c2bc7c1afddf6..8f5a5db1a07fa6a95ecfacaab2f9de609202faf4 100644 --- a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensing.java +++ b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensing.java -@@ -26,9 +26,9 @@ public class Sensing { +@@ -28,10 +28,10 @@ public class Sensing { } else if (this.unseen.contains(i)) { return false; } else { -- this.mob.level().getProfiler().push("hasLineOfSight"); -+ //this.mob.level().getProfiler().push("hasLineOfSight"); // Purpur +- ProfilerFiller profilerFiller = Profiler.get(); +- profilerFiller.push("hasLineOfSight"); ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur ++ //profilerFiller.push("hasLineOfSight"); // Purpur boolean bl = this.mob.hasLineOfSight(entity); -- this.mob.level().getProfiler().pop(); -+ //this.mob.level().getProfiler().pop(); // Purpur +- profilerFiller.pop(); ++ //profilerFiller.pop(); // Purpur if (bl) { this.seen.add(i); } else { -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java -index 85b4b24361e785acf75571ff98f924c00ae80748..09a7b418ddf564c0be13297f7c216db2e7ae1578 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java -@@ -53,10 +53,10 @@ public abstract class Sensor { - if (--this.timeToTick <= 0L) { - // Paper start - configurable sensor tick rate and timings - this.timeToTick = java.util.Objects.requireNonNullElse(world.paperConfig().tickRates.sensor.get(entity.getType(), this.configKey), this.scanRate); -- this.timing.startTiming(); -+ //this.timing.startTiming(); // Purpur - // Paper end - this.doTick(world, entity); -- this.timing.stopTiming(); // Paper - sensor timings -+ //this.timing.stopTiming(); // Paper - sensor timings // Purpur - } - } - 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 00ef7f6d60bcaee2506cf111461f2c2f8eedd59a..02a328bb22ebb3593f9f41a1ffc1008ae8414121 100644 +index 52982c1e6a4da36392569c791853279f5f9ac31a..b3d4c61b1769b6fcc98b7af854f774d24bf39d98 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 e44af851263f27aa0009b14a60bb2d0642a5ce74..36e5a6462675ceb3cef236c451321b1656d9fcc0 100644 +index 60c2868f255d372226e0c1389caaa5477bbef41e..2d4fe19da8d53d47df36399531e78da2c961aecd 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); @@ -5925,7 +5578,7 @@ index e44af851263f27aa0009b14a60bb2d0642a5ce74..36e5a6462675ceb3cef236c451321b16 @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() { @@ -5934,10 +5587,10 @@ index e44af851263f27aa0009b14a60bb2d0642a5ce74..36e5a6462675ceb3cef236c451321b16 } 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(); @@ -5946,10 +5599,10 @@ index e44af851263f27aa0009b14a60bb2d0642a5ce74..36e5a6462675ceb3cef236c451321b16 + } + // 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 { } } @@ -5979,7 +5632,7 @@ index e44af851263f27aa0009b14a60bb2d0642a5ce74..36e5a6462675ceb3cef236c451321b16 @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; @@ -5988,16 +5641,20 @@ index e44af851263f27aa0009b14a60bb2d0642a5ce74..36e5a6462675ceb3cef236c451321b16 b0 = 7; } else if (random.nextBoolean()) { return false; -@@ -243,6 +321,7 @@ public class Bat extends AmbientCreature { - private static boolean isSpookySeason = false; - private static final int ONE_HOUR = 20 * 60 * 60; - private static int lastSpookyCheck = -ONE_HOUR; +@@ -242,6 +320,11 @@ public class Bat extends AmbientCreature { + } + } + ++ // Pufferfish start - only check for spooky season once an hour ++ private static boolean isSpookySeason = false; ++ private static final int ONE_HOUR = 20 * 60 * 60; ++ private static int lastSpookyCheck = -ONE_HOUR; + public static boolean isHalloweenSeason(Level level) { return level.purpurConfig.forceHalloweenSeason || isHalloween(); } // Purpur private static boolean isHalloween() { - if (net.minecraft.server.MinecraftServer.currentTick - lastSpookyCheck > ONE_HOUR) { LocalDate localdate = LocalDate.now(); + int i = localdate.get(ChronoField.DAY_OF_MONTH); 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 { @@ -6011,7 +5668,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()); @@ -6052,10 +5709,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 @@ -6063,7 +5720,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(); @@ -6072,7 +5729,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) { @@ -6096,7 +5753,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 @@ -6110,10 +5767,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); @@ -6121,7 +5778,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() { @@ -6131,7 +5788,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(); @@ -6192,7 +5849,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() { @@ -6200,7 +5857,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)); @@ -6208,25 +5865,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 @@ -6253,32 +5910,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 { @@ -6297,11 +5930,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)); @@ -6364,15 +6018,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)); @@ -6477,12 +6131,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 @@ -6525,7 +6179,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; @@ -6575,7 +6229,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); + } @@ -6600,7 +6254,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 @@ -6608,8 +6262,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 @@ -6633,7 +6287,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); @@ -6671,14 +6325,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()); @@ -6709,13 +6363,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 @@ -6812,14 +6466,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)); @@ -6838,11 +6494,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) { @@ -6851,7 +6507,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(); @@ -6863,7 +6519,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() { @@ -6872,11 +6528,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..0e229955d9ea7036fab124fa7685df22280671f2 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 @@ -6941,7 +6597,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()); @@ -6949,15 +6605,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() { @@ -6966,34 +6622,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); + } @@ -7007,7 +6663,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)); } @@ -7027,7 +6683,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 { } } @@ -7047,7 +6703,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); } @@ -7060,17 +6716,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 { @@ -7157,7 +6813,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)) { @@ -7176,14 +6832,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 0c21959f57ae88fcd0a4d6dc911c1ce347c96528..e5a84dd5f1a375dd44b9d14dc7f44339bd8ddf3a 100644 +index feeb7bc34ae02e44d7f13f0bae5d175ef924c53a..529b1bef6abcecdd2c08afafc6548aeee7db9203 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()) { @@ -7250,42 +6901,25 @@ index 0c21959f57ae88fcd0a4d6dc911c1ce347c96528..e5a84dd5f1a375dd44b9d14dc7f44339 } 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; -@@ -196,7 +233,13 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder { + world.sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5D), this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D); ++ // Purpur start ++ entitycow.copyPosition(this); ++ entitycow.yBodyRot = this.yBodyRot; ++ entitycow.setYHeadRot(this.getYHeadRot()); ++ entitycow.yRotO = this.yRotO; ++ entitycow.xRotO = this.xRotO; ++ // Purpur end + // Paper start - custom shear drops; moved drop generation to separate method + drops.forEach(itemstack1 -> { + for (final ItemStack drop : drops) { 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(); } @@ -7330,7 +6964,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)); @@ -7345,7 +6979,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(); @@ -7355,10 +6989,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 { } @@ -7411,9 +7045,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)); @@ -7421,7 +7055,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)); @@ -7429,7 +7063,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()) { @@ -7441,7 +7075,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()) { @@ -7449,27 +7083,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 { @@ -7477,7 +7108,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 @@ -7490,10 +7121,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); @@ -7583,8 +7214,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)); @@ -7711,7 +7342,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 { @@ -7827,7 +7458,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); } @@ -7840,7 +7471,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); @@ -7849,10 +7480,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(); } @@ -7887,10 +7518,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..d8fa11a297ea2a183cac67c76b378ca912dba1f9 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; @@ -7898,7 +7529,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); } @@ -7975,7 +7606,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() { @@ -7990,21 +7621,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); @@ -8028,7 +7658,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 { } } @@ -8037,7 +7667,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 @@ -8054,21 +7684,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..d6dd771a868bdf012b6095e333ebb12fc6050478 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; @@ -8240,10 +7845,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()); @@ -8251,7 +7856,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")); } @@ -8266,12 +7871,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; } @@ -8279,24 +7884,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); @@ -8311,33 +7911,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); @@ -8406,7 +7984,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()) { @@ -8414,7 +7992,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() { @@ -8442,23 +8020,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 @@ -8496,10 +8074,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); } @@ -8544,7 +8122,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() { @@ -8552,7 +8130,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); } @@ -8569,7 +8147,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 @@ -8578,7 +8156,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(); @@ -8588,28 +8166,28 @@ 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/WaterAnimal.java b/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java -index c9cabb061ebc9172647304431cc3fb2593dd47ba..565408c03849fb3011fb708478a99ec6ffd081ef 100644 +index 8c4532a250f8679d729a35c17e9b5bd339264450..2b8336bd88641cfb29e94c8f01abfbdb39938bf3 100644 --- a/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java +++ b/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java -@@ -71,6 +71,6 @@ public abstract class WaterAnimal extends PathfinderMob { +@@ -74,6 +74,6 @@ public abstract class WaterAnimal extends PathfinderMob { i = world.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.maximum.or(i); j = world.getMinecraftWorld().paperConfig().entities.spawning.wateranimalSpawnHeight.minimum.or(j); // Paper end - Make water animal spawn height configurable - return pos.getY() >= j && pos.getY() <= i && world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER); -+ return ((reason == MobSpawnType.SPAWNER && world.getMinecraftWorld().purpurConfig.spawnerFixMC238526) || (pos.getY() >= j && pos.getY() <= i)) && world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER); // Purpur ++ return ((reason == EntitySpawnReason.SPAWNER && world.getMinecraftWorld().purpurConfig.spawnerFixMC238526) || (pos.getY() >= j && pos.getY() <= i)) && world.getFluidState(pos.below()).is(FluidTags.WATER) && world.getBlockState(pos.above()).is(Blocks.WATER); // Purpur } } 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 fc19bd326f00d1e8bd08ef6cc430c555337a6e3d..499e3294f8dd19fb3802f521cb7d24d0998c8aeb 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 { @@ -8641,7 +8219,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 brainProvider() { return Brain.provider(Allay.MEMORY_TYPES, Allay.SENSOR_TYPES); -@@ -220,13 +261,13 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS - private int behaviorTick = 0; // Pufferfish +@@ -221,14 +262,15 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS + @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("allayBrain"); -- if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish -+ //this.level().getProfiler().push("allayBrain"); // Purpur -+ 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.level().getProfiler().pop(); -- this.level().getProfiler().push("allayActivityUpdate"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("allayActivityUpdate"); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("allayBrain"); ++ //gameprofilerfiller.push("allayBrain"); // Purpur ++ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish + this.getBrain().tick(world, this); +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("allayActivityUpdate"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("allayActivityUpdate"); // Purpur AllayAi.updateActivity(this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur - super.customServerAiStep(); +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur + super.customServerAiStep(world); } diff --git a/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java -index 729fd2d52dd48e25ee7a077a3ffafc80ecef7c9f..5b024bc6166a9034eeba729bf3a53236446a03de 100644 +index c1ef714096159608752d744b98f615cd45fe459a..84516dcfc6cd0fe16c26538ccb86fb5c85b44ffa 100644 --- a/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java +++ b/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java @@ -82,6 +82,34 @@ public class Armadillo extends Animal { - return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 12.0D).add(Attributes.MOVEMENT_SPEED, 0.14D); + return Animal.createAnimalAttributes().add(Attributes.MAX_HEALTH, 12.0D).add(Attributes.MOVEMENT_SPEED, 0.14D); } + // Purpur start @@ -8938,28 +8518,31 @@ index 729fd2d52dd48e25ee7a077a3ffafc80ecef7c9f..5b024bc6166a9034eeba729bf3a53236 @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); -@@ -135,12 +163,12 @@ public class Armadillo extends Animal { +@@ -135,14 +163,14 @@ public class Armadillo extends Animal { @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("armadilloBrain"); -+ //this.level().getProfiler().push("armadilloBrain"); // Purpur - ((Brain) this.brain).tick((ServerLevel) this.level(), this); // CraftBukkit - decompile error -- this.level().getProfiler().pop(); -- this.level().getProfiler().push("armadilloActivityUpdate"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("armadilloActivityUpdate"); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("armadilloBrain"); ++ //gameprofilerfiller.push("armadilloBrain"); // Purpur + ((Brain) this.brain).tick(world, this); // CraftBukkit - decompile error +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("armadilloActivityUpdate"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("armadilloActivityUpdate"); // Purpur ArmadilloAi.updateActivity(this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur if (this.isAlive() && !this.isBaby() && --this.scuteTime <= 0) { - this.playSound(SoundEvents.ARMADILLO_SCUTE_DROP, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); this.forceDrops = true; // CraftBukkit + if (this.dropFromGiftLootTable(world, BuiltInLootTables.ARMADILLO_SHED, this::spawnAtLocation)) { 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 44937570f8e968ba4fe2822f69ca8f09679da89d..3359f492d6a8f193707e08768d73049454f178f4 100644 +index 31b10cd404b672d7ce21c2107d8f83e32de26ef4..c80d74caa393a31e09f2776cdb3cb950ef99e2ef 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 -@@ -97,6 +97,44 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder, B this.lookControl = new Axolotl.AxolotlLookControl(this, 20); } @@ -8978,7 +8561,6 @@ index 44937570f8e968ba4fe2822f69ca8f09679da89d..3359f492d6a8f193707e08768d730494 + protected void registerGoals() { + this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur + } -+ // Purpur end + + @Override + public void initAttributes() { @@ -9000,30 +8582,33 @@ index 44937570f8e968ba4fe2822f69ca8f09679da89d..3359f492d6a8f193707e08768d730494 + protected boolean isAlwaysExperienceDropper() { + return this.level().purpurConfig.axolotlAlwaysDropExp; + } ++ // Purpur end + @Override - public Map getModelRotationValues() { - return this.modelRotationValues; -@@ -272,13 +310,13 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder, B + @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("axolotlBrain"); -- if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish -+ //this.level().getProfiler().push("axolotlBrain"); // Purpur -+ 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.level().getProfiler().pop(); -- this.level().getProfiler().push("axolotlActivityUpdate"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("axolotlActivityUpdate"); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("axolotlBrain"); ++ //gameprofilerfiller.push("axolotlBrain"); // Purpur ++ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish + this.getBrain().tick(world, this); +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("axolotlActivityUpdate"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("axolotlActivityUpdate"); // Purpur AxolotlAi.updateActivity(this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur if (!this.isNoAi()) { Optional optional = this.getBrain().getMemory(MemoryModuleType.PLAY_DEAD_TICKS); -@@ -499,14 +537,22 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder, B private static class AxolotlMoveControl extends SmoothSwimmingMoveControl { private final Axolotl axolotl; @@ -9046,7 +8631,7 @@ index 44937570f8e968ba4fe2822f69ca8f09679da89d..3359f492d6a8f193707e08768d730494 if (!this.axolotl.isPlayingDead()) { super.tick(); } -@@ -521,9 +567,9 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder, B } @Override @@ -9059,10 +8644,10 @@ index 44937570f8e968ba4fe2822f69ca8f09679da89d..3359f492d6a8f193707e08768d730494 } 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 8941752e4600ccd11b3fa1147b2e414785589eed..e88d6d691bb176e33afeb294d735dfb2cbac12ff 100644 +index f3c884ab9c09f04dd01cabf2ee9de3b5b620563d..56d97225a909fd55f0d8aec992d5b6d42687c948 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 +@@ -87,6 +87,17 @@ public class Camel extends AbstractHorse { navigation.setCanWalkOverFences(true); } @@ -9080,26 +8665,29 @@ index 8941752e4600ccd11b3fa1147b2e414785589eed..e88d6d691bb176e33afeb294d735dfb2 @Override public void addAdditionalSaveData(CompoundTag nbt) { super.addAdditionalSaveData(nbt); -@@ -143,14 +154,14 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl +@@ -143,16 +154,16 @@ public class Camel extends AbstractHorse { @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("camelBrain"); -+ //this.level().getProfiler().push("camelBrain"); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("camelBrain"); ++ //gameprofilerfiller.push("camelBrain"); // Purpur Brain behaviorcontroller = (Brain) this.getBrain(); // CraftBukkit - decompile error - behaviorcontroller.tick((ServerLevel) this.level(), this); -- this.level().getProfiler().pop(); -- this.level().getProfiler().push("camelActivityUpdate"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("camelActivityUpdate"); // Purpur + behaviorcontroller.tick(world, this); +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("camelActivityUpdate"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("camelActivityUpdate"); // Purpur CamelAi.updateActivity(this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur - super.customServerAiStep(); +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur + super.customServerAiStep(world); } -@@ -312,6 +323,23 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl +@@ -314,6 +325,23 @@ public class Camel extends AbstractHorse { return this.dashCooldown; } @@ -9124,10 +8712,10 @@ index 8941752e4600ccd11b3fa1147b2e414785589eed..e88d6d691bb176e33afeb294d735dfb2 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 714703519965e8dae42be7442f292b581cc7c049..4c861b18fbfbae3cb2f1e3563393cfcf4005591c 100644 +index 36846ba6b6c7494c745ebd8b221479a9d02ff318..501a12398c56fe0df4e76a3bbce0f98c6c5aa6cb 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> { +@@ -106,6 +106,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(); @@ -9136,7 +8724,7 @@ index 714703519965e8dae42be7442f292b581cc7c049..4c861b18fbfbae3cb2f1e3563393cfcf public Frog(EntityType type, Level world) { super(type, world); -@@ -110,6 +112,58 @@ public class Frog extends Animal implements VariantHolder> { +@@ -113,6 +115,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); @@ -9195,26 +8783,27 @@ index 714703519965e8dae42be7442f292b581cc7c049..4c861b18fbfbae3cb2f1e3563393cfcf } @Override -@@ -184,13 +238,13 @@ public class Frog extends Animal implements VariantHolder> { - private int behaviorTick = 0; // Pufferfish +@@ -186,13 +240,14 @@ public class Frog extends Animal implements VariantHolder> { + @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("frogBrain"); -- if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish -+ //this.level().getProfiler().push("frogBrain"); // Purpur -+ 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.level().getProfiler().pop(); -- this.level().getProfiler().push("frogActivityUpdate"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("frogActivityUpdate"); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller profilerFiller = Profiler.get(); +- profilerFiller.push("frogBrain"); ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur ++ //profilerFiller.push("frogBrain"); // Purpur ++ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish + this.getBrain().tick(world, this); +- profilerFiller.pop(); +- profilerFiller.push("frogActivityUpdate"); ++ //profilerFiller.pop(); // Purpur ++ //profilerFiller.push("frogActivityUpdate"); // Purpur FrogAi.updateActivity(this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur - super.customServerAiStep(); +- profilerFiller.pop(); ++ //profilerFiller.pop(); // Purpur + super.customServerAiStep(world); } -@@ -373,7 +427,7 @@ public class Frog extends Animal implements VariantHolder> { +@@ -384,7 +439,7 @@ public class Frog extends Animal implements VariantHolder> { return world.getBlockState(pos.below()).is(BlockTags.FROGS_SPAWNABLE_ON) && isBrightEnoughToSpawn(world, pos); } @@ -9224,7 +8813,7 @@ index 714703519965e8dae42be7442f292b581cc7c049..4c861b18fbfbae3cb2f1e3563393cfcf 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 90393485ebcf8a4c8c74802fff942b1af8cfbf00..5cd69dd546f42e80a3d3e3a674f65c2ac39f3af9 100644 +index 48ac8c3f6e00c3c2dc67b6c994be7c0ac6dfcf81..071d14cc6697587ec14f02c69c78df364e7d8a8f 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 { @@ -9279,31 +8868,33 @@ index 90393485ebcf8a4c8c74802fff942b1af8cfbf00..5cd69dd546f42e80a3d3e3a674f65c2a @Override protected PathNavigation createNavigation(Level world) { return new WaterBoundPathNavigation(this, world); -@@ -86,13 +123,13 @@ public class Tadpole extends AbstractFish { - private int behaviorTick = 0; // Pufferfish +@@ -85,14 +122,15 @@ public class Tadpole extends AbstractFish { + @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("tadpoleBrain"); -- if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish -+ //this.level().getProfiler().push("tadpoleBrain"); // Purpur -+ 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.level().getProfiler().pop(); -- this.level().getProfiler().push("tadpoleActivityUpdate"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("tadpoleActivityUpdate"); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); + +- gameprofilerfiller.push("tadpoleBrain"); ++ //gameprofilerfiller.push("tadpoleBrain"); // Purpur ++ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // // Purpur - TODO: Pufferfish + this.getBrain().tick(world, this); +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("tadpoleActivityUpdate"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("tadpoleActivityUpdate"); // Purpur TadpoleAi.updateActivity(this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur - super.customServerAiStep(); +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur + 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 07bdea8a7d6706839a758afe0242202c7e841416..004a0212540c0a9061eb3aed458857d3da4c1c3d 100644 +index 76aca47d8638d5c37c57d3a59fa7f8ceaa5a53b4..ebf53d48b09918c7453f982a5e4f9a1584dfc544 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()); +@@ -93,6 +93,38 @@ public class Goat extends Animal { + }); } + // Purpur start @@ -9341,26 +8932,28 @@ index 07bdea8a7d6706839a758afe0242202c7e841416..004a0212540c0a9061eb3aed458857d3 @Override protected Brain.Provider brainProvider() { return Brain.provider(Goat.MEMORY_TYPES, Goat.SENSOR_TYPES); -@@ -193,13 +225,13 @@ public class Goat extends Animal { - private int behaviorTick = 0; // Pufferfish +@@ -194,14 +226,15 @@ public class Goat extends Animal { + @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("goatBrain"); -- if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish -+ //this.level().getProfiler().push("goatBrain"); // Purpur -+ 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.level().getProfiler().pop(); -- this.level().getProfiler().push("goatActivityUpdate"); -+ //this.level().getProfiler().pop(); // Purpur -+ //this.level().getProfiler().push("goatActivityUpdate"); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("goatBrain"); ++ //gameprofilerfiller.push("goatBrain"); // Purpur ++ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish + this.getBrain().tick(world, this); +- gameprofilerfiller.pop(); +- gameprofilerfiller.push("goatActivityUpdate"); ++ //gameprofilerfiller.pop(); // Purpur ++ //gameprofilerfiller.push("goatActivityUpdate"); // Purpur GoatAi.updateActivity(this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur - super.customServerAiStep(); +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur + super.customServerAiStep(world); } -@@ -397,6 +429,7 @@ public class Goat extends Animal { +@@ -399,6 +432,7 @@ public class Goat extends Animal { // Paper start - Goat ram API public void ram(net.minecraft.world.entity.LivingEntity entity) { @@ -9369,10 +8962,10 @@ index 07bdea8a7d6706839a758afe0242202c7e841416..004a0212540c0a9061eb3aed458857d3 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); @@ -9432,7 +9025,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)); } @@ -9440,7 +9033,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); } @@ -9450,10 +9043,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); } @@ -9498,10 +9091,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); } @@ -9546,10 +9139,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) { @@ -9600,7 +9194,7 @@ index cf6a3a63b6f2b96943c0f399e8c82d293fee31ba..7714d7f74836e5a765867fa0339c41fd + + @Override + public boolean isSaddled() { -+ return super.isSaddled() || (isTamed() && getSwag() != null); ++ return super.isSaddled() || (isTamed()); + } + // Purpur end + @@ -9635,7 +9229,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) { @@ -10148,7 +9745,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; } @@ -10176,7 +9773,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() { @@ -10214,7 +9811,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()) { @@ -10223,7 +9820,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); @@ -10235,44 +9832,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 { - } + 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; - 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.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()) { @@ -10280,7 +9877,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) { @@ -10288,7 +9885,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) { @@ -10297,10 +9894,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 82921c56c49edb0ca07425da563aa4876d4e6fb1..d9f5e2413321ed7ed57f84c865ab271af06e667c 100644 +index 244e38db508efa3eebebb6392c4ebb0805367baf..026e730f67c58caf385070d57a2e199fca966a46 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); @@ -10362,7 +9959,7 @@ index 82921c56c49edb0ca07425da563aa4876d4e6fb1..d9f5e2413321ed7ed57f84c865ab271a @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; } @@ -10477,7 +10074,7 @@ index 82921c56c49edb0ca07425da563aa4876d4e6fb1..d9f5e2413321ed7ed57f84c865ab271a 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()); @@ -10485,7 +10082,7 @@ index 82921c56c49edb0ca07425da563aa4876d4e6fb1..d9f5e2413321ed7ed57f84c865ab271a } @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()); } @@ -10493,10 +10090,10 @@ index 82921c56c49edb0ca07425da563aa4876d4e6fb1..d9f5e2413321ed7ed57f84c865ab271a } -@@ -270,6 +413,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(); @@ -10506,20 +10103,19 @@ index 82921c56c49edb0ca07425da563aa4876d4e6fb1..d9f5e2413321ed7ed57f84c865ab271a + shootCooldown--; + } + // Purpur end -+ int i; if (this.getInvulnerableTicks() > 0) { -@@ -286,7 +439,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; -@@ -311,7 +464,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) { @@ -10528,16 +10124,16 @@ index 82921c56c49edb0ca07425da563aa4876d4e6fb1..d9f5e2413321ed7ed57f84c865ab271a } } else { -@@ -371,7 +524,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); -@@ -398,8 +551,10 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob +@@ -389,8 +541,10 @@ public class WitherBoss extends Monster implements RangedAttackMob { } } @@ -10550,7 +10146,7 @@ index 82921c56c49edb0ca07425da563aa4876d4e6fb1..d9f5e2413321ed7ed57f84c865ab271a } this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); -@@ -587,11 +742,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) { @@ -10563,8 +10159,8 @@ index 82921c56c49edb0ca07425da563aa4876d4e6fb1..d9f5e2413321ed7ed57f84c865ab271a + if (getRider() == null || !this.isControllable()) this.entityData.set(WitherBoss.DATA_TARGETS.get(headIndex), id); // Purpur } - @Override -@@ -601,6 +756,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) { @@ -10573,10 +10169,10 @@ index 82921c56c49edb0ca07425da563aa4876d4e6fb1..d9f5e2413321ed7ed57f84c865ab271a } 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 @@ -10589,7 +10185,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; @@ -10597,7 +10193,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); @@ -10605,7 +10201,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() { @@ -10613,7 +10209,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 @@ -10633,45 +10229,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 d6f835320014c07f9d174d05929ed8cc16a10c10..9992a4e791495baae07645444f6374f083c56552 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); -@@ -371,7 +377,16 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -384,7 +390,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; -@@ -579,6 +594,12 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -595,6 +610,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 @@ -10719,32 +10315,34 @@ index 4423973d4d9a2c3879d98d1d4c8b8c117c677ac5..ffc754aa6ed61f62a0c94e9117f3008d @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; + } + @@ -10753,10 +10351,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(); @@ -10776,7 +10374,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 @@ -10816,7 +10414,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()) { @@ -10829,16 +10427,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 @@ -10847,7 +10445,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); @@ -10857,10 +10455,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); @@ -10937,7 +10535,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() { @@ -10946,7 +10544,7 @@ index 61004bb35b0edcc4578b8a9c1b280096466ba279..6c68c1df84e006f9992435f4c8e328c1 } @Override - protected void customServerAiStep() { + protected void customServerAiStep(ServerLevel world) { + // Purpur start + if (getRider() != null && this.isControllable()) { + Vec3 mot = getDeltaMovement(); @@ -10958,10 +10556,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 18dae37d65552077aa3825c76f433bbd31152db9..52993da6868161105450491a81f5c32356fa17aa 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); } @@ -10991,75 +10589,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); } @@ -11097,13 +10631,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 @@ -11135,7 +10669,7 @@ index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a + } + + @Override -+ protected void customServerAiStep() { ++ protected void customServerAiStep(ServerLevel world) { + if (powerToggleDelay > 0) { + powerToggleDelay--; + } @@ -11150,7 +10684,7 @@ index d1041f2a4f1b3ea29ad532006e18cdc30c5019fa..4aca9a07a5638c67922914a617950f7a + } + prevSpacebarCharge = spacebarCharge; + } -+ super.customServerAiStep(); ++ super.customServerAiStep(world); + } + + @Override @@ -11203,7 +10737,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 { } } @@ -11213,7 +10747,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); @@ -11244,15 +10778,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); @@ -11260,12 +10794,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 } @@ -11273,7 +10807,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()); @@ -11282,11 +10816,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 @@ -11344,16 +10878,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 @@ -11370,54 +10904,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; +@@ -396,7 +462,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + } } - @Override -@@ -262,8 +328,7 @@ public class Drowned extends Zombie implements RangedAttackMob { - this.searchingForLand = targetingUnderwater; - } - -- 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 { @@ -11456,7 +10980,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 ace4959f818bf56882b290d109b8b97f2c145631..85b1fefbdb32c7f010dd5650d2573199273113bd 100644 +index 48dcd2bc12ce1d08cc5195bff5460dc0dd9902d3..39ec4b00c6254824632b37ea9824ae9ff84cdb20 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 { @@ -11510,20 +11034,20 @@ index ace4959f818bf56882b290d109b8b97f2c145631..85b1fefbdb32c7f010dd5650d2573199 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() { @@ -11532,30 +11056,30 @@ index ace4959f818bf56882b290d109b8b97f2c145631..85b1fefbdb32c7f010dd5650d2573199 } @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 +@@ -383,6 +413,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 { +@@ -397,6 +429,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 { +@@ -441,7 +474,7 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean requiresCustomPersistence() { @@ -11564,17 +11088,17 @@ index ace4959f818bf56882b290d109b8b97f2c145631..85b1fefbdb32c7f010dd5650d2573199 } private static class EndermanFreezeWhenLookedAt extends Goal { -@@ -507,7 +540,16 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -488,7 +521,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; @@ -11582,17 +11106,17 @@ index ace4959f818bf56882b290d109b8b97f2c145631..85b1fefbdb32c7f010dd5650d2573199 } @Override -@@ -552,7 +594,16 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -533,7 +575,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; @@ -11601,7 +11125,7 @@ index ace4959f818bf56882b290d109b8b97f2c145631..85b1fefbdb32c7f010dd5650d2573199 @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 { @@ -11685,10 +11209,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..732fa9c2bf22e488ba531c0f9fd2a7e08468ff63 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; } @@ -11732,8 +11256,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)); @@ -11741,20 +11265,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); } @@ -11799,10 +11323,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 { } } @@ -11825,7 +11349,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() { @@ -11834,7 +11358,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 { } @@ -11843,7 +11367,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 @@ -11853,7 +11377,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 { @@ -11922,7 +11446,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); @@ -11954,10 +11478,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); @@ -12010,7 +11534,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)); @@ -12018,7 +11542,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()) { @@ -12027,7 +11551,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 { } @@ -12036,7 +11560,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; } @@ -12055,7 +11579,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(); @@ -12065,10 +11589,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); @@ -12127,8 +11651,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() { @@ -12138,10 +11662,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 { } @@ -12186,9 +11710,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)); @@ -12197,7 +11721,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 { @@ -12259,7 +11783,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; @@ -12268,10 +11792,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) { @@ -12287,10 +11811,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; @@ -12299,7 +11823,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); @@ -12364,15 +11888,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); + } + } + @@ -12392,7 +11916,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() { @@ -12413,7 +11937,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(); @@ -12425,7 +11949,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; } @@ -12447,7 +11971,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); } @@ -12464,9 +11988,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 @@ -12477,7 +12000,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"); } @@ -12486,7 +12009,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); } @@ -12696,19 +12219,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); } @@ -12750,6 +12273,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)); @@ -12760,10 +12284,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..487f21c6e6ffc0dc9c0733241a8ded8c73a5ec8f 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); } @@ -12811,6 +12335,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)); @@ -12819,8 +12344,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(); @@ -12829,29 +12354,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)); - } +@@ -153,7 +195,7 @@ public class Ravager extends Raider { + if (world instanceof ServerLevel) { + ServerLevel worldserver = (ServerLevel) world; -- 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(); +- 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; +- 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() { @@ -12966,7 +12491,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 { +@@ -170,7 +207,7 @@ public class Silverfish extends Monster { 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; @@ -13070,7 +12595,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); } @@ -13111,7 +12636,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 { } } @@ -13138,7 +12663,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; + } @@ -13176,10 +12701,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; @@ -13187,7 +12712,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); } @@ -13274,10 +12799,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(); @@ -13289,7 +12814,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; @@ -13297,7 +12822,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()); } @@ -13306,7 +12831,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) { @@ -13343,7 +12868,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 { @@ -13353,7 +12878,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 { @@ -13409,7 +12934,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 { @@ -13448,11 +12973,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 { @@ -13499,7 +13024,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 { @@ -13510,7 +13035,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() { @@ -13519,7 +13044,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)); @@ -13539,20 +13064,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; } @@ -13589,7 +13114,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)); + } + } @@ -13619,7 +13144,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() { @@ -13628,7 +13153,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)); @@ -13649,7 +13174,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); } @@ -13666,7 +13191,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 { @@ -13676,10 +13201,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); } @@ -13721,15 +13246,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); @@ -13742,10 +13268,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); } @@ -13785,9 +13311,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)); @@ -13799,7 +13325,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 { @@ -13843,10 +13369,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 aa458ede5bd645ebf524238179edb33f41bd683f..0cf110be4ec7823996e89c1d1e014e091c1d3d8a 100644 +index 35b0c5c322864e2f5ae5a412296072f268adcd05..f30ad422f19757664228f2064465fbcb22bb54f6 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 { +@@ -85,6 +85,39 @@ public class Zoglin extends Monster implements HoglinBase { this.xpReward = 5; } @@ -13886,24 +13412,26 @@ index aa458ede5bd645ebf524238179edb33f41bd683f..0cf110be4ec7823996e89c1d1e014e09 @Override protected Brain.Provider brainProvider() { return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); -@@ -233,9 +266,10 @@ public class Zoglin extends Monster implements Enemy, HoglinBase { +@@ -248,10 +281,11 @@ public class Zoglin extends Monster implements HoglinBase { @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("zoglinBrain"); -+ //this.level().getProfiler().push("zoglinBrain"); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller profilerFiller = Profiler.get(); +- profilerFiller.push("zoglinBrain"); ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur ++ //profilerFiller.push("zoglinBrain"); // Purpur + if (getRider() == null || !this.isControllable()) // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel)this.level(), this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur + this.getBrain().tick(world, this); +- profilerFiller.pop(); ++ //profilerFiller.pop(); // Purpur 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 @@ -13975,7 +13503,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)); @@ -13996,7 +13524,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() { @@ -14030,15 +13558,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); @@ -14047,7 +13575,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 @@ -14056,7 +13584,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) { @@ -14080,10 +13608,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 } @@ -14091,7 +13619,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()) { @@ -14104,7 +13632,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() { @@ -14114,10 +13642,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 { }); } @@ -14176,7 +13704,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)) { @@ -14188,9 +13716,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 { @@ -14276,29 +13804,31 @@ index 10388cf33f6f33070aa84b3b2d7bd14fc50ceea8..1c04fbea0dce4167a0902b92b95d470f @Nullable diff --git a/src/main/java/net/minecraft/world/entity/monster/breeze/Breeze.java b/src/main/java/net/minecraft/world/entity/monster/breeze/Breeze.java -index ee9098f311b5db7251fcaf3ca199ae51ec1f2a2a..0d8e49e4f3c52244f8f84d6e4beeaa60aa6acdd9 100644 +index a16fd9c4679e874ad2d499f3c00c2ddfd780a7a5..0bc771e20a9bab139cd3fc03ff40baabf787b2f7 100644 --- a/src/main/java/net/minecraft/world/entity/monster/breeze/Breeze.java +++ b/src/main/java/net/minecraft/world/entity/monster/breeze/Breeze.java -@@ -228,11 +228,11 @@ public class Breeze extends Monster { +@@ -235,12 +235,12 @@ public class Breeze extends Monster { @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("breezeBrain"); -+ //this.level().getProfiler().push("breezeBrain"); // Purpur - this.getBrain().tick((ServerLevel)this.level(), this); -- this.level().getProfiler().popPush("breezeActivityUpdate"); -+ //this.level().getProfiler().popPush("breezeActivityUpdate"); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller profilerFiller = Profiler.get(); +- profilerFiller.push("breezeBrain"); ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur ++ //profilerFiller.push("breezeBrain"); // Purpur + this.getBrain().tick(world, this); +- profilerFiller.popPush("breezeActivityUpdate"); ++ //profilerFiller.popPush("breezeActivityUpdate"); // Purpur BreezeAi.updateActivity(this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur - super.customServerAiStep(); +- profilerFiller.pop(); ++ //profilerFiller.pop(); // Purpur + 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 7de73564bc73d6504e18977e97a2ef5f46189e15..6525155cdb5edb326b4f770e68400911ec25d95d 100644 +index 6ea90e54759dbeab025e0a1896ee834ea9986427..7afde99f81ec222ecbffbdcdad3aa6404e8221e0 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 { +@@ -92,11 +92,49 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { this.xpReward = 5; } @@ -14325,6 +13855,11 @@ index 7de73564bc73d6504e18977e97a2ef5f46189e15..6525155cdb5edb326b4f770e68400911 + } + // Purpur end + + @VisibleForTesting + public void setTimeInOverworld(int timeInOverworld) { + this.timeInOverworld = timeInOverworld; + } + + @Override + public int getPurpurBreedTime() { + return this.level().purpurConfig.hoglinBreedingTicks; @@ -14343,25 +13878,26 @@ index 7de73564bc73d6504e18977e97a2ef5f46189e15..6525155cdb5edb326b4f770e68400911 @Override public boolean canBeLeashed() { return true; -@@ -156,10 +194,10 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { - private int behaviorTick; // Pufferfish +@@ -158,10 +196,11 @@ public class Hoglin extends Animal implements Enemy, HoglinBase { + @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("hoglinBrain"); -- if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish -+ //this.level().getProfiler().push("hoglinBrain"); // Purpur -+ 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.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller profilerFiller = Profiler.get(); +- profilerFiller.push("hoglinBrain"); ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur ++ //profilerFiller.push("hoglinBrain"); // Purpur ++ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // Purpur - TODO: Pufferfish + this.getBrain().tick(world, this); +- profilerFiller.pop(); ++ //profilerFiller.pop(); // Purpur HoglinAi.updateActivity(this); if (this.isConverting()) { this.timeInOverworld++; 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 b2ae7088f90bf3cd04a59c6ddfdba60c58c6e1c8..e2b3256184b860b2f27fbcff4e09b70b43aedae8 100644 +index e04d2c5e75dc774fe893a552474fdb8045c32693..b53e4a312ea0dbbd16e948e61c3f6b836d46f3b8 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 +@@ -96,6 +96,39 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento this.xpReward = 5; } @@ -14401,47 +13937,49 @@ index b2ae7088f90bf3cd04a59c6ddfdba60c58c6e1c8..e2b3256184b860b2f27fbcff4e09b70b @Override public void addAdditionalSaveData(CompoundTag nbt) { super.addAdditionalSaveData(nbt); -@@ -296,10 +329,10 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento - private int behaviorTick; // Pufferfish - @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("piglinBrain"); -- if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish -+ //this.level().getProfiler().push("piglinBrain"); // Purpur -+ 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.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur - PiglinAi.updateActivity(this); - super.customServerAiStep(); - } -@@ -390,7 +423,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento +@@ -306,11 +339,12 @@ 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); + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("piglinBrain"); ++ //gameprofilerfiller.push("piglinBrain"); // Purpur ++ //if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider // // Purpur - TODO: Pufferfish + this.getBrain().tick(world, this); +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur + PiglinAi.updateActivity(this); + super.customServerAiStep(world); + } +@@ -405,7 +439,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento + + @Override + 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 + @@ -14449,10 +13987,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 fcadd7f28ccb81bbb36e97d8b8d8a8ba3f3d6a16..2f43bef3acd9db78ecc869f5ff0f4d0f5e121d28 100644 +index 24eaeb93284fe1a573026b85818a93a34fd9e1ec..719179fb232a4f39a2c1642cc0e9593f4dea4bb8 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 { +@@ -65,6 +65,39 @@ public class PiglinBrute extends AbstractPiglin { this.xpReward = 20; } @@ -14490,26 +14028,28 @@ index fcadd7f28ccb81bbb36e97d8b8d8a8ba3f3d6a16..2f43bef3acd9db78ecc869f5ff0f4d0f + } + 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,9 +139,10 @@ public class PiglinBrute extends AbstractPiglin { + return Monster.createMonsterAttributes() + .add(Attributes.MAX_HEALTH, 50.0) +@@ -115,10 +148,11 @@ public class PiglinBrute extends AbstractPiglin { @Override - protected void customServerAiStep() { -- this.level().getProfiler().push("piglinBruteBrain"); -+ //this.level().getProfiler().push("piglinBruteBrain"); // Purpur + protected void customServerAiStep(ServerLevel world) { +- ProfilerFiller profilerFiller = Profiler.get(); +- profilerFiller.push("piglinBruteBrain"); ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur ++ //profilerFiller.push("piglinBruteBrain"); // Purpur + if (getRider() == null || this.isControllable()) // Purpur - only use brain if no rider - this.getBrain().tick((ServerLevel)this.level(), this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur + this.getBrain().tick(world, this); +- profilerFiller.pop(); ++ //profilerFiller.pop(); // Purpur PiglinBruteAi.updateActivity(this); PiglinBruteAi.maybePlayActivitySound(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 40bbd80b1ed4afede6f0769e7f3fcfc61200452f..8e24cd9ed03e2f11da6f4fb2dd58dd9b9e5d7a06 100644 +index 6180019da58b19d2595da508aed3196af922d587..692261880d05daa75fc53dde31d0f2b95dc52746 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 { +@@ -127,8 +127,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); @@ -14542,21 +14082,19 @@ index 40bbd80b1ed4afede6f0769e7f3fcfc61200452f..8e24cd9ed03e2f11da6f4fb2dd58dd9b @Override public Packet getAddEntityPacket(ServerEntity entityTrackerEntry) { return new ClientboundAddEntityPacket(this, entityTrackerEntry, this.hasPose(Pose.EMERGING) ? 1 : 0); -@@ -277,10 +301,11 @@ public class Warden extends Monster implements VibrationSystem { - protected void customServerAiStep() { - ServerLevel worldserver = (ServerLevel) this.level(); +@@ -279,9 +303,9 @@ public class Warden extends Monster implements VibrationSystem { + protected void customServerAiStep(ServerLevel world) { + ProfilerFiller gameprofilerfiller = Profiler.get(); -- worldserver.getProfiler().push("wardenBrain"); -+ //worldserver.getProfiler().push("wardenBrain"); // Purpur -+ //if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - TODO: Move to Ridables patch - if (this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish - this.getBrain().tick(worldserver, this); -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur - super.customServerAiStep(); +- gameprofilerfiller.push("wardenBrain"); ++ //gameprofilerfiller.push("wardenBrain"); // Purpur + this.getBrain().tick(world, this); +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur + super.customServerAiStep(world); if ((this.tickCount + this.getId()) % 120 == 0) { - Warden.applyDarknessAround(worldserver, this.position(), this, 20); -@@ -395,17 +420,14 @@ public class Warden extends Monster implements VibrationSystem { + Warden.applyDarknessAround(world, this.position(), this, 20); +@@ -396,17 +420,14 @@ public class Warden extends Monster implements VibrationSystem { @Contract("null->false") public boolean canTargetEntity(@Nullable Entity entity) { @@ -14578,7 +14116,7 @@ index 40bbd80b1ed4afede6f0769e7f3fcfc61200452f..8e24cd9ed03e2f11da6f4fb2dd58dd9b 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; @@ -14590,7 +14128,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 { @@ -14631,20 +14169,20 @@ 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 a16d9c1661690de0374a4a3c31b119293d8fa52b..d58f845dc814011b8126cc641476b6e4e25bc328 100644 +index b7a34f1c4d7b5ef3f7a843d152e33c839dcdedd5..b4ffad429ace965f16ebf47119c880b709b27f2e 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java -@@ -142,6 +142,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); }); + private boolean isLobotomized = false; public boolean isLobotomized() { return this.isLobotomized; } // Purpur + private int notLobotomizedCount = 0; // Purpur - public long nextGolemPanic = -1; // Pufferfish - -@@ -156,6 +158,92 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - this.getNavigation().setCanFloat(true); + public Villager(EntityType entityType, Level world) { + this(entityType, world, VillagerType.PLAINS); +@@ -154,6 +156,92 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.getNavigation().setRequiredPathLength(48.0F); this.setCanPickUpLoot(true); 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)); @@ -14736,7 +14274,7 @@ index a16d9c1661690de0374a4a3c31b119293d8fa52b..d58f845dc814011b8126cc641476b6e4 } @Override -@@ -192,7 +280,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -190,7 +278,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler brain.addActivity(Activity.PLAY, VillagerGoalPackages.getPlayPackage(0.5F)); } else { brain.setSchedule(Schedule.VILLAGER_DEFAULT); @@ -14745,15 +14283,20 @@ index a16d9c1661690de0374a4a3c31b119293d8fa52b..d58f845dc814011b8126cc641476b6e4 } brain.addActivity(Activity.CORE, VillagerGoalPackages.getCorePackage(villagerprofession, 0.5F)); -@@ -255,15 +343,24 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - // Paper start - this.customServerAiStep(false); +@@ -250,13 +338,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + // Paper start - EAR 2 + this.customServerAiStep(world, false); } -- protected void customServerAiStep(final boolean inactive) { -+ protected void customServerAiStep(boolean inactive) { // Purpur - not final - // Paper end -- this.level().getProfiler().push("villagerBrain"); -+ //this.level().getProfiler().push("villagerBrain"); // Purpur +- protected void customServerAiStep(ServerLevel world, final boolean inactive) { ++ protected void customServerAiStep(ServerLevel world, boolean inactive) { // Purpur - not final + // Paper end - EAR 2 +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur + +- gameprofilerfiller.push("villagerBrain"); +- if (!inactive) this.getBrain().tick(world, this); +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.push("villagerBrain"); // Purpur + // Purpur start + if (this.level().purpurConfig.villagerLobotomizeEnabled) { + // treat as inactive if lobotomized @@ -14762,28 +14305,21 @@ index a16d9c1661690de0374a4a3c31b119293d8fa52b..d58f845dc814011b8126cc641476b6e4 + this.isLobotomized = false; + } + // 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 - } -+ else if (this.isLobotomized && shouldRestock()) restock(); // Purpur - // Pufferfish end -- this.level().getProfiler().pop(); -+ //this.level().getProfiler().pop(); // Purpur ++ if (!inactive && (getRider() == null || !this.isControllable())) this.getBrain().tick(world, this); // Purpur ++ //gameprofilerfiller.pop(); // Purpur if (this.assignProfessionWhenSpawned) { this.assignProfessionWhenSpawned = false; } -@@ -319,7 +416,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -312,7 +408,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(); -@@ -333,9 +430,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -326,9 +422,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } if (flag) { @@ -14796,7 +14332,7 @@ index a16d9c1661690de0374a4a3c31b119293d8fa52b..d58f845dc814011b8126cc641476b6e4 this.startTrading(player); } -@@ -505,7 +604,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -493,7 +591,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler while (iterator.hasNext()) { MerchantOffer merchantrecipe = (MerchantOffer) iterator.next(); @@ -14805,7 +14341,7 @@ index a16d9c1661690de0374a4a3c31b119293d8fa52b..d58f845dc814011b8126cc641476b6e4 } } -@@ -747,7 +846,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -726,7 +824,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @Override public boolean canBreed() { @@ -14814,7 +14350,7 @@ index a16d9c1661690de0374a4a3c31b119293d8fa52b..d58f845dc814011b8126cc641476b6e4 } private boolean hungry() { -@@ -940,6 +1039,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -905,6 +1003,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler public boolean hasFarmSeeds() { return this.getInventory().hasAnyMatching((itemstack) -> { @@ -14826,7 +14362,7 @@ index a16d9c1661690de0374a4a3c31b119293d8fa52b..d58f845dc814011b8126cc641476b6e4 return itemstack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS); }); } -@@ -997,6 +1101,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -962,6 +1065,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } public void spawnGolemIfNeeded(ServerLevel world, long time, int requiredCount) { @@ -14834,7 +14370,7 @@ index a16d9c1661690de0374a4a3c31b119293d8fa52b..d58f845dc814011b8126cc641476b6e4 if (this.wantsToSpawnGolem(time)) { AABB axisalignedbb = this.getBoundingBox().inflate(10.0D, 10.0D, 10.0D); List list = world.getEntitiesOfClass(Villager.class, axisalignedbb); -@@ -1061,6 +1166,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -1026,6 +1130,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @Override public void startSleeping(BlockPos pos) { @@ -14861,10 +14397,10 @@ index 8734ab1bd8299bbf43906d81a349c2a13e0981a7..3ca83269311cbc18c9ef3ce62cff6a2d "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..959e10586cddaae2590d2d84f5fd809dad80889b 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,43 @@ 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. } @@ -14908,7 +14444,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 +116,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) -> { @@ -14917,7 +14453,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 +129,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)); @@ -14925,7 +14461,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 +158,13 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill if (!this.level().isClientSide) { if (this.getOffers().isEmpty()) { @@ -14942,9 +14478,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 { @@ -14967,7 +14503,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 09bcbc0ae36e4e69fee87a7e0c49acf496117a39..330b21946564e6a7b463a258c02fee3f91e0f057 100644 +index 61d412c4f1ebd55661cc3f0260468e3ac0efe0bb..c1d068fa99ec0fd5685bbb627a775e4d1587feab 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java @@ -197,17 +197,40 @@ public abstract class Player extends LivingEntity { @@ -15024,24 +14560,25 @@ index 09bcbc0ae36e4e69fee87a7e0c49acf496117a39..330b21946564e6a7b463a258c02fee3f this.noPhysics = this.isSpectator(); if (this.isSpectator()) { this.setOnGround(false); -@@ -366,6 +395,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 +@@ -332,6 +361,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() { -@@ -598,7 +637,7 @@ public abstract class Player extends LivingEntity { ++ + this.cooldowns.tick(); + this.updatePlayerPose(); + if (this.currentImpulseContextResetGraceTime > 0) { +@@ -622,7 +662,7 @@ public abstract class Player extends LivingEntity { while (iterator.hasNext()) { Entity entity = (Entity) iterator.next(); @@ -15050,7 +14587,7 @@ index 09bcbc0ae36e4e69fee87a7e0c49acf496117a39..330b21946564e6a7b463a258c02fee3f list1.add(entity); } else if (!entity.isRemoved()) { this.touch(entity); -@@ -1317,7 +1356,7 @@ public abstract class Player extends LivingEntity { +@@ -1274,7 +1314,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 @@ -15059,30 +14596,41 @@ index 09bcbc0ae36e4e69fee87a7e0c49acf496117a39..330b21946564e6a7b463a258c02fee3f } float f3 = f + f1; -@@ -1955,9 +1994,19 @@ public abstract class Player extends LivingEntity { +@@ -1640,7 +1680,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(); + } + +@@ -1900,7 +1940,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; - } -@@ -2038,6 +2087,13 @@ public abstract class Player extends LivingEntity { ++ } else { ++ return 0; ++ } ++ // Purpur end + } + + @Override +@@ -1978,6 +2034,13 @@ public abstract class Player extends LivingEntity { return slot != EquipmentSlot.BODY; } @@ -15096,17 +14644,8 @@ index 09bcbc0ae36e4e69fee87a7e0c49acf496117a39..330b21946564e6a7b463a258c02fee3f public boolean setEntityOnShoulder(CompoundTag entityNbt) { if (!this.isPassenger() && this.onGround() && !this.isInWater() && !this.isInPowderSnow) { if (this.getShoulderEntityLeft().isEmpty()) { -@@ -2335,7 +2391,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 9ca29b3d4bf8bca5f51f3644e12fcbec2cb5d35e..1dd61ee306231f77664dee7e4f2b617fe2e3659f 100644 +index accc246f441c8bf5e1a755cfc0db8f97c0c01c6b..f91519f73e766cf891351a95d76abb416da2f957 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 { @@ -15117,7 +14656,7 @@ index 9ca29b3d4bf8bca5f51f3644e12fcbec2cb5d35e..1dd61ee306231f77664dee7e4f2b617f // Spigot Start @Override -@@ -356,7 +357,7 @@ public abstract class AbstractArrow extends Projectile { +@@ -371,7 +372,7 @@ public abstract class AbstractArrow extends Projectile { Vec3 vec3d = this.getDeltaMovement(); this.setDeltaMovement(vec3d.multiply((double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F), (double) (this.random.nextFloat() * 0.2F))); @@ -15125,8 +14664,8 @@ index 9ca29b3d4bf8bca5f51f3644e12fcbec2cb5d35e..1dd61ee306231f77664dee7e4f2b617f + if (this.level().purpurConfig.arrowMovementResetsDespawnCounter) this.life = 0; // Purpur - do not reset despawn counter } - @Override -@@ -589,6 +590,12 @@ public abstract class AbstractArrow extends Projectile { + public boolean isInGround() { +@@ -623,6 +624,12 @@ public abstract class AbstractArrow extends Projectile { return this.firedFromWeapon; } @@ -15140,35 +14679,36 @@ index 9ca29b3d4bf8bca5f51f3644e12fcbec2cb5d35e..1dd61ee306231f77664dee7e4f2b617f 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..6bd6113cabfae068aa421991f0a9016419f20349 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 { @@ -15185,42 +14725,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 091ca20cc7e495dbff90f2fcaae51fb1b2bb33d5..9ededdbb5db39e9dff7376d80e93f41e93efdf5d 100644 +index 49c0f09f91f9ea2428fd3b13b00c99073074beba..b0e258d6025dd9536f1656e087bf85fee60e642d 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -71,7 +71,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { - if (!isLoaded) { - if (Projectile.loadedThisTick > gg.pufferfish.pufferfish.PufferfishConfig.maxProjectileLoadsPerTick) { - if (++this.loadedLifetime > gg.pufferfish.pufferfish.PufferfishConfig.maxProjectileLoadsPerProjectile) { -- this.discard(); -+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); // Purpur - } - return; - } -@@ -394,7 +394,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { - public boolean mayInteract(Level world, BlockPos pos) { +@@ -479,7 +479,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); } - 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..69dd29ed5e3cb37180b65183b0a83c8619d8e9a0 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 { @@ -15267,33 +14798,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 5f790dd24f2bdae827c6dc597064b9b265089751..7cc4a2a6cfef90a84859a128a9e0521ce3110854 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 { @@ -15303,10 +14834,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 { @@ -15336,23 +14867,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..4ef87acec025c6eb706fd8845663aa4f415efb29 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 { +@@ -345,7 +345,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(); - - 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; @@ -15395,11 +14926,38 @@ 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 d8fcd6d1edec1f31a861fab4b86cbeb15ddc799d..c328f4155c0c4cc4f590d9d7a992497d8d129421 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,7 @@ public abstract class AbstractMinecart extends VehicleEntity { private double flyingY = 0.95; private double flyingZ = 0.95; public double maxSpeed = 0.4D; @@ -15407,14 +14965,15 @@ index a38ce400550893f63640e3bb5bb801ab40f06266..8b1c00062a5272d1020bc85491d8627c // CraftBukkit end protected AbstractMinecart(EntityType type, Level world) { - super(type, world); - this.targetDeltaMovement = Vec3.ZERO; - this.blocksBuilding = true; +@@ -102,6 +103,7 @@ public abstract class AbstractMinecart extends VehicleEntity { + } else { + this.behavior = new OldMinecartBehavior(this); + } + if (world != null) maxSpeed = storedMaxSpeed = world.purpurConfig.minecartMaxSpeed; // Purpur + } - protected AbstractMinecart(EntityType type, Level world, double x, double y, double z) { -@@ -296,6 +298,12 @@ public abstract class AbstractMinecart extends VehicleEntity { +@@ -288,6 +290,12 @@ public abstract class AbstractMinecart extends VehicleEntity { @Override public void tick() { @@ -15427,9 +14986,9 @@ index a38ce400550893f63640e3bb5bb801ab40f06266..8b1c00062a5272d1020bc85491d8627c // 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) {} +@@ -425,16 +433,62 @@ public abstract class AbstractMinecart extends VehicleEntity { + this.behavior.moveAlongTrack(world); + } + // Purpur start + private Double lastSpeed; @@ -15450,8 +15009,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)); @@ -15480,7 +15039,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)); @@ -15490,71 +15049,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 00b0004940339dc105fb95f813bd35b16f7a9fb4..934218634854a90c0c8230e3da2d6da3d6916645 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; +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 cf871c174091139c8ad1affb84f98fcd74b60dee..ca1a2e8b32bc8730e7bdb44820696b2c4d1063d1 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; @@ -15563,10 +15125,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)) { @@ -15688,7 +15250,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; @@ -15743,8 +15305,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 @@ -15756,7 +15318,7 @@ 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 { +@@ -308,6 +392,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(); @@ -15770,7 +15332,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) { @@ -15793,10 +15355,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); } @@ -15828,7 +15390,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; @@ -15867,10 +15429,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) { @@ -15881,11 +15443,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) -> { @@ -15894,7 +15455,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 { @@ -15922,7 +15483,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(); @@ -15931,7 +15492,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 { }); } @@ -16003,7 +15564,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); @@ -16027,7 +15588,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; } @@ -16038,10 +15599,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; } @@ -16075,21 +15636,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 { @@ -16108,10 +15656,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 { @@ -16129,7 +15677,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); } @@ -16147,13 +15695,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(); } @@ -16187,10 +15729,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) { @@ -16208,7 +15750,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 @@ -16216,7 +15758,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) { @@ -16225,38 +15767,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); @@ -16264,17 +15807,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 { @@ -16296,7 +15839,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 { @@ -16305,11 +15848,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 { @@ -16324,20 +15867,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 cc1e5882bee94864ad189d7f01ce78223411e51d..4c827c26656ac487cc8c66eeb67e4f38a29fec36 100644 +index b62db8c7c8c57e43869ee239ebf4b02f112355d9..f60e39e56a5dab2de62ae9cfd7a30a70b4985c09 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 { @@ -16350,51 +15893,54 @@ index cc1e5882bee94864ad189d7f01ce78223411e51d..4c827c26656ac487cc8c66eeb67e4f38 } 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 { +- 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 / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); + 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 7e308b364227dedc2d05496f5e0c90573f4a53f7..52e0a741e0a2274d3d70e8d8cdfa56f5e934deb2 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); @@ -16407,7 +15953,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 { @@ -16441,36 +15987,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 522b817f23f08eb720fe9d05eec7f548d2761603..9d9af312037c96c7773a456e37e6425f7004e73a 100644 +index 33e7d2884195677c4d6340d8b84c1dd85c636ec1..42b259c3878bd34b8e7cb768887fd1456be8db35 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; } @@ -16497,20 +16034,20 @@ index 522b817f23f08eb720fe9d05eec7f548d2761603..9d9af312037c96c7773a456e37e6425f 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(); } @@ -16524,32 +16061,32 @@ index 522b817f23f08eb720fe9d05eec7f548d2761603..9d9af312037c96c7773a456e37e6425f 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) { @@ -16557,46 +16094,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 { @@ -16608,10 +16131,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); } @@ -16621,7 +16144,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 { @@ -16640,33 +16163,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); @@ -16692,79 +16206,60 @@ 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..d7eb680b977656556a618431b1511c1050f6db5e 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 ++ entitythrowntrident.setActualEnchantments(stack.getEnchantments()); // Purpur - Add an option to fix MC-3304 projectile looting + -+ // 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); -+ } -+ // Purpur end + 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,16 @@ 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 + - 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/crafting/Ingredient.java b/src/main/java/net/minecraft/world/item/crafting/Ingredient.java -index e314f36951e9ac15c57137e24fce8c410373130a..21dfb8e91c5427ac12133de2c05d923d87adf5ba 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 { - @Nullable - private IntList stackingIds; - public boolean exact; // CraftBukkit -+ 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 ++ // Purpur start ++ List list = EquipmentSlot.VALUES.stream().filter((enumitemslot) -> LivingEntity.canGlideUsing(entityhuman.getItemBySlot(enumitemslot), enumitemslot)).toList(); ++ 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 + - ItemStack[] aitemstack = this.getItems(); - int i = aitemstack.length; - + 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/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java -index fce49b17905ab97e691aa8499a5dfed67adf0c40..1abf54eeaad1b062f1465ee1a847bbfcba295665 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; @@ -16775,7 +16270,7 @@ index fce49b17905ab97e691aa8499a5dfed67adf0c40..1abf54eeaad1b062f1465ee1a847bbfc 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); } @@ -16835,15 +16330,15 @@ index fce49b17905ab97e691aa8499a5dfed67adf0c40..1abf54eeaad1b062f1465ee1a847bbfc + // 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 @@ -16856,7 +16351,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 { @@ -16891,7 +16386,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 { @@ -16903,10 +16398,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()) { @@ -16915,82 +16410,20 @@ 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 f696afd7e241bf1966a2d505b5d59bff824b43e4..4ea1ce1cface25b9bf0e3958d55ba2fbbff69a9e 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 -@@ -647,7 +666,7 @@ public class Explosion { - } - - if (flag1) { -- this.level.getProfiler().push("explosion_blocks"); -+ //this.level.getProfiler().push("explosion_blocks"); // Purpur - List> list = new ArrayList(); - - Util.shuffle(this.toBlow, this.level.random); -@@ -722,7 +741,7 @@ public class Explosion { - Block.popResource(this.level, (BlockPos) pair.getSecond(), (ItemStack) pair.getFirst()); - } - -- this.level.getProfiler().pop(); -+ //this.level.getProfiler().pop(); // Purpur - } - - if (this.fire) { diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 2479b47186202de40cdb4ae773c696a4adee9bad..5057d9d433ba002a22d22adfaf7323b2cfaee9af 100644 +index 022de445bbbb869c38be4972c98dcf1c665539ec..7493262c2879af196e5585b15faad69ae42764e3 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -173,6 +173,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -174,6 +174,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl // Paper end - add paper world config 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; + private org.spigotmc.TickLimiter tileLimiter; @@ -181,6 +182,49 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions + 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 + // Purpur start @@ -17039,26 +16472,26 @@ index 2479b47186202de40cdb4ae773c696a4adee9bad..5057d9d433ba002a22d22adfaf7323b2 public CraftWorld getWorld() { return this.world; } -@@ -225,7 +269,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -226,7 +270,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public final List getEntitiesOfClass(final Class entityClass, final AABB boundingBox, final Predicate predicate) { -- this.getProfiler().incrementCounter("getEntities"); -+ //this.getProfiler().incrementCounter("getEntities"); // Purpur +- Profiler.get().incrementCounter("getEntities"); ++ //Profiler.get().incrementCounter("getEntities"); // Purpur final List ret = new java.util.ArrayList<>(); ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)this).moonrise$getEntityLookup().getEntities(entityClass, null, boundingBox, ret, predicate); -@@ -235,7 +279,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -236,7 +280,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public final List moonrise$getHardCollidingEntities(final Entity entity, final AABB box, final Predicate predicate) { -- this.getProfiler().incrementCounter("getEntities"); -+ //this.getProfiler().incrementCounter("getEntities"); // Purpur +- Profiler.get().incrementCounter("getEntities"); ++ //Profiler.get().incrementCounter("getEntities"); // Purpur final List ret = new java.util.ArrayList<>(); ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)this).moonrise$getEntityLookup().getHardCollidingEntities(entity, box, ret, predicate); -@@ -687,6 +731,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config & Anti-Xray +@@ -842,6 +886,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + // Paper end - getblock optimisations - cache world height/sections 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.purpurConfig = new org.purpurmc.purpur.PurpurWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), env); // Purpur @@ -17066,74 +16499,50 @@ index 2479b47186202de40cdb4ae773c696a4adee9bad..5057d9d433ba002a22d22adfaf7323b2 this.generator = gen; this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); -@@ -1366,18 +1412,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1440,9 +1486,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } protected void tickBlockEntities() { -- ProfilerFiller gameprofilerfiller = this.getProfiler(); -+ //ProfilerFiller gameprofilerfiller = this.getProfiler(); // Purpur +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); // Purpur - gameprofilerfiller.push("blockEntities"); -- this.timings.tileEntityPending.startTiming(); // Spigot + //gameprofilerfiller.push("blockEntities"); // Purpur -+ //this.timings.tileEntityPending.startTiming(); // Spigot // Purpur this.tickingBlockEntities = true; if (!this.pendingBlockEntityTickers.isEmpty()) { this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); - this.pendingBlockEntityTickers.clear(); - } -- this.timings.tileEntityPending.stopTiming(); // Spigot -+ //this.timings.tileEntityPending.stopTiming(); // Spigot // Purpur - -- this.timings.tileEntityTick.startTiming(); // Spigot -+ //this.timings.tileEntityTick.startTiming(); // Spigot // Purpur - // Spigot start - // Iterator iterator = this.blockEntityTickers.iterator(); - boolean flag = this.tickRateManager().runsNormally(); -@@ -1408,10 +1454,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - } +@@ -1480,7 +1526,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 -- this.timings.tileEntityTick.stopTiming(); // Spigot -+ //this.timings.tileEntityTick.stopTiming(); // Spigot // Purpur this.tickingBlockEntities = false; - co.aikar.timings.TimingHistory.tileEntityTicks += this.blockEntityTickers.size(); // Paper - gameprofilerfiller.pop(); + //gameprofilerfiller.pop(); // Purpur this.spigotConfig.currentPrimedTnt = 0; // Spigot } -@@ -1640,7 +1686,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1650,7 +1696,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public List getEntities(@Nullable Entity except, AABB box, Predicate predicate) { -- this.getProfiler().incrementCounter("getEntities"); -+ //this.getProfiler().incrementCounter("getEntities"); // Purpur - // Paper start - rewrite chunk system - final List ret = new java.util.ArrayList<>(); +- Profiler.get().incrementCounter("getEntities"); ++ //Profiler.get().incrementCounter("getEntities"); // Purpur + List list = Lists.newArrayList(); -@@ -1666,7 +1712,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + // Paper start - rewrite chunk system +@@ -1680,7 +1726,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public void getEntities(final EntityTypeTest entityTypeTest, final AABB boundingBox, final Predicate predicate, final List into, final int maxCount) { -- this.getProfiler().incrementCounter("getEntities"); -+ //this.getProfiler().incrementCounter("getEntities"); // Purpur +- Profiler.get().incrementCounter("getEntities"); ++ //Profiler.get().incrementCounter("getEntities"); // Purpur if (entityTypeTest instanceof net.minecraft.world.entity.EntityType byType) { if (maxCount != Integer.MAX_VALUE) { -@@ -1961,7 +2007,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -2031,4 +2077,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + return this.id; + } } - - public ProfilerFiller getProfiler() { -- if (gg.pufferfish.pufferfish.PufferfishConfig.disableMethodProfiler) return net.minecraft.util.profiling.InactiveProfiler.INSTANCE; // Pufferfish -+ if (true || gg.pufferfish.pufferfish.PufferfishConfig.disableMethodProfiler) return net.minecraft.util.profiling.InactiveProfiler.INSTANCE; // Pufferfish // Purpur - return (ProfilerFiller) this.profiler.get(); - } - -@@ -2042,4 +2088,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - return null; - } - // Paper end - optimize redstone (Alternate Current) ++ + // Purpur start + public boolean isNether() { + return getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER; @@ -17145,32 +16554,19 @@ index 2479b47186202de40cdb4ae773c696a4adee9bad..5057d9d433ba002a22d22adfaf7323b2 + // 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 e524b27d185da3e88668f8ef107517272860bd66..061706ee732f9809d6b73305c14871257af8305e 100644 +index 5297798c2be1ba85569c2b92ed221956bf75477a..7f936a7ba994ccb51c17168c798b42dde0877a5d 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -127,8 +127,8 @@ public final class NaturalSpawner { - } - - public static void spawnForChunk(ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnState info, boolean spawnAnimals, boolean spawnMonsters, boolean rareSpawn) { -- world.getProfiler().push("spawner"); -- world.timings.mobSpawn.startTiming(); // Spigot -+ //world.getProfiler().push("spawner"); // Purpur -+ //world.timings.mobSpawn.startTiming(); // Spigot // Purpur - MobCategory[] aenumcreaturetype = NaturalSpawner.SPAWNING_CATEGORIES; - int i = aenumcreaturetype.length; - -@@ -181,8 +181,8 @@ public final class NaturalSpawner { +@@ -211,7 +211,7 @@ public final class NaturalSpawner { } } -- world.timings.mobSpawn.stopTiming(); // Spigot -- world.getProfiler().pop(); -+ //world.timings.mobSpawn.stopTiming(); // Spigot // Purpur -+ //world.getProfiler().pop(); // Purpur +- gameprofilerfiller.pop(); ++ //gameprofilerfiller.pop(); // Purpur } // Paper start - Add mobcaps commands -@@ -253,7 +253,7 @@ public final class NaturalSpawner { +@@ -280,7 +280,7 @@ public final class NaturalSpawner { blockposition_mutableblockposition.set(l, i, i1); double d0 = (double) l + 0.5D; double d1 = (double) i1 + 0.5D; @@ -17179,8 +16575,50 @@ index e524b27d185da3e88668f8ef107517272860bd66..061706ee732f9809d6b73305c1487125 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 bbbd451ff184be8fa13bd93d53c89a9502f9951a..3c3d219c9339f64c23ec0b31783bf68a4423636c 100644 +--- a/src/main/java/net/minecraft/world/level/ServerExplosion.java ++++ b/src/main/java/net/minecraft/world/level/ServerExplosion.java +@@ -311,7 +311,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; +@@ -666,10 +666,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 { @@ -17189,12 +16627,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); @@ -17203,19 +16641,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); @@ -17228,20 +16666,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) { @@ -17263,10 +16701,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) { @@ -17275,19 +16713,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(); @@ -17296,7 +16734,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) { @@ -17306,10 +16744,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); } @@ -17319,7 +16757,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 29947de9eb6887f2e61516523ff08d8b581b0f53..4ff7e3693305069e7fad185802a3b0481ab70a4a 100644 +index b6d6c2cb9b227a17fb4ce42bc75f92206fbea043..1748aea6613e0c8081f70092c9431e7e04907383 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 { @@ -17330,10 +16768,10 @@ index 29947de9eb6887f2e61516523ff08d8b581b0f53..4ff7e3693305069e7fad185802a3b048 + 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) -> { @@ -17342,7 +16780,7 @@ index 29947de9eb6887f2e61516523ff08d8b581b0f53..4ff7e3693305069e7fad185802a3b048 }); 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()) { @@ -17351,7 +16789,7 @@ index 29947de9eb6887f2e61516523ff08d8b581b0f53..4ff7e3693305069e7fad185802a3b048 } 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) -> { @@ -17385,7 +16823,7 @@ index 29947de9eb6887f2e61516523ff08d8b581b0f53..4ff7e3693305069e7fad185802a3b048 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 } @@ -17404,7 +16842,7 @@ index 29947de9eb6887f2e61516523ff08d8b581b0f53..4ff7e3693305069e7fad185802a3b048 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) { @@ -17412,32 +16850,32 @@ index 29947de9eb6887f2e61516523ff08d8b581b0f53..4ff7e3693305069e7fad185802a3b048 + 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)) { @@ -17451,10 +16889,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); } @@ -17480,10 +16918,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 @@ -17492,7 +16930,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)); @@ -17501,7 +16939,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; } @@ -17536,11 +16974,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; @@ -17550,11 +17000,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()); @@ -17562,7 +17012,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); @@ -17571,7 +17021,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) { @@ -17602,10 +17052,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); } @@ -17631,10 +17081,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) { @@ -17643,10 +17093,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 d3d12f9114173f4971f95d7ef895a4374705bd3f..f34159f8d6c51af2341bf49db0d6d6f0417919cf 100644 +index db837b250fc35af5b528bf973b3b07f63e79bc46..ed3a310d56a0cca8c4c11c3768ac2056cd11edea 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())) { @@ -17654,7 +17104,7 @@ index d3d12f9114173f4971f95d7ef895a4374705bd3f..f34159f8d6c51af2341bf49db0d6d6f0 - 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 - @@ -17664,7 +17114,7 @@ index d3d12f9114173f4971f95d7ef895a4374705bd3f..f34159f8d6c51af2341bf49db0d6d6f0 + // 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; @@ -17675,7 +17125,7 @@ index d3d12f9114173f4971f95d7ef895a4374705bd3f..f34159f8d6c51af2341bf49db0d6d6f0 + 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); @@ -17683,9 +17133,9 @@ index d3d12f9114173f4971f95d7ef895a4374705bd3f..f34159f8d6c51af2341bf49db0d6d6f0 + } + // 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 { } } @@ -17712,10 +17162,10 @@ index d3d12f9114173f4971f95d7ef895a4374705bd3f..f34159f8d6c51af2341bf49db0d6d6f0 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) { @@ -17724,19 +17174,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..4f64011262eef6a24a8e8595ace1e4d1d82923e5 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); } @@ -17753,10 +17203,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; @@ -17764,7 +17214,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; } @@ -17784,7 +17234,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 { @@ -17798,10 +17248,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; } @@ -17821,10 +17271,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()) { @@ -17839,13 +17289,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()) { @@ -17857,19 +17307,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 ebb9baca7a65173f7c9fdf9bf47a8db876719625..d9a1ec9c6ccab71618a42121f049005cf821eb42 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( +@@ -88,7 +88,7 @@ public class EnderChestBlock extends AbstractChestBlock i + } else { + // Paper start - Fix InventoryOpenEvent cancellation - moved up; + 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; + playerEnderChestContainer.setActiveChest(enderChestBlockEntity); +@@ -104,6 +104,35 @@ public class EnderChestBlock extends AbstractChestBlock i } } @@ -17906,21 +17356,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..6db97982972bfc67c828f574fb86391e1cdcd4a5 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; @@ -17938,10 +17388,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 { } } @@ -17951,15 +17401,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 @@ -18028,10 +17478,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)) { @@ -18040,7 +17490,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 @@ -18066,10 +17516,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) { @@ -18078,29 +17528,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) { @@ -18110,10 +17560,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) { @@ -18122,7 +17572,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)) { @@ -18136,12 +17586,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; } @@ -18192,10 +17642,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) { @@ -18205,22 +17655,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) { @@ -18229,7 +17679,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) { @@ -18246,20 +17696,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..3e1dddab0500bb805e5accd0ece69c450bad478f 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 { @@ -18272,10 +17722,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(); @@ -18285,10 +17735,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) { @@ -18298,10 +17748,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; } } @@ -18328,7 +17778,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 { @@ -18415,10 +17865,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 @@ -18427,7 +17877,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 @@ -18436,7 +17886,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 @@ -18448,10 +17898,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; } @@ -18467,7 +17917,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; @@ -18515,10 +17965,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..3829dbae8542396f8360eae54f0ed18fbde4cd8c 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); @@ -18527,10 +17977,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) { @@ -18593,10 +18043,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(); @@ -18605,33 +18055,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 730aca233f6e7564d4cb85b5b628d23c4f01d2f4..d12469a1bbd37026012bfd6bce30d7a2593779da 100644 +index 15e0861486a2bda3e2f4049b1b5a299c870acd31..91a158ed90b7ce3eac7277fd962682a0226c08ed 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); @@ -18653,16 +18080,16 @@ index 730aca233f6e7564d4cb85b5b628d23c4f01d2f4..d12469a1bbd37026012bfd6bce30d7a2 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 { @@ -18720,7 +18147,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 @@ -18755,7 +18182,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 @@ -18768,10 +18195,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; @@ -18780,7 +18207,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; } @@ -18814,16 +18241,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 { } } @@ -18836,10 +18254,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); } @@ -18852,8 +18270,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 @@ -18865,10 +18283,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); } @@ -18886,10 +18304,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); @@ -18898,7 +18316,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 @@ -18915,7 +18333,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) { @@ -18934,12 +18352,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) { @@ -18965,7 +18383,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 @@ -18978,7 +18396,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 } @@ -18986,7 +18404,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 } @@ -19007,11 +18425,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); } @@ -19045,7 +18476,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 } @@ -19106,10 +18537,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 99fd67a78539133adf78d65e2c520ff3dd260301..852bfe68ab722a5cbdd90dbd70501b751fe81a78 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; @@ -19118,31 +18549,22 @@ 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/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 00987d0e1ee8a9541b0610616ace1c84d50e5f1a..a4578ae22409edb686d0bcbac8cbc1a2e1d7b988 100644 +index 4640baec5bed6c2d53cc0f8ca1d273cc115abe9b..15c83c6f5f56d6a27911d3bbd326cef1c21b1e58 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -130,7 +130,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - this.defaultBlockState = empty ? VOID_AIR_BLOCKSTATE : AIR_BLOCKSTATE; - // Paper end - get block chunk optimisation - -- this.lightningTick = new java.util.Random().nextInt(100000) << 1; // Pufferfish - initialize lightning tick -+ this.lightningTick = java.util.concurrent.ThreadLocalRandom.current().nextInt(100000) << 1; // Pufferfish - initialize lightning tick // Purpur - any random will do - } - - // CraftBukkit start -@@ -397,11 +397,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - if (LightEngine.hasDifferentLightProperties(this, blockposition, iblockdata1, iblockdata)) { - ProfilerFiller gameprofilerfiller = this.level.getProfiler(); +@@ -407,11 +407,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p + if (LightEngine.hasDifferentLightProperties(iblockdata1, iblockdata)) { + ProfilerFiller gameprofilerfiller = Profiler.get(); - gameprofilerfiller.push("updateSkyLightSources"); + //gameprofilerfiller.push("updateSkyLightSources"); // Purpur @@ -19155,39 +18577,19 @@ index 00987d0e1ee8a9541b0610616ace1c84d50e5f1a..a4578ae22409edb686d0bcbac8cbc1a2 } boolean flag3 = iblockdata1.hasBlockEntity(); -@@ -680,7 +680,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(this.locX, this.locZ).getEntityChunk().callEntitiesLoadEvent(); // Paper - rewrite chunk system - - if (this.needsDecoration) { -- try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper -+ //try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper // Purpur - this.needsDecoration = false; - java.util.Random random = new java.util.Random(); - random.setSeed(this.level.getSeed()); -@@ -700,7 +700,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - } - } - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); -- } // Paper -+ //} // Paper // Purpur - } - } - } -@@ -1037,10 +1037,10 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -1058,9 +1058,9 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p if (LevelChunk.this.isTicking(blockposition)) { try { -- ProfilerFiller gameprofilerfiller = LevelChunk.this.level.getProfiler(); -+ //ProfilerFiller gameprofilerfiller = LevelChunk.this.level.getProfiler(); +- ProfilerFiller gameprofilerfiller = Profiler.get(); ++ //ProfilerFiller gameprofilerfiller = Profiler.get(); - gameprofilerfiller.push(this::getType); -- this.blockEntity.tickTimer.startTiming(); // Spigot + //gameprofilerfiller.push(this::getType); -+ //this.blockEntity.tickTimer.startTiming(); // Spigot // Purpur BlockState iblockdata = LevelChunk.this.getBlockState(blockposition); if (this.blockEntity.getType().isValid(iblockdata)) { -@@ -1056,7 +1056,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -1076,7 +1076,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p // Paper end - Remove the Block Entity if it's invalid } @@ -19196,20 +18598,11 @@ index 00987d0e1ee8a9541b0610616ace1c84d50e5f1a..a4578ae22409edb686d0bcbac8cbc1a2 } catch (Throwable throwable) { if (throwable instanceof ThreadDeath) throw throwable; // Paper // Paper start - Prevent block entity and entity crashes -@@ -1067,7 +1067,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - // Paper end - Prevent block entity and entity crashes - // Spigot start - } finally { -- this.blockEntity.tickTimer.stopTiming(); -+ //this.blockEntity.tickTimer.stopTiming(); // Purpur - // Spigot end - } - } 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(); @@ -19218,10 +18611,10 @@ index d4a505ef4af9ded02aeb1a817bcbe5b1a912a5b3..97a310f042db1a838a744d2909d261aa listTag.add(compoundTagx); } 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 40689256711cc94a806ca1da346f4f62eda31526..4c178b234bc1118a577d0e016f4b986e9197e99d 100644 +index 78922c3e9a69db1774dd846047b79e9523d7cf41..0dde7cd71a32e6c0cde6cbbaef585896a3d7dae7 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 -@@ -177,7 +177,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -274,7 +274,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise // Paper start private static void printOversizedLog(String msg, Path file, int x, int z) { @@ -19231,7 +18624,7 @@ index 40689256711cc94a806ca1da346f4f62eda31526..4c178b234bc1118a577d0e016f4b986e private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { 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 1b1b475ca27e799e251d6f8a8c9fe1a4fd8bae83..04f67f7b43d2f461c776c76614dc3e5f060aea63 100644 +index 021221da5d0315f6e371380a705ac6b3f6ac18d3..27eb9a365006884c85603dc6d9dd8eee009c98b3 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 { @@ -19266,21 +18659,21 @@ index 1b1b475ca27e799e251d6f8a8c9fe1a4fd8bae83..04f67f7b43d2f461c776c76614dc3e5f 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 6785baf574f233ed1c3bea8d406be8a524d9ff82..d2f9ffa09d46287707324fd67e60736991b632ac 100644 +index f4fbcbb8ff6d2677af1a02a0801a323c06dce9b1..6f024a29e8824a604ff0c74f88522d23423beb5c 100644 --- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java +++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -@@ -227,7 +227,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(); -@@ -325,6 +325,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) { @@ -19289,13 +18682,13 @@ index 6785baf574f233ed1c3bea8d406be8a524d9ff82..d2f9ffa09d46287707324fd67e607369 + // 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) { @@ -19304,7 +18697,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); } @@ -19316,13 +18709,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); } @@ -19337,31 +18730,33 @@ 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/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -index 18bbb3f8f99849333ff4bc020c8ce758a69312a5..404080976208c30e9e95e5bee47c2a749e709a45 100644 +index cc7d94144e39f7dace7b569b4567def98396e8f9..91abbda59446d462979dddc4b380c6f24d0b4c92 100644 --- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java +++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java -@@ -53,8 +53,8 @@ public class PathFinder { +@@ -58,9 +58,9 @@ public class PathFinder { @Nullable // Paper start - Perf: remove streams and optimize collection - private Path findPath(ProfilerFiller profiler, Node startNode, List> positions, float followRange, int distance, float rangeMultiplier) { -- profiler.push("find_path"); -- profiler.markForCharting(MetricCategory.PATH_FINDING); -+ //profiler.push("find_path"); // Purpur -+ //profiler.markForCharting(MetricCategory.PATH_FINDING); // Purpur + private Path findPath(Node startNode, List> positions, float followRange, int distance, float rangeMultiplier) { +- ProfilerFiller profilerFiller = Profiler.get(); +- profilerFiller.push("find_path"); +- profilerFiller.markForCharting(MetricCategory.PATH_FINDING); ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur ++ //profilerFiller.push("find_path"); // Purpur ++ //profilerFiller.markForCharting(MetricCategory.PATH_FINDING); // Purpur // Set set = positions.keySet(); startNode.g = 0.0F; startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection -@@ -122,7 +122,7 @@ public class PathFinder { +@@ -128,7 +128,7 @@ public class PathFinder { if (best == null || comparator.compare(path, best) < 0) best = path; } -- profiler.pop(); -+ //profiler.pop(); // Purpur +- profilerFiller.pop(); ++ //profilerFiller.pop(); // Purpur return best; // Paper end - Perf: remove streams and optimize collection } 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 { @@ -19383,10 +18778,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) -> { @@ -19396,10 +18791,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 6794466051dd4b725d579b2136c37844995a648e..769d283cd98cba829262e45020ce3936c484938a 100644 +index ae321b3b8d98e42ef07fd1f0f738c1a2b428f6db..26da9e7c25ef6a89482838010d8ed6bcf8c87511 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 @@ -19408,15 +18803,15 @@ index 6794466051dd4b725d579b2136c37844995a648e..769d283cd98cba829262e45020ce3936 // 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 @@ -19424,10 +18819,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); } @@ -19439,19 +18834,19 @@ index 29123f3a2f211c08d1a9ccf62ca9bc9822f90111..db78616676ba021ee0f03cfea932f291 + // Purpur } diff --git a/src/main/java/net/minecraft/world/ticks/LevelTicks.java b/src/main/java/net/minecraft/world/ticks/LevelTicks.java -index 7a69564572357a7acc043e35b9c113beeb738951..a6d62abd3102770652f914b9d697c6d3c2533cfc 100644 +index 778e6476c86d823dc8efe603a95e589e8b2ea9d9..452fb3442221fd66debfe1e1d6e85ee17951e556 100644 --- a/src/main/java/net/minecraft/world/ticks/LevelTicks.java +++ b/src/main/java/net/minecraft/world/ticks/LevelTicks.java -@@ -81,20 +81,20 @@ public class LevelTicks implements LevelTickAccess { +@@ -79,20 +79,20 @@ public class LevelTicks implements LevelTickAccess { } public void tick(long time, int maxTicks, BiConsumer ticker) { -- ProfilerFiller profilerFiller = this.profiler.get(); +- ProfilerFiller profilerFiller = Profiler.get(); - profilerFiller.push("collect"); - this.collectTicks(time, maxTicks, profilerFiller); - profilerFiller.popPush("run"); - profilerFiller.incrementCounter("ticksToRun", this.toRunThisTick.size()); -+ //ProfilerFiller profilerFiller = this.profiler.get(); // Purpur ++ //ProfilerFiller profilerFiller = Profiler.get(); // Purpur + //profilerFiller.push("collect"); // Purpur + this.collectTicks(time, maxTicks, null); // Purpur + //profilerFiller.popPush("run"); // Purpur @@ -19710,10 +19105,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 c7df339aeb62ee627edaf1bb4c8474b61e357ba6..8854e3adca98214697fdfa7f1296e2d66b5afa48 100644 +index 9f9eefc7346838a9effcda861cecd098092efb0f..e7a4e019ce26b8fd21481e52356ee38130cbeeea 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -411,6 +411,20 @@ public final class CraftServer implements Server { +@@ -414,6 +414,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 @@ -19734,15 +19129,15 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..8854e3adca98214697fdfa7f1296e2d6 CraftRegistry.setMinecraftRegistry(console.registryAccess()); -@@ -1072,6 +1086,7 @@ public final class CraftServer implements Server { +@@ -1074,6 +1088,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); + 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)) -@@ -1087,6 +1102,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)) +@@ -1089,6 +1104,7 @@ public final class CraftServer implements Server { } } world.spigotConfig.init(); // Spigot @@ -19750,7 +19145,7 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..8854e3adca98214697fdfa7f1296e2d6 } Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper -@@ -1104,6 +1120,7 @@ public final class CraftServer implements Server { +@@ -1106,6 +1122,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 @@ -19758,7 +19153,7 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..8854e3adca98214697fdfa7f1296e2d6 this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); -@@ -1610,6 +1627,55 @@ public final class CraftServer implements Server { +@@ -1614,6 +1631,58 @@ public final class CraftServer implements Server { return true; } @@ -19766,12 +19161,15 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..8854e3adca98214697fdfa7f1296e2d6 + @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 @@ -19814,7 +19212,7 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..8854e3adca98214697fdfa7f1296e2d6 @Override public List getRecipesFor(ItemStack result) { Preconditions.checkArgument(result != null, "ItemStack cannot be null"); -@@ -2990,6 +3056,18 @@ public final class CraftServer implements Server { +@@ -3009,6 +3078,18 @@ public final class CraftServer implements Server { return CraftServer.this.console.paperConfigurations.createLegacyObject(CraftServer.this.console); } @@ -19833,7 +19231,7 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..8854e3adca98214697fdfa7f1296e2d6 @Override public void restart() { org.spigotmc.RestartCommand.restart(); -@@ -3019,6 +3097,7 @@ public final class CraftServer implements Server { +@@ -3038,6 +3119,7 @@ public final class CraftServer implements Server { @Override public double[] getTPS() { return new double[] { @@ -19841,7 +19239,7 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..8854e3adca98214697fdfa7f1296e2d6 net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(), net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(), net.minecraft.server.MinecraftServer.getServer().tps15.getAverage() -@@ -3217,4 +3296,16 @@ public final class CraftServer implements Server { +@@ -3236,4 +3318,16 @@ public final class CraftServer implements Server { return this.potionBrewer; } // Paper end @@ -19859,10 +19257,10 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..8854e3adca98214697fdfa7f1296e2d6 + // Purpur end } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index e76186d580a2d7f1a83af4600b0bdd435b67eba3..0921894dbc0d81b943827ecda6e6befdbfd715f5 100644 +index d41c81158c00931e6b11093cce141f6a3085ba05..ea1b4f0073f775fdd18eb080886d60c71a08ab2c 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 { +@@ -2399,6 +2399,48 @@ public class CraftWorld extends CraftRegionAccessor implements World { return (this.getHandle().getDragonFight() == null) ? null : new CraftDragonBattle(this.getHandle().getDragonFight()); } @@ -19912,10 +19310,10 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..0921894dbc0d81b943827ecda6e6befd 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 b3ba6bccdbb08af27916f0c611c60b2595b90164..068aa459b4d1dfbbbd80dc0ae5c43b8202474477 100644 +index a7524d3853d5b67b6385d2b74832b9267503dfe6..b2d60b214b58d9a5fadf3629e5ebc358c904d1c6 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -176,6 +176,20 @@ public class Main { +@@ -176,6 +176,14 @@ public class Main { .describedAs("Jar file"); // Paper end @@ -19925,18 +19323,12 @@ index b3ba6bccdbb08af27916f0c611c60b2595b90164..068aa459b4d1dfbbbd80dc0ae5c43b82 + .ofType(File.class) + .defaultsTo(new File("purpur.yml")) + .describedAs("Yml file"); -+ -+ acceptsAll(asList("pufferfish", "pufferfish-settings"), "File for pufferfish settings") -+ .withRequiredArg() -+ .ofType(File.class) -+ .defaultsTo(new File("pufferfish.yml")) -+ .describedAs("Yml file"); + // Purpur end + // Paper start acceptsAll(asList("server-name"), "Name of the server") .withRequiredArg() -@@ -259,7 +273,7 @@ public class Main { +@@ -259,7 +267,7 @@ public class Main { System.setProperty(net.minecrell.terminalconsole.TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper } @@ -20090,10 +19482,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 179886dcbda29c5cdb7dbd43e44951ae38d9df96..cc7d5aeb2044019aabad93dd79a16178c7483037 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()); } @@ -20117,7 +19509,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()) { @@ -20125,7 +19517,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..770606c4462d85d116f6d0bf91192dc4 return false; } -@@ -1310,4 +1328,27 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1311,4 +1329,27 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } } // Paper end - broadcast hurt animation @@ -20154,7 +19546,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 4312290ad970f71e1dc25b707ab312c597a481a9..e0cbf2e2c17c87af23495e6365ff9378f7c861da 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 { @@ -20244,10 +19636,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; @@ -20256,7 +19648,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 @@ -20295,10 +19687,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 550e175c7fec97818644933a4e4f7805e54d7d5f..9db85096974bd16140b8f58bacb0a2b79d9edd89 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) { @@ -20315,7 +19707,7 @@ index 42d7660efe5baa6f796f2a7606686c765b6f2478..173e4a075078af67f030750c9a6294ab if (this.getHandle().connection == null) return; // Paper - Updates are possible before the player has fully joined for (ServerPlayer player : (List) this.server.getHandle().players) { if (player.getBukkitEntity().canSee(this)) { -@@ -1435,6 +1440,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1453,6 +1458,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper start - Teleport passenger API // Don't allow teleporting between worlds while keeping passengers if (ignorePassengers && entity.isVehicle() && location.getWorld() != this.getWorld()) { @@ -20323,7 +19715,7 @@ index 42d7660efe5baa6f796f2a7606686c765b6f2478..173e4a075078af67f030750c9a6294ab return false; } -@@ -1456,6 +1462,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1474,6 +1480,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } if (entity.isVehicle() && !ignorePassengers) { // Paper - Teleport API @@ -20331,7 +19723,7 @@ index 42d7660efe5baa6f796f2a7606686c765b6f2478..173e4a075078af67f030750c9a6294ab return false; } -@@ -2757,6 +2764,28 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2787,6 +2794,28 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this.getHandle().getAbilities().walkingSpeed * 2f; } @@ -20360,7 +19752,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 { +@@ -3598,4 +3627,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 @@ -20454,10 +19846,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 @@ -20492,7 +19884,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 { @@ -20513,10 +19905,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 1e98f68e51618606f1178c12be77c1a945362630..1a6e4455783fd47a3562e89565d92ed7a8da817d 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); @@ -20532,7 +19924,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; @@ -20541,7 +19933,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); @@ -20645,10 +20037,10 @@ 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 756c73a401437566258813946fa10c7caa8f2469..2b6f9fce59178525b1211f2133645a7991a146dd 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 { +@@ -526,4 +526,285 @@ public final class CraftItemStack extends ItemStack { return this.pdcView; } // Paper end - pdc @@ -20934,18 +20326,6 @@ 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 ---- 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 { - } 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.predicate = ((RecipeChoice.ExactChoice) bukkit).getPredicate(); // Purpur - // Paper start - support "empty" choices - } else if (bukkit == RecipeChoice.empty()) { - stack = Ingredient.EMPTY; 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 @@ -20978,7 +20358,7 @@ index f86c95a13dff012de5db3e41ac261e9e8d44d9f3..1db0b790d824e419bb5fb6ab1f3003e1 + // Purpur end - Anvil API } diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java -index fa599f9533fbc18608d8d1d00dddd7ac2ecc4e31..1fef28f7ba02a13669e783bc73cd236a32f4c995 100644 +index 51ae8eddadc87b143b93521a3cef374f1e3a24dc..a7b45602d9d86aec235eef06d252fb6225f17f6e 100644 --- a/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java +++ b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java @@ -265,6 +265,7 @@ public final class CraftLegacy { @@ -21042,113 +20422,40 @@ index 0cbbd915631904fe8c6effefb92895422b33eff6..aef19cfbecb4ddfc8dc71c4f3b2a0113 + // Purpur - end } diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 2f4d6b56301195f8d39ed50dffe842464065bfe1..48999a860a3b9ed691691c355beaf3e0674acb95 100644 +index 6fef86e47e37eab6721cfd67d494afb25a2ded68..c914e1e13c4f64f24efa5f825e58efb69632bfa6 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 Paper"); // Paper + task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Purpur"); // Paper // Purpur // 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) } -@@ -504,10 +504,10 @@ public class CraftScheduler implements BukkitScheduler { - this.runners.remove(task.getTaskId()); - } - } -- MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); // Paper -+ //MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); // Paper // Purpur - this.pending.addAll(temp); - temp.clear(); -- MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper -+ //MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper // Purpur - //this.debugHead = this.debugHead.getNextHead(currentTick); // Paper - } - -@@ -550,7 +550,7 @@ public class CraftScheduler implements BukkitScheduler { - } - - void parsePending() { // Paper -- if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper -+ //if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper // Purpur - CraftTask head = this.head; - CraftTask task = head.getNext(); - CraftTask lastTask = head; -@@ -569,7 +569,7 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -- if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper -+ //if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper // Purpur - } - - private boolean isReady(final int currentTick) { -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index ba369f3dcfdf498e971dc4405d39657a9b6e97cc..8f181e03eda734b18f8c9ee80ee6e45f8689d178 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -@@ -81,13 +81,13 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - - @Override - public void run() { -- try (Timing ignored = timings.startTiming()) { // Paper -+ //try (Timing ignored = timings.startTiming()) { // Paper // Purpur - if (this.rTask != null) { - this.rTask.run(); - } else { - this.cTask.accept(this); - } -- } // Paper -+ //} // Paper // Purpur - } - - long getCreatedAt() { -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -index b3e1adeb932da9b3bed16acd94e2f16da48a7c72..d3ec817e95628f1fc8be4a29c9a0f13c7d5fd552 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -@@ -115,7 +115,7 @@ public final class CraftScoreboardManager implements ScoreboardManager { - public void forAllObjectives(ObjectiveCriteria criteria, ScoreHolder holder, Consumer consumer) { - // Paper start - add timings for scoreboard search - // plugins leaking scoreboards will make this very expensive, let server owners debug it easily -- co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.startTimingIfSync(); -+ //co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.startTimingIfSync(); // Purpur - try { - // Paper end - add timings for scoreboard search - for (CraftScoreboard scoreboard : this.scoreboards) { -@@ -123,7 +123,7 @@ public final class CraftScoreboardManager implements ScoreboardManager { - board.forAllObjectives(criteria, holder, (score) -> consumer.accept(score)); - } - } finally { // Paper start - add timings for scoreboard search -- co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.stopTimingIfSync(); -+ //co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.stopTimingIfSync(); // Purpur - } - // Paper end - add timings for scoreboard search - } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 8fa2b2a67891d34ec95f7eed2a4118ddd8a5be15..5505c13d0e602f39fe02dde350082c11a2f2a2e0 100644 +index 05a62b2cf9ca8e0141274bd7f44ef8fb703466d1..fcb5bc76955edd773488dd3e476ea5e6fd09ca9b 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 { - +@@ -494,7 +494,7 @@ public final class CraftMagicNumbers implements UnsafeValues { + // Paper start @Override public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -- return new gg.pufferfish.pufferfish.PufferfishVersionFetcher(); // Pufferfish +- return new com.destroystokyo.paper.PaperVersionFetcher(); + return new com.destroystokyo.paper.PaperVersionFetcher(); // Pufferfish // Purpur } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 80553face9c70c2a3d897681e7761df85b22d464..99597258e8e88cd9e2c901c4ac3ff7faeeabee2b 100644 +index 774556a62eb240da42e84db4502e2ed43495be17..99597258e8e88cd9e2c901c4ac3ff7faeeabee2b 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java @@ -11,7 +11,7 @@ public final class Versioning { public static String getBukkitVersion() { String result = "Unknown-Version"; -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/gg.pufferfish.pufferfish/pufferfish-api/pom.properties"); // Pufferfish +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/io.papermc.paper/paper-api/pom.properties"); + InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.purpurmc.purpur/purpur-api/pom.properties"); // Pufferfish // Purpur Properties properties = new Properties(); @@ -21176,10 +20483,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..546d920198acc2a7aea6e251a34d92d33cbaaee7 +index 0000000000000000000000000000000000000000..95cd1156766895546ef5574b33a60806bff08fa2 --- /dev/null +++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java -@@ -0,0 +1,607 @@ +@@ -0,0 +1,606 @@ +package org.purpurmc.purpur; + +import com.google.common.base.Throwables; @@ -21201,6 +20508,7 @@ index 0000000000000000000000000000000000000000..546d920198acc2a7aea6e251a34d92d3 +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; @@ -21264,7 +20572,7 @@ index 0000000000000000000000000000000000000000..546d920198acc2a7aea6e251a34d92d3 + + readConfig(PurpurConfig.class, null); + -+ Blocks.rebuildCache(); ++ Block.BLOCK_STATE_REGISTRY.forEach(BlockBehaviour.BlockStateBase::initCache); + } + + protected static void log(String s) { @@ -21569,8 +20877,8 @@ index 0000000000000000000000000000000000000000..546d920198acc2a7aea6e251a34d92d3 + 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); + }); @@ -21604,7 +20912,6 @@ index 0000000000000000000000000000000000000000..546d920198acc2a7aea6e251a34d92d3 + 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; @@ -21629,7 +20936,6 @@ index 0000000000000000000000000000000000000000..546d920198acc2a7aea6e251a34d92d3 + } + 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); @@ -21706,7 +21012,7 @@ index 0000000000000000000000000000000000000000..546d920198acc2a7aea6e251a34d92d3 + + 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; @@ -21738,7 +21044,7 @@ index 0000000000000000000000000000000000000000..546d920198acc2a7aea6e251a34d92d3 + 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; @@ -21789,10 +21095,10 @@ index 0000000000000000000000000000000000000000..546d920198acc2a7aea6e251a34d92d3 +} 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..3bcbf5e2dbb991a8416d827ddfe59e04f701ebf7 +index 0000000000000000000000000000000000000000..742a46ef95a5e46e9c338cedcecaf008a7108c58 --- /dev/null +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -@@ -0,0 +1,3423 @@ +@@ -0,0 +1,3419 @@ +package org.purpurmc.purpur; + +import net.minecraft.core.registries.BuiltInRegistries; @@ -21919,28 +21225,27 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + public boolean boatEjectPlayersOnLand = false; + public boolean boatsDoFallDamage = false; + public boolean disableDropsOnCrammingDeath = false; ++ 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); @@ -21948,15 +21253,23 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); ++ 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); @@ -21965,17 +21278,8 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + } + 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); + } + @@ -22052,7 +21356,7 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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(); @@ -22061,7 +21365,7 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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(); @@ -22070,7 +21374,7 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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(); @@ -22079,7 +21383,7 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); @@ -22150,7 +21454,7 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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)); + } @@ -22291,7 +21595,7 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + "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); + }); + } @@ -22427,17 +21731,17 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); + }); @@ -22481,17 +21785,17 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); + }); @@ -22526,17 +21830,17 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); + }); @@ -22549,20 +21853,20 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); + }); @@ -22576,17 +21880,17 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); + }); @@ -22711,7 +22015,7 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); + } @@ -23429,7 +22733,6 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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; @@ -23454,7 +22757,6 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); @@ -24203,7 +23505,7 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); @@ -24295,7 +23597,7 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); + } @@ -25190,7 +24492,7 @@ index 0000000000000000000000000000000000000000..3bcbf5e2dbb991a8416d827ddfe59e04 + 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); + } @@ -26209,10 +25511,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; @@ -26310,13 +25612,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); ++ } + } + } + } @@ -26324,14 +25630,18 @@ index 0000000000000000000000000000000000000000..75e31aee6e706f042398444f272888f9 + + @Override + protected void onHitBlock(BlockHitResult blockHitResult) { -+ if (this.hitCancelled) { -+ return; ++ 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); + } -+ if (this.canGrief) { -+ BlockState state = this.level().getBlockState(blockHitResult.getBlockPos()); -+ state.onProjectileHit(this.level(), state, blockHitResult, this); -+ } -+ 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 @@ -26770,7 +26080,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 @@ @@ -26780,13 +26090,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); + } @@ -27773,19 +27083,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 1461daa08c5b671b8556f29f90400b7e98285a44..ed1cdea66dd117ecafd14a52727f094430f39b60 100644 +index 6ffe86aa887ebf96f21114a468e16376c2449911..813b8aeb7bf39e03346fd9ca63c4c6498e162965 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -171,7 +171,7 @@ public class ActivationRange - */ - public static void activateEntities(Level world) - { -- MinecraftTimings.entityActivationCheckTimer.startTiming(); -+ //MinecraftTimings.entityActivationCheckTimer.startTiming(); // Purpur - final int miscActivationRange = world.spigotConfig.miscActivationRange; - final int raiderActivationRange = world.spigotConfig.raiderActivationRange; - final int animalActivationRange = world.spigotConfig.animalActivationRange; -@@ -205,6 +205,8 @@ public class ActivationRange +@@ -198,6 +198,8 @@ public class ActivationRange continue; } @@ -27794,16 +27095,7 @@ index 1461daa08c5b671b8556f29f90400b7e98285a44..ed1cdea66dd117ecafd14a52727f0944 // Paper start int worldHeight = world.getHeight(); ActivationRange.maxBB = player.getBoundingBox().inflate( maxRange, worldHeight, maxRange ); -@@ -249,7 +251,7 @@ public class ActivationRange - } - // Paper end - } -- MinecraftTimings.entityActivationCheckTimer.stopTiming(); -+ //MinecraftTimings.entityActivationCheckTimer.stopTiming(); // Purpur - } - - /** -@@ -402,6 +404,7 @@ public class ActivationRange +@@ -375,6 +377,7 @@ public class ActivationRange */ public static boolean checkIfActive(Entity entity) { diff --git a/patches/server/0003-Build-System-Changes.patch b/patches/server/0002-Build-System-Changes.patch similarity index 90% rename from patches/server/0003-Build-System-Changes.patch rename to patches/server/0002-Build-System-Changes.patch index fe5f1e4..b2f5e6d 100644 --- a/patches/server/0003-Build-System-Changes.patch +++ b/patches/server/0002-Build-System-Changes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Build System Changes diff --git a/build.gradle.kts b/build.gradle.kts -index 535b0c6a750cc77fb9340d6e080932f3eb3bde17..3bb91f4d0447fc283c56ffab24cb8e203925ebad 100644 +index ccb31eb5993db028d0cbf104261205c9462f8734..44ebd149b18cf002cb9ffc9073c95ab1bd9bd356 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -13,70 +13,29 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { +@@ -13,63 +13,29 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { val alsoShade: Configuration by configurations.creating dependencies { @@ -33,8 +33,8 @@ index 535b0c6a750cc77fb9340d6e080932f3eb3bde17..3bb91f4d0447fc283c56ffab24cb8e20 - implementation("org.ow2.asm:asm-commons:9.7.1") - implementation("org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT") // Paper - config files - implementation("commons-lang:commons-lang:2.6") -- runtimeOnly("org.xerial:sqlite-jdbc:3.46.0.0") -- runtimeOnly("com.mysql:mysql-connector-j:8.4.0") +- runtimeOnly("org.xerial:sqlite-jdbc:3.46.1.3") +- runtimeOnly("com.mysql:mysql-connector-j:9.1.0") - runtimeOnly("com.lmax:disruptor:3.4.4") // Paper - // Paper start - Use Velocity cipher - implementation("com.velocitypowered:velocity-native:3.3.0-SNAPSHOT") { @@ -46,13 +46,6 @@ index 535b0c6a750cc77fb9340d6e080932f3eb3bde17..3bb91f4d0447fc283c56ffab24cb8e20 - runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") - runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18") - -- // Pufferfish start -- implementation("org.yaml:snakeyaml:1.32") -- implementation ("com.github.carleslc.Simple-YAML:Simple-Yaml:1.8.4") { // Purpur -- exclude(group="org.yaml", module="snakeyaml") -- } -- // Pufferfish end -- - implementation("org.mozilla:rhino-runtime:1.7.14") // Purpur - implementation("org.mozilla:rhino-engine:1.7.14") // Purpur - implementation("dev.omega24:upnp4j:1.0") // Purpur @@ -89,8 +82,8 @@ index 535b0c6a750cc77fb9340d6e080932f3eb3bde17..3bb91f4d0447fc283c56ffab24cb8e20 + implementation(server.bundles.implementation) + + log4jPlugins.annotationProcessorConfigurationName(common.log4j.core) -+ alsoShade(log4jPlugins.output) // Plazma - Diff on patch -+ runtimeOnly(log4jPlugins.output) // Plazma - Diff on patch ++ alsoShade(log4jPlugins.output) // diff on changes ++ runtimeOnly(log4jPlugins.output) // diff on changes + + runtimeOnly(common.maven.provider) + runtimeOnly(common.bundles.maven) @@ -102,7 +95,7 @@ index 535b0c6a750cc77fb9340d6e080932f3eb3bde17..3bb91f4d0447fc283c56ffab24cb8e20 } paperweight { -@@ -104,14 +63,14 @@ tasks.jar { +@@ -89,14 +55,14 @@ tasks.jar { val gitBranch = git("rev-parse", "--abbrev-ref", "HEAD").getText().trim() // Paper attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", diff --git a/patches/server/0004-Fork-friendly-Rebranding.patch b/patches/server/0003-Fork-friendly-Rebranding.patch similarity index 95% rename from patches/server/0004-Fork-friendly-Rebranding.patch rename to patches/server/0003-Fork-friendly-Rebranding.patch index 1607b4c..e8335f3 100644 --- a/patches/server/0004-Fork-friendly-Rebranding.patch +++ b/patches/server/0003-Fork-friendly-Rebranding.patch @@ -127,21 +127,20 @@ index 0000000000000000000000000000000000000000..3af005ce2bbd30601917987d8c831db2 + +} diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java -index 3099c21ee589acf6edff5903a23673adf489024f..a337e2c9576fb70a8ee9082e9b69719c804b286e 100644 +index a6e5950b5875cafd734300cdfbf58f5d3736f3c8..a337e2c9576fb70a8ee9082e9b69719c804b286e 100644 --- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java +++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java -@@ -30,10 +30,6 @@ public record ServerBuildInfoImpl( +@@ -30,9 +30,6 @@ public record ServerBuildInfoImpl( private static final String ATTRIBUTE_GIT_BRANCH = "Git-Branch"; private static final String ATTRIBUTE_GIT_COMMIT = "Git-Commit"; - private static final String BRAND_PAPER_NAME = "Paper"; -- private static final String BRAND_PUFFERFISH_NAME = "Pufferfish"; // Purpur - private static final String BRAND_PURPUR_NAME = "Purpur"; // Purpur - private static final String BUILD_DEV = "DEV"; public ServerBuildInfoImpl() { -@@ -44,9 +40,9 @@ public record ServerBuildInfoImpl( +@@ -43,9 +40,9 @@ public record ServerBuildInfoImpl( this( getManifestAttribute(manifest, ATTRIBUTE_BRAND_ID) .map(Key::key) @@ -153,11 +152,11 @@ index 3099c21ee589acf6edff5903a23673adf489024f..a337e2c9576fb70a8ee9082e9b69719c SharedConstants.getCurrentVersion().getId(), SharedConstants.getCurrentVersion().getName(), getManifestAttribute(manifest, ATTRIBUTE_BUILD_NUMBER) -@@ -63,7 +59,7 @@ public record ServerBuildInfoImpl( +@@ -62,7 +59,7 @@ public record ServerBuildInfoImpl( @Override public boolean isBrandCompatible(final @NotNull Key brandId) { -- return brandId.equals(this.brandId) || brandId.equals(BRAND_PAPER_ID) || brandId.equals(BRAND_PUFFERFISH_ID); // Purpur +- return brandId.equals(this.brandId) || brandId.equals(BRAND_PAPER_ID); // Purpur + return brandId.equals(this.brandId) || SUPPORTED_BRANDS.contains(brandId); // Purpur // Plazma - Fork-friendly Rebranding } @@ -198,7 +197,7 @@ index 710477ae27ebc5afdf0012ef0867d05efd293c24..3a5e7546c5cc1fcec880cece3f0d0b04 public String getTitle() { diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index aad2cdf4c2237caf2c99695d0cbb01f56c0074e2..e9842bf7e43a4fdfc4a23d6ee13d56a8cf4fb77a 100644 +index f0d762bd140fad27ae73bcf3e61b640b9e3f2592..3a9f7143505ba1a70bcd224ee8fef5c844a94ed1 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java @@ -108,6 +108,11 @@ public class Main { @@ -214,10 +213,10 @@ index aad2cdf4c2237caf2c99695d0cbb01f56c0074e2..e9842bf7e43a4fdfc4a23d6ee13d56a8 Path path = (Path) optionset.valueOf("pidFile"); // CraftBukkit diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d78cb68c3a53b277aa26186062efc716c8f80f36..e36b9964569c8476ca25386c783fb8323f637476 100644 +index 6acffd0d74f35ea9ec7e9937b65c3fc81c7769e5..e11c65bd47875d6c7a4e9927cd772afeb0e51da9 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1259,7 +1259,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.server.getQueryPlugins()) { diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index 9ebe1f1797b5be562bc4f6d92b9a4d6022ca2151..e0a09827db002b87e738091d820f05a9a97f3edb 100644 +index b97d8f43f24baf36eca9064b2b48bf6c092f848c..9dce68d9d3f5dc0bb3cc7c11859d3082b73347cb 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -56,12 +56,12 @@ public class DedicatedServerProperties extends Settings minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig, minecraftserver.registryAccess(), iworlddataserver.getGameRules())), executor); // Paper - create paper world configs; Async-Anti-Xray: Pass executor + // Add env and gen to constructor, IWorldDataServer -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { +- super(iworlddataserver, resourcekey, minecraftserver.registryAccess(), worlddimension.type(), false, flag, i, minecraftserver.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> minecraftserver.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(convertable_conversionsession.levelDirectory.path(), iworlddataserver.getLevelName(), resourcekey.location(), spigotConfig, minecraftserver.registryAccess(), iworlddataserver.getGameRules())), executor); // Paper - create paper world configs; Async-Anti-Xray: Pass executor + // Plazma start - Configurable Plazma + super( + iworlddataserver, + resourcekey, + minecraftserver.registryAccess(), + worlddimension.type(), -+ minecraftserver::getProfiler, + false, + flag, + i, @@ -657,34 +656,34 @@ index 067b10134b087626e05596225744b905211e8b63..dfcd3989ffbd4aa5dc9368a34b95c1c2 this.convertable = convertable_conversionsession; this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 5057d9d433ba002a22d22adfaf7323b2cfaee9af..253d47418b4e9cbce74584c2461d12e17effd7bb 100644 +index 7493262c2879af196e5585b15faad69ae42764e3..ad15fc9f329f5ea7fa0d0d88c937b2f36e0f2f3d 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -171,6 +171,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -172,7 +172,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl return this.paperConfig; } // Paper end - add paper world config +- + // Plazma start - Configurable Plazma + private final org.plazmamc.plazma.configurations.WorldConfigurations plazmaConfig; + public org.plazmamc.plazma.configurations.WorldConfigurations plazmaConfig() { + return this.plazmaConfig; + } + // Plazma end - Configurable Plazma - public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray public final org.purpurmc.purpur.PurpurWorldConfig purpurConfig; // Purpur -@@ -728,9 +734,28 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + public static BlockPos lastPhysicsProblem; // Spigot +@@ -874,7 +879,24 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } // Paper end - optimise random ticking -- protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config & Anti-Xray +- protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config & Anti-Xray + // Plazma start - Configurable Plazma + protected Level( + WritableLevelData worlddatamutable, + ResourceKey resourcekey, + RegistryAccess iregistrycustom, + Holder holder, -+ Supplier supplier, + boolean flag, + boolean flag1, + long i, @@ -697,6 +696,11 @@ index 5057d9d433ba002a22d22adfaf7323b2cfaee9af..253d47418b4e9cbce74584c2461d12e1 + java.util.concurrent.Executor executor + ) { + // Plazma end - Configurable Plazma + // Paper start - getblock optimisations - cache world height/sections + final DimensionType dimType = holder.value(); + this.minY = dimType.minY(); +@@ -886,6 +908,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + // Paper end - getblock optimisations - cache world height/sections 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.plazmaConfig = plazmaWorldConfigurationCreator.apply(this.spigotConfig); // Plazma - Configurable Plazma @@ -704,10 +708,10 @@ index 5057d9d433ba002a22d22adfaf7323b2cfaee9af..253d47418b4e9cbce74584c2461d12e1 this.playerBreedingCooldowns = this.getNewBreedingCooldownCache(); // Purpur this.generator = gen; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 8854e3adca98214697fdfa7f1296e2d66b5afa48..0bd9f4dc28bb67def4af402f88b05a257262c0a4 100644 +index e7a4e019ce26b8fd21481e52356ee38130cbeeea..66e2dff21c1aedd7de707077b7cb420e82127f91 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1086,6 +1086,7 @@ public final class CraftServer implements Server { +@@ -1088,6 +1088,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); @@ -715,7 +719,7 @@ index 8854e3adca98214697fdfa7f1296e2d66b5afa48..0bd9f4dc28bb67def4af402f88b05a25 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 -@@ -3068,6 +3069,13 @@ public final class CraftServer implements Server { +@@ -3090,6 +3091,13 @@ public final class CraftServer implements Server { } // Purpur end @@ -730,10 +734,10 @@ index 8854e3adca98214697fdfa7f1296e2d66b5afa48..0bd9f4dc28bb67def4af402f88b05a25 public void restart() { org.spigotmc.RestartCommand.restart(); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 8d67bf7aaed07a3438f29347bd3b1fd6c9efac2e..f12a0a44c31de3983f207678bbd7fe232e13e14c 100644 +index f9ee08eae4a1e1c6490e4682901609c0e4d52579..a1b7bacf43d68aee60b3f5a7fd3b077ee0fcb354 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -197,6 +197,14 @@ public class Main { +@@ -191,6 +191,14 @@ public class Main { .defaultsTo("A " + io.papermc.paper.ServerBrandConstants.BRAND_NAME + " Server") // Plazma - Fork-friendly Rebranding .describedAs("Name"); // Paper end @@ -1316,7 +1320,7 @@ index 0000000000000000000000000000000000000000..f2d3d51cb4b8fc7a5fd6db1a63289fff + +} diff --git a/src/test/java/org/bukkit/support/DummyServerHelper.java b/src/test/java/org/bukkit/support/DummyServerHelper.java -index cb2b39c562f609375b9e5b20cb5899780995373d..272ccfb9bbbf526b596dcc367397e52e84223daf 100644 +index 309d371247adcddf0a1b370cc5faff3e6e01cb0f..285a90ff5cdc8cb28fafd4ea3dae306ae5b899c9 100644 --- a/src/test/java/org/bukkit/support/DummyServerHelper.java +++ b/src/test/java/org/bukkit/support/DummyServerHelper.java @@ -92,6 +92,7 @@ public final class DummyServerHelper { diff --git a/patches/server/0007-Setup-basic-configuration-sections.patch b/patches/server/0006-Setup-basic-configuration-sections.patch similarity index 100% rename from patches/server/0007-Setup-basic-configuration-sections.patch rename to patches/server/0006-Setup-basic-configuration-sections.patch diff --git a/patches/server/0008-Warn-on-startup.patch b/patches/server/0007-Warn-on-startup.patch similarity index 96% rename from patches/server/0008-Warn-on-startup.patch rename to patches/server/0007-Warn-on-startup.patch index de6dadb..4c17cc2 100644 --- a/patches/server/0008-Warn-on-startup.patch +++ b/patches/server/0007-Warn-on-startup.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Warn on startup diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index e9842bf7e43a4fdfc4a23d6ee13d56a8cf4fb77a..5aea9b3cc84bcfba940e13e8f680899f5df67856 100644 +index 3a9f7143505ba1a70bcd224ee8fef5c844a94ed1..e0885f53aa3d0ae95a40574806af70c865025a9d 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java @@ -113,6 +113,18 @@ public class Main { diff --git a/patches/server/0009-Always-agree-EULA-on-development-mode.patch b/patches/server/0008-Always-agree-EULA-on-development-mode.patch similarity index 89% rename from patches/server/0009-Always-agree-EULA-on-development-mode.patch rename to patches/server/0008-Always-agree-EULA-on-development-mode.patch index 6c59a16..1f80d38 100644 --- a/patches/server/0009-Always-agree-EULA-on-development-mode.patch +++ b/patches/server/0008-Always-agree-EULA-on-development-mode.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Always agree EULA on development mode diff --git a/build.gradle.kts b/build.gradle.kts -index 3bb91f4d0447fc283c56ffab24cb8e203925ebad..95df5b7c437f95849b193345640e6001aed71a3d 100644 +index 44ebd149b18cf002cb9ffc9073c95ab1bd9bd356..c45f40170cbdc03df31451d2c30a877f8d8f26af 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -141,7 +141,7 @@ fun TaskContainer.registerRunTask( +@@ -133,7 +133,7 @@ fun TaskContainer.registerRunTask( languageVersion.set(JavaLanguageVersion.of(21)) vendor.set(JvmVendorSpec.JETBRAINS) }) @@ -18,7 +18,7 @@ index 3bb91f4d0447fc283c56ffab24cb8e203925ebad..95df5b7c437f95849b193345640e6001 if (rootProject.childProjects["test-plugin"] != null) { val testPluginJar = rootProject.project(":test-plugin").tasks.jar.flatMap { it.archiveFile } diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 5aea9b3cc84bcfba940e13e8f680899f5df67856..2807a67ad42b35045ef9f607062403c376e0c4ef 100644 +index e0885f53aa3d0ae95a40574806af70c865025a9d..e9ba8ad80a66b8b0c99d214709222310758fcc65 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java @@ -179,6 +179,7 @@ public class Main { diff --git a/patches/server/0010-Add-more-metrics.patch b/patches/server/0009-Add-more-metrics.patch similarity index 98% rename from patches/server/0010-Add-more-metrics.patch rename to patches/server/0009-Add-more-metrics.patch index 06dfdf6..9c52df6 100644 --- a/patches/server/0010-Add-more-metrics.patch +++ b/patches/server/0009-Add-more-metrics.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add more metrics diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 81b204c03b3c9a997f00fd423daa963757cb0daf..67e299893b7e1a64ab2962d79c2434dad189eed5 100644 +index 8d5a52c5762c3d9b44dcdf00ae312e0bdc01fa1f..48d33d4131af90eee35c9553898a2ac7ec5e2b7e 100644 --- a/src/main/java/com/destroystokyo/paper/Metrics.java +++ b/src/main/java/com/destroystokyo/paper/Metrics.java @@ -636,38 +636,59 @@ public class Metrics { diff --git a/patches/server/0011-Optimize-default-configurations.patch b/patches/server/0010-Optimize-default-configurations.patch similarity index 85% rename from patches/server/0011-Optimize-default-configurations.patch rename to patches/server/0010-Optimize-default-configurations.patch index 4d85b05..4f2c3be 100644 --- a/patches/server/0011-Optimize-default-configurations.patch +++ b/patches/server/0010-Optimize-default-configurations.patch @@ -8,69 +8,11 @@ Subject: [PATCH] Optimize default configurations - AkiraDevelopment/SimplyMC - YouHaveTrouble/minecraft-exploits-and-how-to-fix-them -diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -index 8f1645573780d12bf29d441d31eab1b76cd9e70f..8e35f7fbe3629ab05c16f52d72a3cd7343cf835f 100644 ---- a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -+++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java -@@ -64,7 +64,7 @@ public class PufferfishConfig { - getString("info.version", "1.0"); - setComment("info", - "Pufferfish Configuration", -- "Check out Pufferfish Host for maximum performance server hosting: https://pufferfish.host", -+ // "Check out Pufferfish Host for maximum performance server hosting: https://pufferfish.host", // Plazma - Sponsorblock - "Join our Discord for support: https://discord.gg/reZw4vQV9H", - "Download new builds at https://ci.pufferfish.host/job/Pufferfish"); - -@@ -219,7 +219,7 @@ public class PufferfishConfig { - public static int maxProjectileLoadsPerTick; - public static int maxProjectileLoadsPerProjectile; - private static void projectileLoading() { -- maxProjectileLoadsPerTick = getInt("projectile.max-loads-per-tick", 10, "Controls how many chunks are allowed", "to be sync loaded by projectiles in a tick."); -+ maxProjectileLoadsPerTick = getInt("projectile.max-loads-per-tick", org.plazmamc.plazma.configurations.PlazmaConfigurations.optimize() ? 8 : 10, "Controls how many chunks are allowed", "to be sync loaded by projectiles in a tick."); // Plazma - Optimize default configurations - maxProjectileLoadsPerProjectile = getInt("projectile.max-loads-per-projectile", 10, "Controls how many chunks a projectile", "can load in its lifetime before it gets", "automatically removed."); - - setComment("projectile", "Optimizes projectile settings"); -@@ -233,12 +233,12 @@ public class PufferfishConfig { - public static int activationDistanceMod; - - private static void dynamicActivationOfBrains() throws IOException { -- dearEnabled = getBoolean("dab.enabled", "activation-range.enabled", false); // Purpur -+ dearEnabled = getBoolean("dab.enabled", "activation-range.enabled", org.plazmamc.plazma.configurations.PlazmaConfigurations.optimize()); // Purpur // Plazma - Optimize default configurations - startDistance = getInt("dab.start-distance", "activation-range.start-distance", 12, - "This value determines how far away an entity has to be", - "from the player to start being effected by DEAR."); - startDistanceSquared = startDistance * startDistance; -- maximumActivationPrio = getInt("dab.max-tick-freq", "activation-range.max-tick-freq", 20, -+ maximumActivationPrio = getInt("dab.max-tick-freq", "activation-range.max-tick-freq", org.plazmamc.plazma.configurations.PlazmaConfigurations.optimize() ? 7 : 8, // Plazma - Optimize default configurations - "This value defines how often in ticks, the furthest entity", - "will get their pathfinders and behaviors ticked. 20 = 1s"); - activationDistanceMod = getInt("dab.activation-dist-mod", "activation-range.activation-dist-mod", 8, -@@ -261,8 +261,18 @@ public class PufferfishConfig { - public static Map projectileTimeouts; - private static void projectileTimeouts() { - // Set some defaults -- getInt("entity_timeouts.SNOWBALL", -1); -- getInt("entity_timeouts.LLAMA_SPIT", -1); -+ // Plazma start - Optimize default configurations -+ if (org.plazmamc.plazma.configurations.PlazmaConfigurations.optimize()) { -+ getInt("entity_timeouts.ARROW", 200); -+ getInt("entity_timeouts.EGG", 200); -+ getInt("entity_timeouts.ENDER_PEARL", 200); -+ getInt("entity_timeouts.SNOWBALL", 200); -+ getInt("entity_timeouts.LLAMA_SPIT", 200); -+ } else { -+ getInt("entity_timeouts.SNOWBALL", -1); -+ getInt("entity_timeouts.LLAMA_SPIT", -1); -+ } -+ // Plazma end - Optimize default configurations - setComment("entity_timeouts", - "These values define a entity's maximum lifespan. If an", - "entity is in this list and it has survived for longer than", diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -index a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca..d417b773dec5f2c4a8e115864338612d8e4b9f6c 100644 +index cbd0f2c6636b8ae332f20a3cb763b06855dfe795..3b636760f32b9b5b277edb15782d6206567e012f 100644 --- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -@@ -172,7 +172,7 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -147,7 +147,7 @@ public class GlobalConfiguration extends ConfigurationPart { public class Watchdog extends ConfigurationPart { public int earlyWarningEvery = 5000; @@ -79,7 +21,7 @@ index a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca..d417b773dec5f2c4a8e115864338612d } public SpamLimiter spamLimiter; -@@ -214,7 +214,7 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -189,7 +189,7 @@ public class GlobalConfiguration extends ConfigurationPart { public Commands commands; public class Commands extends ConfigurationPart { @@ -88,7 +30,7 @@ index a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca..d417b773dec5f2c4a8e115864338612d public boolean fixTargetSelectorTagCompletion = true; public boolean timeCommandAffectsAllWorlds = false; } -@@ -263,7 +263,7 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -255,7 +255,7 @@ public class GlobalConfiguration extends ConfigurationPart { public BookSize bookSize; public class BookSize extends ConfigurationPart { @@ -97,7 +39,7 @@ index a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca..d417b773dec5f2c4a8e115864338612d public double totalMultiplier = 0.98D; // TODO this should probably be merged into the above inner class } public boolean resolveSelectorsInBooks = false; -@@ -274,7 +274,15 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -266,7 +266,15 @@ public class GlobalConfiguration extends ConfigurationPart { public class PacketLimiter extends ConfigurationPart { public Component kickMessage = Component.translatable("disconnect.exceeded_packet_rate", NamedTextColor.RED); public PacketLimit allPackets = new PacketLimit(7.0, 500.0, PacketLimit.ViolateAction.KICK); @@ -114,7 +56,7 @@ index a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca..d417b773dec5f2c4a8e115864338612d @ConfigSerializable public record PacketLimit(@Required double interval, @Required double maxPacketRate, ViolateAction action) { -@@ -342,7 +350,7 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -334,7 +342,7 @@ public class GlobalConfiguration extends ConfigurationPart { executor.setMaximumPoolSize(_chatExecutorMaxSize); } } @@ -124,7 +66,7 @@ index a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca..d417b773dec5f2c4a8e115864338612d public boolean loadPermissionsYmlBeforePlugins = true; @Constraints.Min(4) diff --git a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java -index c867796f625813797f167610ad443c4be5a7561e..ecced20724bc7f6136ff023ca37ae8368bec410b 100644 +index 1d18cad6c32815854ff8dace256b59022200c842..2de2d307ecd298c5205f40c0a4cc4d56c2495f62 100644 --- a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java @@ -100,12 +100,32 @@ public class WorldConfiguration extends ConfigurationPart { @@ -193,7 +135,7 @@ index c867796f625813797f167610ad443c4be5a7561e..ecced20724bc7f6136ff023ca37ae836 } } -@@ -155,14 +196,14 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -154,14 +195,14 @@ public class WorldConfiguration extends ConfigurationPart { public ArmorStands armorStands; public class ArmorStands extends ConfigurationPart { @@ -211,7 +153,7 @@ index c867796f625813797f167610ad443c4be5a7561e..ecced20724bc7f6136ff023ca37ae836 } public Sniffer sniffer; -@@ -407,7 +448,7 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -406,7 +447,7 @@ public class WorldConfiguration extends ConfigurationPart { public class Environment extends ConfigurationPart { public boolean disableThunder = false; public boolean disableIceAndSnow = false; @@ -220,7 +162,7 @@ index c867796f625813797f167610ad443c4be5a7561e..ecced20724bc7f6136ff023ca37ae836 public boolean disableExplosionKnockback = false; public boolean generateFlatBedrock = false; public FrostedIce frostedIce; -@@ -463,7 +504,7 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -462,7 +503,7 @@ public class WorldConfiguration extends ConfigurationPart { public Fixes fixes; public class Fixes extends ConfigurationPart { @@ -229,7 +171,7 @@ index c867796f625813797f167610ad443c4be5a7561e..ecced20724bc7f6136ff023ca37ae836 public boolean disableUnloadedChunkEnderpearlExploit = true; public boolean preventTntFromMovingInWater = false; public boolean splitOverstackedLoot = true; -@@ -491,9 +532,9 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -490,9 +531,9 @@ public class WorldConfiguration extends ConfigurationPart { public class Collisions extends ConfigurationPart { public boolean onlyPlayersCollide = false; public boolean allowVehicleCollisions = true; @@ -241,7 +183,7 @@ index c867796f625813797f167610ad443c4be5a7561e..ecced20724bc7f6136ff023ca37ae836 public boolean allowPlayerCrammingDamage = false; } -@@ -501,18 +542,41 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -500,18 +541,41 @@ public class WorldConfiguration extends ConfigurationPart { public class Chunks extends ConfigurationPart { public AutosavePeriod autoSaveInterval = AutosavePeriod.def(); @@ -291,7 +233,7 @@ index c867796f625813797f167610ad443c4be5a7561e..ecced20724bc7f6136ff023ca37ae836 }); public boolean flushRegionsOnSave = false; } -@@ -527,9 +591,9 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -526,9 +590,9 @@ public class WorldConfiguration extends ConfigurationPart { public TickRates tickRates; public class TickRates extends ConfigurationPart { @@ -303,7 +245,7 @@ index c867796f625813797f167610ad443c4be5a7561e..ecced20724bc7f6136ff023ca37ae836 public int wetFarmland = 1; public int dryFarmland = 1; public Table, String, Integer> sensor = Util.make(HashBasedTable.create(), table -> table.put(EntityType.VILLAGER, "secondarypoisensor", 40)); -@@ -563,9 +627,9 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -562,9 +626,9 @@ public class WorldConfiguration extends ConfigurationPart { public class Misc extends ConfigurationPart { public int lightQueueSize = 20; @@ -328,7 +270,7 @@ index 24763d3d270c29c95e0b3e85111145234f660a62..80ddc627e02e3c749e6b074afa93d357 } diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 2807a67ad42b35045ef9f607062403c376e0c4ef..7306b1fff556859ccb0a705621a1c7031ed52e29 100644 +index e9ba8ad80a66b8b0c99d214709222310758fcc65..3066d9a2f6b2fe677181d6a0204140a30aedfe6f 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java @@ -164,7 +164,7 @@ public class Main { @@ -341,7 +283,7 @@ index 2807a67ad42b35045ef9f607062403c376e0c4ef..7306b1fff556859ccb0a705621a1c703 File commandFile = (File) optionset.valueOf("commands-settings"); diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index e0a09827db002b87e738091d820f05a9a97f3edb..135476d68e4d9cb2d6a4cbe30e578e9e5fde90e0 100644 +index 9dce68d9d3f5dc0bb3cc7c11859d3082b73347cb..2182361a13e8f7fb12a4d65de6bca15cf9537701 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java @@ -132,14 +132,14 @@ public class DedicatedServerProperties extends Settings public diff --git a/patches/server/0014-Add-missing-purpur-configuration-options.patch b/patches/server/0013-Add-missing-purpur-configuration-options.patch similarity index 83% rename from patches/server/0014-Add-missing-purpur-configuration-options.patch rename to patches/server/0013-Add-missing-purpur-configuration-options.patch index 0b6820f..0273ed3 100644 --- a/patches/server/0014-Add-missing-purpur-configuration-options.patch +++ b/patches/server/0013-Add-missing-purpur-configuration-options.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add missing purpur configuration options 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 62c62fd26660d8405378340315042d7b95ac7046..771fe01b262e951f1350e4997f4cba1b35c79945 100644 +index f60961bd5fdf6d1417e458b92e311c1a0a62463d..026cd57df33476841ed3a8f9fdc4d17a77e037b0 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 -@@ -158,6 +158,18 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS +@@ -160,6 +160,18 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.allayMaxHealth); this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.allayScale); } @@ -28,10 +28,10 @@ index 62c62fd26660d8405378340315042d7b95ac7046..771fe01b262e951f1350e4997f4cba1b @Override 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 e88d6d691bb176e33afeb294d735dfb2cbac12ff..00803dcc2d990046013b8a175af20359883a15fe 100644 +index 56d97225a909fd55f0d8aec992d5b6d42687c948..39cdecc382a71ef643d382ac506249bbb8df3d34 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 -@@ -96,6 +96,18 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl +@@ -96,6 +96,18 @@ public class Camel extends AbstractHorse { public int getPurpurBreedTime() { return this.level().purpurConfig.camelBreedingTicks; } @@ -51,10 +51,10 @@ index e88d6d691bb176e33afeb294d735dfb2cbac12ff..00803dcc2d990046013b8a175af20359 @Override 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 4c861b18fbfbae3cb2f1e3563393cfcf4005591c..651f30b4fb02dc03fabad34b62d7d86fa0889754 100644 +index 501a12398c56fe0df4e76a3bbce0f98c6c5aa6cb..94ca735513901a180d42ac1cfd48d841142a6ef5 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 -@@ -160,6 +160,23 @@ public class Frog extends Animal implements VariantHolder> { +@@ -163,6 +163,23 @@ public class Frog extends Animal implements VariantHolder> { public float getJumpPower() { return (getRider() != null && isControllable()) ? level().purpurConfig.frogRidableJumpHeight * this.getBlockJumpFactor() : super.getJumpPower(); } @@ -79,7 +79,7 @@ index 4c861b18fbfbae3cb2f1e3563393cfcf4005591c..651f30b4fb02dc03fabad34b62d7d86f public int getPurpurBreedTime() { 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 5cd69dd546f42e80a3d3e3a674f65c2ac39f3af9..1abf23fb16391087d41d8a180a17e394dd1a7dd0 100644 +index 071d14cc6697587ec14f02c69c78df364e7d8a8f..cc5c172b2fccc5fc59337203ed2b6edb2abc0c22 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 @@ -93,6 +93,23 @@ public class Tadpole extends AbstractFish { @@ -107,10 +107,10 @@ index 5cd69dd546f42e80a3d3e3a674f65c2ac39f3af9..1abf23fb16391087d41d8a180a17e394 @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java b/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java -index b6f5281705ce4c7a755e3818cf6c4a2235a024f9..bc931f54d1087f2515b8185368ade3e8dd55a00d 100644 +index 3fb4f12095883ea4ec6e0d60e0600b9de6ed7be2..f853730cee4fad2f3a5711e38918c65dcb1dc038 100644 --- a/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java +++ b/src/main/java/net/minecraft/world/entity/animal/sniffer/Sniffer.java -@@ -120,6 +120,18 @@ public class Sniffer extends Animal { +@@ -116,6 +116,18 @@ public class Sniffer extends Animal { public int getPurpurBreedTime() { return this.level().purpurConfig.snifferBreedingTicks; } @@ -130,10 +130,10 @@ index b6f5281705ce4c7a755e3818cf6c4a2235a024f9..bc931f54d1087f2515b8185368ade3e8 @Override 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 8e24cd9ed03e2f11da6f4fb2dd58dd9b9e5d7a06..c0398f21cb2ecc9e07f01163a4432a603ff26f03 100644 +index 692261880d05daa75fc53dde31d0f2b95dc52746..9f542e4f0077a6abc89fdec1a4bf3e8f40203b2a 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 -@@ -148,6 +148,23 @@ public class Warden extends Monster implements VibrationSystem { +@@ -151,6 +151,23 @@ public class Warden extends Monster implements VibrationSystem { 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 } @@ -157,26 +157,20 @@ index 8e24cd9ed03e2f11da6f4fb2dd58dd9b9e5d7a06..c0398f21cb2ecc9e07f01163a4432a60 // Purpur end @Override -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/ChestBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/ChestBoat.java -index c14019a131c90c699b8a76bada82592b66f0fa89..8b9f78b3b0e00a859f3106fe383352863027f51e 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/ChestBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/ChestBoat.java -@@ -45,12 +45,12 @@ public class ChestBoat extends Boat implements HasCustomInventoryScreen, Contain +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractChestBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractChestBoat.java +index 1f4cc08e84a23213bb9786ea09ad77caeec2d336..f888f1dd2e3c228b0a370fe920b63d547bbba571 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractChestBoat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractChestBoat.java +@@ -46,7 +46,7 @@ public abstract class AbstractChestBoat extends AbstractBoat implements HasCusto - public ChestBoat(EntityType type, Level world) { - super(type, world); + public AbstractChestBoat(EntityType type, Level world, Supplier itemSupplier) { + super(type, world, itemSupplier); - this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); + this.itemStacks = NonNullList.withSize(org.purpurmc.purpur.PurpurConfig.chestBoatRows * 9, ItemStack.EMPTY); // Plazma - Add missing purpur configuration options } - public ChestBoat(Level world, double d0, double d1, double d2) { - super(EntityType.CHEST_BOAT, world); -- this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY); -+ this.itemStacks = NonNullList.withSize(org.purpurmc.purpur.PurpurConfig.chestBoatRows * 9, ItemStack.EMPTY); // Plazma - Add missing purpur configuration options - this.setPos(d0, d1, d2); - this.xo = d0; - this.yo = d1; -@@ -177,7 +177,7 @@ public class ChestBoat extends Boat implements HasCustomInventoryScreen, Contain + @Override +@@ -142,7 +142,7 @@ public abstract class AbstractChestBoat extends AbstractBoat implements HasCusto @Override public int getContainerSize() { @@ -186,10 +180,10 @@ index c14019a131c90c699b8a76bada82592b66f0fa89..8b9f78b3b0e00a859f3106fe38335286 @Override diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java -index 97fc4fb795fa2dc859b0ea02dc132b41300d56ed..cd8194b08457d38b942631e0e6450264615f9427 100644 +index 097f3c34d244b89e7dd9f8b6f2a3d8fdc67b36dc..3f4c94aada930e55dfe6a2dd6f3bfb51b2276b0d 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java -@@ -330,6 +330,7 @@ public class PurpurConfig { +@@ -331,6 +331,7 @@ public class PurpurConfig { } public static int barrelRows = 3; @@ -197,7 +191,7 @@ index 97fc4fb795fa2dc859b0ea02dc132b41300d56ed..cd8194b08457d38b942631e0e6450264 public static boolean enderChestSixRows = false; public static boolean enderChestPermissionRows = false; public static boolean cryingObsidianValidForPortalFrame = false; -@@ -372,6 +373,7 @@ public class PurpurConfig { +@@ -373,6 +374,7 @@ public class PurpurConfig { case 1 -> 9; default -> 27; }); @@ -206,10 +200,10 @@ index 97fc4fb795fa2dc859b0ea02dc132b41300d56ed..cd8194b08457d38b942631e0e6450264 org.bukkit.event.inventory.InventoryType.ENDER_CHEST.setDefaultSize(enderChestSixRows ? 54 : 27); enderChestPermissionRows = getBoolean("settings.blocks.ender_chest.use-permissions-for-rows", enderChestPermissionRows); diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index 1ff95cced54e8230eb5b4b4314f8f3716e264264..0318c4916a17e6ec721efbfc98835424568366d9 100644 +index 2198477c174f89fdaece5ffef8b40c8096a9c9a9..046af5afaf3e234fb7d14c4a9ae183cda8cb0b0c 100644 --- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -@@ -1135,7 +1135,13 @@ public class PurpurWorldConfig { +@@ -1133,7 +1133,13 @@ public class PurpurWorldConfig { public boolean allayControllable = true; public double allayMaxHealth = 20.0D; public double allayScale = 1.0D; @@ -223,7 +217,7 @@ index 1ff95cced54e8230eb5b4b4314f8f3716e264264..0318c4916a17e6ec721efbfc98835424 allayRidable = getBoolean("mobs.allay.ridable", allayRidable); allayRidableInWater = getBoolean("mobs.allay.ridable-in-water", allayRidableInWater); allayControllable = getBoolean("mobs.allay.controllable", allayControllable); -@@ -1290,7 +1296,13 @@ public class PurpurWorldConfig { +@@ -1288,7 +1294,13 @@ public class PurpurWorldConfig { public double camelMovementSpeedMin = 0.09D; public double camelMovementSpeedMax = 0.09D; public int camelBreedingTicks = 6000; @@ -237,7 +231,7 @@ index 1ff95cced54e8230eb5b4b4314f8f3716e264264..0318c4916a17e6ec721efbfc98835424 camelRidableInWater = getBoolean("mobs.camel.ridable-in-water", camelRidableInWater); camelMaxHealthMin = getDouble("mobs.camel.attributes.max_health.min", camelMaxHealthMin); camelMaxHealthMax = getDouble("mobs.camel.attributes.max_health.max", camelMaxHealthMax); -@@ -1744,7 +1756,15 @@ public class PurpurWorldConfig { +@@ -1740,7 +1752,15 @@ public class PurpurWorldConfig { public boolean frogControllable = true; public float frogRidableJumpHeight = 0.65F; public int frogBreedingTicks = 6000; @@ -253,7 +247,7 @@ index 1ff95cced54e8230eb5b4b4314f8f3716e264264..0318c4916a17e6ec721efbfc98835424 frogRidable = getBoolean("mobs.frog.ridable", frogRidable); frogRidableInWater = getBoolean("mobs.frog.ridable-in-water", frogRidableInWater); frogControllable = getBoolean("mobs.frog.controllable", frogControllable); -@@ -2756,7 +2776,13 @@ public class PurpurWorldConfig { +@@ -2752,7 +2772,13 @@ public class PurpurWorldConfig { public double snifferMaxHealth = 14.0D; public double snifferScale = 1.0D; public int snifferBreedingTicks = 6000; @@ -267,7 +261,7 @@ index 1ff95cced54e8230eb5b4b4314f8f3716e264264..0318c4916a17e6ec721efbfc98835424 snifferRidable = getBoolean("mobs.sniffer.ridable", snifferRidable); snifferRidableInWater = getBoolean("mobs.sniffer.ridable-in-water", snifferRidableInWater); snifferControllable = getBoolean("mobs.sniffer.controllable", snifferControllable); -@@ -2864,7 +2890,15 @@ public class PurpurWorldConfig { +@@ -2860,7 +2886,15 @@ public class PurpurWorldConfig { public boolean tadpoleRidable = false; public boolean tadpoleRidableInWater = true; public boolean tadpoleControllable = true; @@ -283,7 +277,7 @@ index 1ff95cced54e8230eb5b4b4314f8f3716e264264..0318c4916a17e6ec721efbfc98835424 tadpoleRidable = getBoolean("mobs.tadpole.ridable", tadpoleRidable); tadpoleRidableInWater = getBoolean("mobs.tadpole.ridable-in-water", tadpoleRidableInWater); tadpoleControllable = getBoolean("mobs.tadpole.controllable", tadpoleControllable); -@@ -3092,7 +3126,15 @@ public class PurpurWorldConfig { +@@ -3088,7 +3122,15 @@ public class PurpurWorldConfig { public boolean wardenRidable = false; public boolean wardenRidableInWater = true; public boolean wardenControllable = true; diff --git a/patches/server/0015-Add-option-to-change-nether-portal-size.patch b/patches/server/0014-Add-option-to-change-nether-portal-size.patch similarity index 51% rename from patches/server/0015-Add-option-to-change-nether-portal-size.patch rename to patches/server/0014-Add-option-to-change-nether-portal-size.patch index a72b409..9b843de 100644 --- a/patches/server/0015-Add-option-to-change-nether-portal-size.patch +++ b/patches/server/0014-Add-option-to-change-nether-portal-size.patch @@ -5,33 +5,33 @@ Subject: [PATCH] Add option to change nether portal size 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 6c07fc507df6070854f5950a8616d2949c040656..19f58609aedecec1ea1a552c135a0b4199ab5c2a 100644 +index acdff7b4a00d563739fd301c3633a266875296fa..1d361880f80462c1eedad3936b895ec06cf8f505 100644 --- a/src/main/java/net/minecraft/world/level/portal/PortalShape.java +++ b/src/main/java/net/minecraft/world/level/portal/PortalShape.java -@@ -97,7 +97,7 @@ public class PortalShape { - private int calculateWidth() { - int i = this.getDistanceUntilEdgeAboveFrame(this.bottomLeft, this.rightDir); +@@ -113,7 +113,7 @@ public class PortalShape { + private static int calculateWidth(BlockGetter iblockaccess, BlockPos blockposition, Direction enumdirection, BlockStateListPopulator blocks) { // CraftBukkit + int i = PortalShape.getDistanceUntilEdgeAboveFrame(iblockaccess, blockposition, enumdirection, blocks); // CraftBukkit - return i >= 2 && i <= 21 ? i : 0; + return i >= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.width.min() && i <= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.width.max() ? i : 0; // Plazma - Configurable nether portal size } - private int getDistanceUntilEdgeAboveFrame(BlockPos pos, Direction direction) { -@@ -130,7 +130,7 @@ public class PortalShape { + private static int getDistanceUntilEdgeAboveFrame(BlockGetter iblockaccess, BlockPos blockposition, Direction enumdirection, BlockStateListPopulator blocks) { // CraftBukkit +@@ -146,7 +146,7 @@ public class PortalShape { BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); - int i = this.getDistanceUntilTop(blockposition_mutableblockposition); + int j = PortalShape.getDistanceUntilTop(iblockaccess, blockposition, enumdirection, blockposition_mutableblockposition, i, mutableint, blocks); // CraftBukkit -- return i >= 3 && i <= 21 && this.hasTopFrame(blockposition_mutableblockposition, i) ? i : 0; -+ return i >= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.height.min() && i <= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.height.max() && this.hasTopFrame(blockposition_mutableblockposition, i) ? i : 0; // Plazma - Configurable nether portal size +- return j >= 3 && j <= 21 && PortalShape.hasTopFrame(iblockaccess, blockposition, enumdirection, blockposition_mutableblockposition, i, j, blocks) ? j : 0; // CraftBukkit ++ return j >= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.height.min() && j <= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.height.max() && PortalShape.hasTopFrame(iblockaccess, blockposition, enumdirection, blockposition_mutableblockposition, i, j, blocks) ? j : 0; // Craftbukkit // Plazma - Configurable nether portal size } - private boolean hasTopFrame(BlockPos.MutableBlockPos pos, int height) { -@@ -184,7 +184,7 @@ public class PortalShape { + private static boolean hasTopFrame(BlockGetter iblockaccess, BlockPos blockposition, Direction enumdirection, BlockPos.MutableBlockPos blockposition_mutableblockposition, int i, int j, BlockStateListPopulator blocks) { // CraftBukkit +@@ -200,7 +200,7 @@ public class PortalShape { } public boolean isValid() { -- return this.bottomLeft != null && this.width >= 2 && this.width <= 21 && this.height >= 3 && this.height <= 21; -+ return this.bottomLeft != null && this.width >= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.width.min() && this.width <= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.width.max() && this.height >= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.height.min() && this.height <= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.height.max(); // Plazma - Configurable nether portal size +- return this.width >= 2 && this.width <= 21 && this.height >= 3 && this.height <= 21; ++ return this.width >= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.width.min() && this.width <= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.width.max() && this.height >= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.height.min() && this.height <= this.level.getMinecraftWorld().plazmaConfig().structure.netherPortal.height.max(); // Plazma - Configurable nether portal size } // CraftBukkit start - return boolean, add entity diff --git a/patches/server/0016-Apply-various-optimizations.patch b/patches/server/0015-Apply-various-optimizations.patch similarity index 87% rename from patches/server/0016-Apply-various-optimizations.patch rename to patches/server/0015-Apply-various-optimizations.patch index 9139b1c..205bce7 100644 --- a/patches/server/0016-Apply-various-optimizations.patch +++ b/patches/server/0015-Apply-various-optimizations.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Apply various optimizations Akarin - Swaps the predicate order of collision diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7aadcaa1785c6560eb1ce2f1179225facca47d84..2adc6f3400a2b914176d0ae0a85c479b00289fb4 100644 +index 6b32cd1391f39b6fe61c3c8c00249d1d4278cbd0..b94f3e2071e71b2b038e875b25c985b0c7c00fc0 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2211,8 +2211,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2341,8 +2341,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public void playerTouch(Player player) {} public void push(Entity entity) { @@ -21,7 +21,7 @@ index 7aadcaa1785c6560eb1ce2f1179225facca47d84..2adc6f3400a2b914176d0ae0a85c479b if (this.level.paperConfig().collisions.onlyPlayersCollide && !(entity instanceof ServerPlayer || this instanceof ServerPlayer)) return; // Paper - Collision option for requiring a player participant double d0 = entity.getX() - this.getX(); double d1 = entity.getZ() - this.getZ(); -@@ -2240,8 +2241,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2370,8 +2371,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess entity.push(d0, 0.0D, d1); } } diff --git a/patches/server/0017-Do-not-load-chunks-to-spawn-phantom.patch b/patches/server/0016-Do-not-load-chunks-to-spawn-phantom.patch similarity index 95% rename from patches/server/0017-Do-not-load-chunks-to-spawn-phantom.patch rename to patches/server/0016-Do-not-load-chunks-to-spawn-phantom.patch index 1cec7fc..8684e86 100644 --- a/patches/server/0017-Do-not-load-chunks-to-spawn-phantom.patch +++ b/patches/server/0016-Do-not-load-chunks-to-spawn-phantom.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Do not load chunks to spawn phantom 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 04f67f7b43d2f461c776c76614dc3e5f060aea63..b3fe0dd152b3e2e1b83b4ec2270d387e6117ec1c 100644 +index 27eb9a365006884c85603dc6d9dd8eee009c98b3..958a48d05aba8e500c7b19a466dcca6fea8a8bcc 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java @@ -70,6 +70,7 @@ public class PhantomSpawner implements CustomSpawner { diff --git a/patches/server/0018-Add-option-to-disable-moved-to-quickly-check-for-spe.patch b/patches/server/0017-Add-option-to-disable-moved-to-quickly-check-for-spe.patch similarity index 57% rename from patches/server/0018-Add-option-to-disable-moved-to-quickly-check-for-spe.patch rename to patches/server/0017-Add-option-to-disable-moved-to-quickly-check-for-spe.patch index 50cfd34..be32ed2 100644 --- a/patches/server/0018-Add-option-to-disable-moved-to-quickly-check-for-spe.patch +++ b/patches/server/0017-Add-option-to-disable-moved-to-quickly-check-for-spe.patch @@ -6,17 +6,23 @@ Subject: [PATCH] Add option to disable moved to quickly check for specific diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index fd22a6709c7ffd828fbab5b8723f2b723af92f3d..79cfaf78840ac9052b83666d44cdd27f1ed3ae4f 100644 +index 61b19f52aeb371abdd29f41291099f35a9b4c258..dcb0a4461a2fca964e4d8390401e463648ed3351 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1462,6 +1462,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - // Paper end - Prevent moving into unloaded chunks - -+ if (!this.player.getBukkitEntity().hasPermission("plazma.bypass-moved-to-quickly-check") || !(org.plazmamc.plazma.configurations.GlobalConfiguration.get().player.checkSpectatorMovedToQuickly && this.player.isSpectator())) // Plazma - Options to bypass moved to quickly check - if (!this.player.isChangingDimension() && (!this.player.level().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !flag)) { - float f2 = flag ? 300.0F : 100.0F; +@@ -1694,7 +1694,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + } + } ++ // Plazma start - Add option to bypass moved to quickly check + private boolean shouldCheckPlayerMovement(boolean elytra) { ++ return (!this.player.getBukkitEntity().hasPermission("plazma.bypass-moved-to-quickly-check") || !(org.plazmamc.plazma.configurations.GlobalConfiguration.get().player.checkSpectatorMovedToQuickly && this.player.isSpectator())) && shouldCheckPlayerMovement0(elytra); ++ } ++ ++ private boolean shouldCheckPlayerMovement0(boolean elytra) { ++ // Plazma end - Add option to bypass moved to quickly check + if (this.isSingleplayerOwner()) { + return false; + } else if (this.player.isChangingDimension()) { diff --git a/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java b/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java index 3ec9c947ac19412ad81d0cc85e0eff289a285d1e..af89ad0fcaebb5776ae3c18d02441c48f4227251 100644 --- a/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java diff --git a/patches/server/0019-Configurable-cave-lava-sea-level.patch b/patches/server/0018-Configurable-cave-lava-sea-level.patch similarity index 97% rename from patches/server/0019-Configurable-cave-lava-sea-level.patch rename to patches/server/0018-Configurable-cave-lava-sea-level.patch index e6128da..5c6209a 100644 --- a/patches/server/0019-Configurable-cave-lava-sea-level.patch +++ b/patches/server/0018-Configurable-cave-lava-sea-level.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Configurable cave lava sea level This patch also fix MC-237017. diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -index 68be0d51aa64b5d917fb53dbbbdf8966d4f4abd8..688d9a2fe0ad0f176cd19a3ed7f2669fef2c962e 100644 +index 3f39d6c786d9dfdd9ad591e08ff05fcbb41a1df6..0346fd4ab7095d66c0eef5a440afbc7a8ba52466 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java @@ -71,14 +71,14 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { diff --git a/patches/unapplied/server/0011-Optimize-default-configurations.patch b/patches/unapplied/server/0011-Optimize-default-configurations.patch index 32094bf..4668f11 100644 --- a/patches/unapplied/server/0011-Optimize-default-configurations.patch +++ b/patches/unapplied/server/0011-Optimize-default-configurations.patch @@ -1,4 +1,62 @@ +diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java +index 8f1645573780d12bf29d441d31eab1b76cd9e70f..8e35f7fbe3629ab05c16f52d72a3cd7343cf835f 100644 +--- a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java ++++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java +@@ -64,7 +64,7 @@ public class PufferfishConfig { + getString("info.version", "1.0"); + setComment("info", + "Pufferfish Configuration", +- "Check out Pufferfish Host for maximum performance server hosting: https://pufferfish.host", ++ // "Check out Pufferfish Host for maximum performance server hosting: https://pufferfish.host", // Plazma - Sponsorblock + "Join our Discord for support: https://discord.gg/reZw4vQV9H", + "Download new builds at https://ci.pufferfish.host/job/Pufferfish"); + +@@ -219,7 +219,7 @@ public class PufferfishConfig { + public static int maxProjectileLoadsPerTick; + public static int maxProjectileLoadsPerProjectile; + private static void projectileLoading() { +- maxProjectileLoadsPerTick = getInt("projectile.max-loads-per-tick", 10, "Controls how many chunks are allowed", "to be sync loaded by projectiles in a tick."); ++ maxProjectileLoadsPerTick = getInt("projectile.max-loads-per-tick", org.plazmamc.plazma.configurations.PlazmaConfigurations.optimize() ? 8 : 10, "Controls how many chunks are allowed", "to be sync loaded by projectiles in a tick."); // Plazma - Optimize default configurations + maxProjectileLoadsPerProjectile = getInt("projectile.max-loads-per-projectile", 10, "Controls how many chunks a projectile", "can load in its lifetime before it gets", "automatically removed."); + + setComment("projectile", "Optimizes projectile settings"); +@@ -233,12 +233,12 @@ public class PufferfishConfig { + public static int activationDistanceMod; + + private static void dynamicActivationOfBrains() throws IOException { +- dearEnabled = getBoolean("dab.enabled", "activation-range.enabled", false); // Purpur ++ dearEnabled = getBoolean("dab.enabled", "activation-range.enabled", org.plazmamc.plazma.configurations.PlazmaConfigurations.optimize()); // Purpur // Plazma - Optimize default configurations + startDistance = getInt("dab.start-distance", "activation-range.start-distance", 12, + "This value determines how far away an entity has to be", + "from the player to start being effected by DEAR."); + startDistanceSquared = startDistance * startDistance; +- maximumActivationPrio = getInt("dab.max-tick-freq", "activation-range.max-tick-freq", 20, ++ maximumActivationPrio = getInt("dab.max-tick-freq", "activation-range.max-tick-freq", org.plazmamc.plazma.configurations.PlazmaConfigurations.optimize() ? 7 : 8, // Plazma - Optimize default configurations + "This value defines how often in ticks, the furthest entity", + "will get their pathfinders and behaviors ticked. 20 = 1s"); + activationDistanceMod = getInt("dab.activation-dist-mod", "activation-range.activation-dist-mod", 8, +@@ -261,8 +261,18 @@ public class PufferfishConfig { + public static Map projectileTimeouts; + private static void projectileTimeouts() { + // Set some defaults +- getInt("entity_timeouts.SNOWBALL", -1); +- getInt("entity_timeouts.LLAMA_SPIT", -1); ++ // Plazma start - Optimize default configurations ++ if (org.plazmamc.plazma.configurations.PlazmaConfigurations.optimize()) { ++ getInt("entity_timeouts.ARROW", 200); ++ getInt("entity_timeouts.EGG", 200); ++ getInt("entity_timeouts.ENDER_PEARL", 200); ++ getInt("entity_timeouts.SNOWBALL", 200); ++ getInt("entity_timeouts.LLAMA_SPIT", 200); ++ } else { ++ getInt("entity_timeouts.SNOWBALL", -1); ++ getInt("entity_timeouts.LLAMA_SPIT", -1); ++ } ++ // Plazma end - Optimize default configurations + setComment("entity_timeouts", + "These values define a entity's maximum lifespan. If an", + "entity is in this list and it has survived for longer than", diff --git a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java index c867796f6..ecced2072 100644 --- a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java diff --git a/patches/server/0032-Add-some-missing-Pufferfish-configurations.patch b/patches/unapplied/server/0032-Add-some-missing-Pufferfish-configurations.patch similarity index 100% rename from patches/server/0032-Add-some-missing-Pufferfish-configurations.patch rename to patches/unapplied/server/0032-Add-some-missing-Pufferfish-configurations.patch diff --git a/patches/server/0020-Configurable-entity-sensor-tick.patch b/patches/works/server/0020-Configurable-entity-sensor-tick.patch similarity index 100% rename from patches/server/0020-Configurable-entity-sensor-tick.patch rename to patches/works/server/0020-Configurable-entity-sensor-tick.patch diff --git a/patches/server/0021-Variable-entity-wakeup-duration.patch b/patches/works/server/0021-Variable-entity-wakeup-duration.patch similarity index 100% rename from patches/server/0021-Variable-entity-wakeup-duration.patch rename to patches/works/server/0021-Variable-entity-wakeup-duration.patch diff --git a/patches/server/0022-Optimise-state-lookup-more.patch b/patches/works/server/0022-Optimise-state-lookup-more.patch similarity index 100% rename from patches/server/0022-Optimise-state-lookup-more.patch rename to patches/works/server/0022-Optimise-state-lookup-more.patch diff --git a/patches/server/0023-Skip-event-if-no-listeners.patch b/patches/works/server/0023-Skip-event-if-no-listeners.patch similarity index 100% rename from patches/server/0023-Skip-event-if-no-listeners.patch rename to patches/works/server/0023-Skip-event-if-no-listeners.patch diff --git a/patches/server/0024-Add-entity-spawn-deadlock-timer.patch b/patches/works/server/0024-Add-entity-spawn-deadlock-timer.patch similarity index 100% rename from patches/server/0024-Add-entity-spawn-deadlock-timer.patch rename to patches/works/server/0024-Add-entity-spawn-deadlock-timer.patch diff --git a/patches/server/0025-Lithium-HashedList.patch b/patches/works/server/0025-Lithium-HashedList.patch similarity index 100% rename from patches/server/0025-Lithium-HashedList.patch rename to patches/works/server/0025-Lithium-HashedList.patch diff --git a/patches/server/0026-Improve-SwingTime-ticking.patch b/patches/works/server/0026-Improve-SwingTime-ticking.patch similarity index 100% rename from patches/server/0026-Improve-SwingTime-ticking.patch rename to patches/works/server/0026-Improve-SwingTime-ticking.patch diff --git a/patches/server/0027-Save-Json-list-asynchronously.patch b/patches/works/server/0027-Save-Json-list-asynchronously.patch similarity index 100% rename from patches/server/0027-Save-Json-list-asynchronously.patch rename to patches/works/server/0027-Save-Json-list-asynchronously.patch diff --git a/patches/server/0028-Process-pathfinding-asynchronously.patch b/patches/works/server/0028-Process-pathfinding-asynchronously.patch similarity index 100% rename from patches/server/0028-Process-pathfinding-asynchronously.patch rename to patches/works/server/0028-Process-pathfinding-asynchronously.patch diff --git a/patches/server/0029-Use-Akair-s-flag-when-running-the-test-server-with-g.patch b/patches/works/server/0029-Use-Akair-s-flag-when-running-the-test-server-with-g.patch similarity index 100% rename from patches/server/0029-Use-Akair-s-flag-when-running-the-test-server-with-g.patch rename to patches/works/server/0029-Use-Akair-s-flag-when-running-the-test-server-with-g.patch diff --git a/patches/server/0030-Use-Plazma-logo-instead-if-server-favicon-doesn-t-ex.patch b/patches/works/server/0030-Use-Plazma-logo-instead-if-server-favicon-doesn-t-ex.patch similarity index 100% rename from patches/server/0030-Use-Plazma-logo-instead-if-server-favicon-doesn-t-ex.patch rename to patches/works/server/0030-Use-Plazma-logo-instead-if-server-favicon-doesn-t-ex.patch diff --git a/patches/server/0031-Implement-FreedomChat.patch b/patches/works/server/0031-Implement-FreedomChat.patch similarity index 100% rename from patches/server/0031-Implement-FreedomChat.patch rename to patches/works/server/0031-Implement-FreedomChat.patch diff --git a/patches/server/0033-Port-SparklyPaper-patches.patch b/patches/works/server/0033-Port-SparklyPaper-patches.patch similarity index 100% rename from patches/server/0033-Port-SparklyPaper-patches.patch rename to patches/works/server/0033-Port-SparklyPaper-patches.patch diff --git a/patches/server/0034-Add-more-MSPT.patch b/patches/works/server/0034-Add-more-MSPT.patch similarity index 100% rename from patches/server/0034-Add-more-MSPT.patch rename to patches/works/server/0034-Add-more-MSPT.patch diff --git a/patches/server/0035-Reset-dirty-flag-when-loading-maps-from-the-disk.patch b/patches/works/server/0035-Reset-dirty-flag-when-loading-maps-from-the-disk.patch similarity index 100% rename from patches/server/0035-Reset-dirty-flag-when-loading-maps-from-the-disk.patch rename to patches/works/server/0035-Reset-dirty-flag-when-loading-maps-from-the-disk.patch diff --git a/patches/server/0036-Allow-throttling-hopper-checks-if-the-target-contain.patch b/patches/works/server/0036-Allow-throttling-hopper-checks-if-the-target-contain.patch similarity index 100% rename from patches/server/0036-Allow-throttling-hopper-checks-if-the-target-contain.patch rename to patches/works/server/0036-Allow-throttling-hopper-checks-if-the-target-contain.patch diff --git a/patches/server/0037-Suppress-errors-from-dirty-attributes.patch b/patches/works/server/0037-Suppress-errors-from-dirty-attributes.patch similarity index 100% rename from patches/server/0037-Suppress-errors-from-dirty-attributes.patch rename to patches/works/server/0037-Suppress-errors-from-dirty-attributes.patch diff --git a/patches/server/0038-Implement-Rail-Optimazition.patch b/patches/works/server/0038-Implement-Rail-Optimazition.patch similarity index 100% rename from patches/server/0038-Implement-Rail-Optimazition.patch rename to patches/works/server/0038-Implement-Rail-Optimazition.patch diff --git a/patches/server/0039-Implement-alternative-noise-chunk-generator.patch b/patches/works/server/0039-Implement-alternative-noise-chunk-generator.patch similarity index 100% rename from patches/server/0039-Implement-alternative-noise-chunk-generator.patch rename to patches/works/server/0039-Implement-alternative-noise-chunk-generator.patch diff --git a/patches/server/0040-Load-player-data-asynchronously.patch b/patches/works/server/0040-Load-player-data-asynchronously.patch similarity index 100% rename from patches/server/0040-Load-player-data-asynchronously.patch rename to patches/works/server/0040-Load-player-data-asynchronously.patch diff --git a/patches/server/0041-Configurable-RandomSource-factory-provider.patch b/patches/works/server/0041-Configurable-RandomSource-factory-provider.patch similarity index 100% rename from patches/server/0041-Configurable-RandomSource-factory-provider.patch rename to patches/works/server/0041-Configurable-RandomSource-factory-provider.patch diff --git a/patches/server/0042-Optimize-advancement-criteria-triggering.patch b/patches/works/server/0042-Optimize-advancement-criteria-triggering.patch similarity index 100% rename from patches/server/0042-Optimize-advancement-criteria-triggering.patch rename to patches/works/server/0042-Optimize-advancement-criteria-triggering.patch diff --git a/patches/server/0043-Configurable-water-flowing-speed.patch b/patches/works/server/0043-Configurable-water-flowing-speed.patch similarity index 100% rename from patches/server/0043-Configurable-water-flowing-speed.patch rename to patches/works/server/0043-Configurable-water-flowing-speed.patch diff --git a/patches/server/0044-TickControl-System.patch b/patches/works/server/0044-TickControl-System.patch similarity index 100% rename from patches/server/0044-TickControl-System.patch rename to patches/works/server/0044-TickControl-System.patch