diff --git a/.gitignore b/.gitignore
index 3e9533a..14a5b5f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,4 +55,4 @@ build-data/
*-API
*-MojangAPI
*-Server
-*.jar
+paper-api-generator
diff --git a/README.md b/README.md
index 580e995..d87f843 100644
--- a/README.md
+++ b/README.md
@@ -5,8 +5,8 @@
### A Server Platform for Minecraft: Java Edition based on [Paper](https://github.com/PaperMC/Paper)
[](https://discord.gg/MmfC52K8A8)
-[](https://github.com/PlazmaMC/Plazma/actions/workflows/build.yml?query=branch:ver/1.20.2)
-[](https://github.com/PlazmaMC/Plazma/releases/build/1.20.2/latest)
+[](https://github.com/PlazmaMC/Plazma/actions/workflows/build.yml?query=branch:ver/1.20.4)
+[](https://github.com/PlazmaMC/Plazma/releases/build/1.20.4/latest)
[](LICENSE)
[](https://github.com/PlazmaMC/Plazma/releases)
@@ -19,8 +19,8 @@
[main]: https://github.com/PlazmaMC/Plazma
> [!IMPORTANT]
-This is the branch for Plazma 1.20.2. If you want to know more about Plazma, please check the **[main branch][main]**.
-이곳은 플라즈마의 1.20.2용 분기입니다. 플라즈마에 대해 자세히 알고 싶다면 **[main 브랜치][main]** 를 확인해주세요.
+This is the branch for Plazma 1.20.4. If you want to know more about Plazma, please check the **[main branch][main]**.
+이곳은 플라즈마의 1.20.4용 분기입니다. 플라즈마에 대해 자세히 알고 싶다면 **[main 분기][main]** 를 확인해주세요.
## ⬇️ Downloads
> [!NOTE]
@@ -28,11 +28,12 @@ If you don't know about Mojmap or Bundler, download **Reobf Paperclip**
Mojmap 또는 Bundler에 대해 잘 알지 못한다면, **Reobf Paperclip**을 사용하세요
-[paperReobf]: https://github.com/PlazmaMC/Plazma/releases/download/build/1.20.2/latest/plazma-paperclip-1.20.2-R0.1-SNAPSHOT-reobf.jar
-[paperMojmap]: https://github.com/PlazmaMC/Plazma/releases/download/build/1.20.2/latest/plazma-paperclip-1.20.2-R0.1-SNAPSHOT-mojmap.jar
-[bundlerReobf]: https://github.com/PlazmaMC/Plazma/releases/download/build/1.20.2/latest/plazma-bundler-1.20.2-R0.1-SNAPSHOT-reobf.jar
-[bundlerMojmap]: https://github.com/PlazmaMC/Plazma/releases/download/build/1.20.2/latest/plazma-bundler-1.20.2-R0.1-SNAPSHOT-mojmap.jar
+[paperReobf]: https://github.com/PlazmaMC/Plazma/releases/download/build/1.20.4/latest/plazma-paperclip-1.20.4-R0.1-SNAPSHOT-reobf.jar
+[paperMojmap]: https://github.com/PlazmaMC/Plazma/releases/download/build/1.20.4/latest/plazma-paperclip-1.20.4-R0.1-SNAPSHOT-mojmap.jar
+[bundlerReobf]: https://github.com/PlazmaMC/Plazma/releases/download/build/1.20.4/latest/plazma-bundler-1.20.4-R0.1-SNAPSHOT-reobf.jar
+[bundlerMojmap]: https://github.com/PlazmaMC/Plazma/releases/download/build/1.20.4/latest/plazma-bundler-1.20.4-R0.1-SNAPSHOT-mojmap.jar
| **Reobf Paperclip (Default)** | Mojmap Paperclip | Reobf Bundler | Mojmap Bundler |
|:-----------------------------:|:-----------------------:|:------------------------:|:-------------------------:|
-| [Download][paperReobf] | [Download][paperMojmap] | [Download][bundlerReobf] | [Download][bundlerMojmap] |
+| Work | In | Progress | !!! |
+
diff --git a/build.gradle.kts b/build.gradle.kts
index f3c0cbe..a032275 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,4 +1,5 @@
-import io.papermc.paperweight.util.constants.PAPERCLIP_CONFIG
+import org.gradle.api.tasks.testing.logging.TestExceptionFormat
+import org.gradle.api.tasks.testing.logging.TestLogEvent
group = "org.plazmamc.plazma"
@@ -19,7 +20,7 @@ repositories {
mavenCentral()
maven("https://papermc.io/repo/repository/maven-public/") {
content {
- onlyForConfigurations(PAPERCLIP_CONFIG)
+ onlyForConfigurations(configurations.paperclip.name)
}
}
}
@@ -62,7 +63,7 @@ subprojects {
withType().configureEach {
options.compilerArgs.addAll(listOf("--add-modules=jdk.incubator.vector", "-Xmaxwarns", "1"))
options.encoding = Charsets.UTF_8.name()
- options.release.set(17)
+ options.release = 17
}
withType {
@@ -74,30 +75,27 @@ subprojects {
}
withType {
- minHeapSize = "2g"
- maxHeapSize = "2g"
+ testLogging {
+ showStackTraces = true
+ exceptionFormat = TestExceptionFormat.FULL
+ events(TestLogEvent.STANDARD_OUT)
+ }
}
}
repositories {
mavenCentral()
- maven("https://oss.sonatype.org/content/groups/public/")
maven("https://papermc.io/repo/repository/maven-public/")
- maven("https://ci.emc.gs/nexus/content/groups/aikar/")
- maven("https://repo.aikar.co/content/groups/aikar")
- maven("https://repo.md-5.net/content/repositories/releases/")
- maven("https://hub.spigotmc.org/nexus/content/groups/public/")
maven("https://jitpack.io")
- maven("https://oss.sonatype.org/content/repositories/snapshots/")
}
}
paperweight {
- serverProject.set(project(":plazma-server"))
+ serverProject = project(":plazma-server")
- remapRepo.set("https://maven.fabricmc.net/")
- decompileRepo.set("https://files.minecraftforge.net/maven/")
+ remapRepo = "https://repo.papermc.io/repository/maven-public/"
+ decompileRepo = "https://repo.papermc.io/repository/maven-public/"
usePaperUpstream(providers.gradleProperty("paperCommit")) {
withPaperPatcher {
@@ -107,6 +105,13 @@ paperweight {
serverPatchDir.set(layout.projectDirectory.dir("patches/server"))
serverOutputDir.set(layout.projectDirectory.dir("Plazma-Server"))
}
+
+ patchTasks.register("generatedApi") {
+ isBareDirectory = true
+ upstreamDirPath = "paper-api-generator/generated"
+ patchDir = layout.projectDirectory.dir("patches/generated-api")
+ outputDir = layout.projectDirectory.dir("paper-api-generator/generated")
+ }
}
}
@@ -125,7 +130,16 @@ tasks {
mojangApiCoordinates.set("io.papermc.paper:paper-mojangapi")
libraryRepositories.addAll(
"https://repo.maven.apache.org/maven2/",
+ "https://maven.pkg.github.com/PlazmaMC/Plazma",
"https://papermc.io/repo/repository/maven-public/"
)
}
}
+
+publishing {
+ publications.create("devBundle") {
+ artifact(tasks.generateDevelopmentBundle) {
+ artifactId = "dev-bundle"
+ }
+ }
+}
diff --git a/buildSrc/src/main/kotlin/org/plazmamc/alwaysuptodate/tasks/PaperUpdateTask.kt b/buildSrc/src/main/kotlin/org/plazmamc/alwaysuptodate/tasks/PaperUpdateTask.kt
index 849b859..e5fd66b 100644
--- a/buildSrc/src/main/kotlin/org/plazmamc/alwaysuptodate/tasks/PaperUpdateTask.kt
+++ b/buildSrc/src/main/kotlin/org/plazmamc/alwaysuptodate/tasks/PaperUpdateTask.kt
@@ -35,10 +35,10 @@ abstract class PaperUpdateTask : Task() {
}
-fun updatePaperCommit(repo: String, branch: String, properties: File) {
+fun updatePaperCommit(repo: String, branch: String, properties: File, regexRule: String = "paperCommit = ") {
val latestCommit = Git(properties.parentFile.toPath())("ls-remote", repo).readText()?.lines()
?.filterNot { "[a-z0-9]{40}\trefs/heads/$branch".toRegex().matches(it) }?.first()?.split("\t")?.first()
?: throw AlwaysUpToDateException("Failed to get latest Paper commit")
- properties.writeText(properties.readText().replace("paperCommit = .*".toRegex(), "paperCommit = $latestCommit"))
+ properties.writeText(properties.readText().replace("$regexRule.*".toRegex(), "$regexRule$latestCommit"))
}
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 444a6dc..848a3d7 100644
--- a/buildSrc/src/main/kotlin/org/plazmamc/alwaysuptodate/tasks/PurpurUpdateTask.kt
+++ b/buildSrc/src/main/kotlin/org/plazmamc/alwaysuptodate/tasks/PurpurUpdateTask.kt
@@ -84,7 +84,7 @@ abstract class PurpurUpdateTask : Task() {
val pufferfish = git.clone("Pufferfish", property.pufferfishRepository.get(), property.pufferfishBranch.get(), dir)
val purpur = git.clone("Purpur", property.purpurRepository.get(), property.purpurBranch.get(), dir)
- updatePaperCommit(property.paperRepository.get(), property.paperBranch.get(), pufferfish.resolve("gradle.properties").toFile())
+ updatePaperCommit(property.paperRepository.get(), property.paperBranch.get(), pufferfish.resolve("gradle.properties").toFile(), "paperRef=")
updatePaperCommit(property.paperRepository.get(), property.paperBranch.get(), purpur.resolve("gradle.properties").toFile())
updatePaperCommit(property.paperRepository.get(), property.paperBranch.get(), project.file("gradle.properties"))
@@ -107,6 +107,7 @@ abstract class PurpurUpdateTask : Task() {
copySource(paper)
Git(paper)("add", ".").executeOut()
Git(paper)("commit", "-m", "Vanilla Sources", "--author=Vanilla ").executeOut()
+ Thread.sleep(1_000)
paper.resolve(".git").toFile().copyRecursively(dotGit, overwrite = true)
Git(it).addCommit("Pufferfish Server Changes\n\n$pufferfishCommit", "--author=Kevin Raneri ")
diff --git a/gradle.properties b/gradle.properties
index 98d02f0..886b32e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,7 +1,7 @@
-version = 1.20.2-R0.1-SNAPSHOT
-mcVersion = 1.20.2
+version = 1.20.4-R0.1-SNAPSHOT
+mcVersion = 1.20.4
-paperCommit = 931781c220b98dde0159c9a3c8dce06c3b2b1e13
+paperCommit = 94807a1d2e74b26b1a3154974d4024daa4c95f51
purpurCommit = c46cb7ef66675e00a48e20c40febed7ff914f35d
pufferfishCommit = bc89152d4cd4bb0f9644da2fe10774df4cc25661
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 02be563..b0a8f41 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,6 +1,6 @@
[versions]
shadow = "8.1.1"
-paperweight = "1.5.10"
+paperweight = "1.5.11"
paperclip = "3.0.3"
decompiler = "2.0.627.2"
remapper = "0.3.0:fat"
diff --git a/libs/api.versions.toml b/libs/api.versions.toml
index 4519023..e012682 100644
--- a/libs/api.versions.toml
+++ b/libs/api.versions.toml
@@ -5,7 +5,7 @@ guava = "32.1.2-jre"
sentry = "5.4.0"
fastutil = "8.5.6"
findbugs = "1.3.9"
-slf4j-api = "1.8.0-beta4"
+slf4j-api = "2.0.9"
bungeechat = "1.20-R0.1-deprecated+build.14"
json-simple = "1.1.1"
annotations = "24.0.1"
diff --git a/libs/common.versions.toml b/libs/common.versions.toml
index 89798d5..ec81036 100644
--- a/libs/common.versions.toml
+++ b/libs/common.versions.toml
@@ -5,7 +5,7 @@ mockito = "5.5.0"
jupiter = "5.10.0"
hamcrest = "2.2"
snakeyaml = "2.2"
-adventure = "4.14.0"
+adventure = "4.15.0"
commons-lang2 = "2.6"
commons-lang3 = "3.12.0"
maven-provider = "3.8.5"
diff --git a/patches/api/0001-Pufferfish-API-Changes.patch b/patches/api/0001-Pufferfish-API-Changes.patch
index aec2e53..39c9227 100644
--- a/patches/api/0001-Pufferfish-API-Changes.patch
+++ b/patches/api/0001-Pufferfish-API-Changes.patch
@@ -1,10 +1,10 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kevin Raneri
-Date: Sun, 26 Nov 2023 23:32:01 +0000
+Date: Tue, 9 Nov 2021 14:01:56 -0500
Subject: [PATCH] Pufferfish API Changes
-Original: Kevin Raneri
-Copyright (C) 2023 Pufferfish Studios LLC
+Pufferfish
+Copyright (C) 2022 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
@@ -20,18 +20,18 @@ 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 e827ee211e3c65dc68ac5867fd8476639df63645..b9c75a190dbd7a90ac5ef0fbc6e6fe34806acc4e 100644
+index bf01892c248b988531d21d9fb0f74d0adf2205ac..80833c13a2d19e31d6f648e7ef5b3456025e767e 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
-@@ -47,6 +47,7 @@ dependencies {
+@@ -51,6 +51,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.4")
- implementation("org.ow2.asm:asm-commons:9.4")
-@@ -106,6 +107,13 @@ val generateApiVersioningFile by tasks.registering {
+ implementation("org.ow2.asm:asm:9.5")
+ implementation("org.ow2.asm:asm-commons:9.5")
+@@ -109,6 +110,13 @@ val generateApiVersioningFile by tasks.registering {
}
}
@@ -480,7 +480,7 @@ index eaefbb00e9993d54906cc8cf35cf753c0d6c7707..301e82369603f3dd6e6c1bd380da4bac
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 f9b57b872780aa6b9b959494874b57c7a8ff0c53..90953bfc81168068a281be4d2d3942d5e7dd69ff 100644
+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
diff --git a/patches/api/0002-Purpur-API-Changes.patch b/patches/api/0002-Purpur-API-Changes.patch
index 709798c..596e0af 100644
--- a/patches/api/0002-Purpur-API-Changes.patch
+++ b/patches/api/0002-Purpur-API-Changes.patch
@@ -1,10 +1,10 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: William Blake Galbreath
-Date: Sun, 26 Nov 2023 23:37:25 +0000
+From: granny
+Date: Thu, 18 Jan 2024 22:51:24 +0900
Subject: [PATCH] Purpur API Changes
-Original: PurpurMC
-Copyright (C) 2023 PurpurMC
+PurpurMC
+Copyright (C) 2024 PurpurMC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -25,10 +25,10 @@ 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 b9c75a190dbd7a90ac5ef0fbc6e6fe34806acc4e..41d7b75e904b94073dfcd12b776a7759a963b66f 100644
+index 80833c13a2d19e31d6f648e7ef5b3456025e767e..0a33275fdf16bda47771bab9ddfeb2bf8616c2dc 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
-@@ -126,6 +126,8 @@ tasks.jar {
+@@ -129,6 +129,8 @@ tasks.jar {
}
tasks.withType {
@@ -168,29 +168,6 @@ index e801e79fa57c44b2e5d359647c920f88064826f1..1abfcee0f6d632f4cd8d74b4994a90c9
return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS,
new ArrayList(TIMINGS_SUBCOMMANDS.size()));
}
-diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java
-index 0c4dbb9ef63fa8575b5546239443cb2bd91ba847..b347224c223569297ee67ac630a710fdf28748ea 100644
---- a/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java
-+++ b/src/main/java/com/destroystokyo/paper/entity/ai/VanillaGoal.java
-@@ -198,6 +198,18 @@ public interface VanillaGoal extends Goal {
- GoalKey CLIMB_ON_TOP_OF_POWDER_SNOW = GoalKey.of(Mob.class, NamespacedKey.minecraft("climb_on_top_of_powder_snow"));
- GoalKey WOLF_PANIC = GoalKey.of(Wolf.class, NamespacedKey.minecraft("wolf_panic"));
-
-+ // Purpur start
-+ GoalKey MOB_HAS_RIDER = GoalKey.of(Mob.class, NamespacedKey.minecraft("has_rider"));
-+ GoalKey HORSE_HAS_RIDER = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("horse_has_rider"));
-+ GoalKey LLAMA_HAS_RIDER = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_has_rider"));
-+ GoalKey FIND_CRYSTAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("find_crystal"));
-+ GoalKey ORBIT_CRYSTAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("orbit_crystal"));
-+ GoalKey DROWNED_ATTACK_VILLAGER = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack_villager"));
-+ GoalKey ZOMBIE_ATTACK_VILLAGER = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_villager"));
-+ GoalKey AVOID_RABID_WOLF = GoalKey.of(Wolf.class, NamespacedKey.minecraft("avoid_rabid_wolf"));
-+ GoalKey RECEIVE_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("receive_flower"));
-+ // Purpur end
-+
- /**
- * @deprecated removed in 1.20.2
- */
diff --git a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
index a736d7bcdc5861a01b66ba36158db1c716339346..22fc165fd9c95f0f3ae1be7a0857e48cc50fad5b 100644
--- a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
@@ -209,10 +186,10 @@ index a736d7bcdc5861a01b66ba36158db1c716339346..22fc165fd9c95f0f3ae1be7a0857e48c
@Override
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
-index 4863d9f21f0a0f11974be85360edc587ffd7eab3..8ea42a1f07df756bf504609d2bbff578f20bb808 100644
+index 48fab492609e0bae459d20cc2eae78b87e37ab75..109304f8064ab2fab57f9c0f1745e446e6748b3d 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
-@@ -2832,4 +2832,127 @@ public final class Bukkit {
+@@ -2842,4 +2842,127 @@ public final class Bukkit {
public static Server.Spigot spigot() {
return server.spigot();
}
@@ -431,10 +408,10 @@ index 918a045165cdcde264bc24082b7afebb407271de..687d11619379aead7f665d4a5f8f8bcc
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java
-index 7ca70b269e15e818e61a9329e2775789abb4bc73..aa9ca3e33903747a455ad0949387684ce4b917af 100644
+index f9af60356da4668cec8b24e73f5747ab82e35a91..b304ad1307cdd6785653b1eab9781e070fb14c5a 100644
--- a/src/main/java/org/bukkit/Material.java
+++ b/src/main/java/org/bukkit/Material.java
-@@ -11054,4 +11054,40 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
+@@ -11557,4 +11557,40 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla
public boolean isEnabledByFeature(@NotNull World world) {
return Bukkit.getDataPackManager().isEnabledByFeature(this, world);
}
@@ -595,10 +572,10 @@ index bce07d84cafca677bb6fad78c21b82097f06430c..4ef0fa4f1ef72bb784674671473c6a32
+ // Purpur end - OfflinePlayer API
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
-index f1fa97d12f97baf97beb92ca0719cf3cf906b225..dd99f53e3d559685a4b3a454a9e607c310fc6aff 100644
+index 9af4bc16da09e59009c47911219e99450cdf2aa5..529fb1beadefc79ce6bf5755d5223301b9933152 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
-@@ -2190,6 +2190,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
+@@ -2198,6 +2198,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
}
// Paper end
@@ -617,7 +594,7 @@ index f1fa97d12f97baf97beb92ca0719cf3cf906b225..dd99f53e3d559685a4b3a454a9e607c3
/**
* Sends the component to the player
*
-@@ -2473,4 +2485,105 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
+@@ -2481,4 +2493,105 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
boolean isOwnedByCurrentRegion(@NotNull Entity entity);
// Paper end - Folia region threading API
@@ -724,10 +701,10 @@ index f1fa97d12f97baf97beb92ca0719cf3cf906b225..dd99f53e3d559685a4b3a454a9e607c3
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
-index 567a36a4887da8994c9170e2885aa8cc357efa0c..405d60bd2c99ba741d2614b16f4bda5da48a0387 100644
+index bf4b94ea2577e9d7e344385209fc0644a4e6bfbb..eea802fbee51e919595f6501161bf2fd58d6a1c1 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
-@@ -4235,6 +4235,86 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
+@@ -4172,6 +4172,86 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
@Nullable
public DragonBattle getEnderDragonBattle();
@@ -977,10 +954,10 @@ index 138d2530de2410f4a9424dabd3e5ce0cd1c1dcd2..10a8d64ad2da0be2c14f34c3e7d1957c
// Paper start
/**
diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java
-index 9e3cb75536ae260dc898ab9dafbc1d98398782bc..ed9627dff9a33524da546c46e1d1be71ae1d1e0c 100644
+index 1d0fd7ff8449f815a7d980af0b378181ea8bf8d8..42b8de355855baecd0a435314909116c210d002d 100644
--- a/src/main/java/org/bukkit/entity/Entity.java
+++ b/src/main/java/org/bukkit/entity/Entity.java
-@@ -1063,4 +1063,55 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
+@@ -1107,4 +1107,55 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
*/
@NotNull String getScoreboardEntryName();
// Paper end - entity scoreboard name
@@ -1129,10 +1106,10 @@ index 58017fce436cdbda255f7172fbdadb726d4b113c..05600fc8bf2a61aca8094029bc4c208a
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
-index a599ed2795ba1baf2cbb465d1c7145580c27e1ea..298acbfb93663e40e627f6a47d51fd87a1551feb 100644
+index 47b0154928b3d36e2602da202df07defbcf82108..7498179f6df47008c4da6ad6d67b2ce16f49e7a6 100644
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
-@@ -1243,4 +1243,41 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
+@@ -1276,4 +1276,41 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
*/
void setBodyYaw(float bodyYaw);
// Paper end
@@ -1200,10 +1177,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 47fcfa2a3358766dfda2efc9bbcf5b50e3f2f7c1..eea83040ff15ea7c9bf97a45f5557294b309b4c8 100644
+index ae61a39b25267b84fe0b8766e4b12d9b24b44ded..3aa79be25d63f704170baaf799482ccdde6a2830 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
-@@ -3366,4 +3366,123 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
+@@ -3574,4 +3574,123 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
@Override
Spigot spigot();
// Spigot end
@@ -1439,10 +1416,10 @@ index c9f395064656dd0126410eb3c6e197baa450c063..13156a12e5df50cdc1e465dc0bd9d941
* When a player gets bad omen after killing a patrol captain.
*/
diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java
-index cbce826add9dc2b3187c7bea00c27b785d7517df..3a98de6407d9a6307f89c207be1f09e639385ebe 100644
+index daa1306a7324d946d66ad5a674bbc84371d8d4d6..f3b2d7b6fda051211add2b3215f120fb6911aeed 100644
--- a/src/main/java/org/bukkit/event/inventory/InventoryType.java
+++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java
-@@ -151,7 +151,7 @@ public enum InventoryType {
+@@ -165,7 +165,7 @@ public enum InventoryType {
SMITHING_NEW(4, "Upgrade Gear"),
;
@@ -1471,10 +1448,10 @@ index c60be4fd24c7fdf65251dd6169e5e1ac3b588d95..569deccd2f1cf21da9b5906433ac493c
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java
-index 0217f98a74140bbae454d467de27c12b6060ca75..fba5b867ea9de36b45ef25c2a93fc436701bb3d9 100644
+index f680545b6b59bf8d2ad154b0472dda4cba42a162..58a62ba0635f9158bf18043da89aba7521e0e2e1 100644
--- a/src/main/java/org/bukkit/inventory/ItemFactory.java
+++ b/src/main/java/org/bukkit/inventory/ItemFactory.java
-@@ -355,4 +355,14 @@ public interface ItemFactory {
+@@ -353,4 +353,14 @@ public interface ItemFactory {
*/
@NotNull ItemStack enchantWithLevels(@NotNull ItemStack itemStack, @org.jetbrains.annotations.Range(from = 1, to = 30) int levels, boolean allowTreasure, @NotNull java.util.Random random);
// Paper end - enchantWithLevels API
@@ -2149,7 +2126,7 @@ index 36e3fbc727cd748aa138f52976154ba32954cd87..9ecfc504df089a74add168cd5a8376d7
+ // Purpur end
}
diff --git a/src/main/java/org/bukkit/inventory/RecipeChoice.java b/src/main/java/org/bukkit/inventory/RecipeChoice.java
-index 523818cbb0d6c90481ec97123e7fe0e2ff4eea14..bfeb8171a723d84b94bfaacd8aaf7d4d48ecd051 100644
+index db8bcc66bdc4bedfffb4705db6338eda4c0ad29a..feda3ddfaaf37b6ee218a0e0b1fbc199899bd364 100644
--- a/src/main/java/org/bukkit/inventory/RecipeChoice.java
+++ b/src/main/java/org/bukkit/inventory/RecipeChoice.java
@@ -10,6 +10,7 @@ import java.util.function.Predicate;
@@ -2246,10 +2223,10 @@ index 301e82369603f3dd6e6c1bd380da4bacacd7ef6c..0c6ca7588fb3d6b6497ddf032fe75e5c
/**
* This class was not meant to be constructed explicitly
diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
-index e4b6f278a811acbb0070e311c5c3bdaff7b00474..ee83ecb054099cb85168a9499dfe967a0a9ec796 100644
+index 653135352c104a6ddeb74a1b6d4916c6952d6271..46b0d02aa759b3735e6ac811523d459cf263aa8b 100644
--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
-@@ -65,6 +65,7 @@ public class LibraryLoader
+@@ -66,6 +66,7 @@ public class LibraryLoader
@Override
public void transferStarted(@NotNull TransferEvent event) throws TransferCancelledException
{
@@ -2257,7 +2234,7 @@ index e4b6f278a811acbb0070e311c5c3bdaff7b00474..ee83ecb054099cb85168a9499dfe967a
logger.log( Level.INFO, "Downloading {0}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName() );
}
} );
-@@ -80,6 +81,7 @@ public class LibraryLoader
+@@ -81,6 +82,7 @@ public class LibraryLoader
{
return null;
}
@@ -2265,7 +2242,7 @@ index e4b6f278a811acbb0070e311c5c3bdaff7b00474..ee83ecb054099cb85168a9499dfe967a
logger.log( Level.INFO, "[{0}] Loading {1} libraries... please wait", new Object[]
{
java.util.Objects.requireNonNullElseGet(desc.getPrefix(), desc::getName), desc.getLibraries().size() // Paper - use configured log prefix
-@@ -118,6 +120,7 @@ public class LibraryLoader
+@@ -119,6 +121,7 @@ public class LibraryLoader
}
jarFiles.add( url );
@@ -2274,10 +2251,10 @@ index e4b6f278a811acbb0070e311c5c3bdaff7b00474..ee83ecb054099cb85168a9499dfe967a
{
java.util.Objects.requireNonNullElseGet(desc.getPrefix(), desc::getName), file // Paper - use configured log prefix
diff --git a/src/main/java/org/bukkit/potion/PotionEffect.java b/src/main/java/org/bukkit/potion/PotionEffect.java
-index 037af5fd6d71a526c0e6620f2db0cd6df9625261..939ed1931492854c5854cab06730cf235eba7e89 100644
+index c8ab330ef171795d08fa201cf8320703c7f1c66b..93e2ea220dc03c122f82af65d5e9fda5b582290c 100644
--- a/src/main/java/org/bukkit/potion/PotionEffect.java
+++ b/src/main/java/org/bukkit/potion/PotionEffect.java
-@@ -32,12 +32,14 @@ public class PotionEffect implements ConfigurationSerializable {
+@@ -33,6 +33,7 @@ public class PotionEffect implements ConfigurationSerializable {
private static final String AMBIENT = "ambient";
private static final String PARTICLES = "has-particles";
private static final String ICON = "has-icon";
@@ -2285,34 +2262,46 @@ index 037af5fd6d71a526c0e6620f2db0cd6df9625261..939ed1931492854c5854cab06730cf23
private final int amplifier;
private final int duration;
private final PotionEffectType type;
- private final boolean ambient;
+@@ -40,6 +41,7 @@ public class PotionEffect implements ConfigurationSerializable {
private final boolean particles;
private final boolean icon;
+ private final PotionEffect hiddenEffect; // Paper
+ @Nullable private final NamespacedKey key; // Purpur
/**
* Creates a potion effect.
-@@ -50,6 +52,36 @@ public class PotionEffect implements ConfigurationSerializable {
+@@ -50,11 +52,12 @@ public class PotionEffect implements ConfigurationSerializable {
+ * @param ambient the ambient status, see {@link PotionEffect#isAmbient()}
+ * @param particles the particle status, see {@link PotionEffect#hasParticles()}
+ * @param icon the icon status, see {@link PotionEffect#hasIcon()}
++ * @param key the namespacedKey, see {@link PotionEffect#getKey()}
+ * @param hiddenEffect the hidden PotionEffect
+ * @hidden Internal-- hidden effects are only shown internally
+ */
+ @org.jetbrains.annotations.ApiStatus.Internal // Paper
+- public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon, @Nullable PotionEffect hiddenEffect) { // Paper
++ public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon, @Nullable PotionEffect hiddenEffect, @Nullable NamespacedKey key) { // Paper // Purpur
+ Preconditions.checkArgument(type != null, "effect type cannot be null");
+ this.type = type;
+ this.duration = duration;
+@@ -62,6 +65,7 @@ public class PotionEffect implements ConfigurationSerializable {
+ this.ambient = ambient;
+ this.particles = particles;
+ this.icon = icon;
++ this.key = key; // Purpur
+ // Paper start
+ this.hiddenEffect = hiddenEffect;
+ }
+@@ -77,10 +81,27 @@ public class PotionEffect implements ConfigurationSerializable {
* @param icon the icon status, see {@link PotionEffect#hasIcon()}
*/
public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon) {
-+ // Purpur start
-+ this(type, duration, amplifier, ambient, particles, icon, null);
-+ }
-+
-+ /**
-+ * Create a potion effect.
-+ * @param duration measured in ticks, see {@link
-+ * PotionEffect#getDuration()}
-+ * @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()}
-+ * @param ambient the ambient status, see {@link PotionEffect#isAmbient()}
-+ * @param particles the particle status, see {@link PotionEffect#hasParticles()}
-+ * @param key the namespacedKey, see {@link PotionEffect#getKey()}
-+ */
-+ public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, @Nullable NamespacedKey key) {
-+ this(type, duration, amplifier, ambient, particles, particles, key);
-+ }
-+
+- this(type, duration, amplifier, ambient, particles, icon, null);
++ this(type, duration, amplifier, ambient, particles, icon, null, null); // Purpur
+ // Paper end
+ }
+
++ // Purpur start
+ /**
+ * Creates a potion effect.
+ * @param type effect type
@@ -2325,24 +2314,19 @@ index 037af5fd6d71a526c0e6620f2db0cd6df9625261..939ed1931492854c5854cab06730cf23
+ * @param key the namespacedKey, see {@link PotionEffect#getKey()}
+ */
+ public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon, @Nullable NamespacedKey key) {
-+ // Purpur end
- Preconditions.checkArgument(type != null, "effect type cannot be null");
- this.type = type;
- this.duration = duration;
-@@ -57,6 +89,7 @@ public class PotionEffect implements ConfigurationSerializable {
- this.ambient = ambient;
- this.particles = particles;
- this.icon = icon;
-+ this.key = key; // Purpur - add key
- }
-
++ this(type, duration, amplifier, ambient, particles, icon, null, key);
++ }
++ // Purpur end
++
/**
-@@ -104,36 +137,43 @@ public class PotionEffect implements ConfigurationSerializable {
+ * Creates a potion effect with no defined color.
+ *
+@@ -126,33 +147,33 @@ public class PotionEffect implements ConfigurationSerializable {
* @param map the map to deserialize from
*/
public PotionEffect(@NotNull Map map) {
-- this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true)));
-+ this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true)), getKey(map)); // Purpur - getKey
+- this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true)), (PotionEffect) map.get(HIDDEN_EFFECT)); // Paper
++ this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true)), (PotionEffect) map.get(HIDDEN_EFFECT), getKey(map)); // Paper // Purpur - getKey
}
// Paper start
@@ -2376,6 +2360,10 @@ index 037af5fd6d71a526c0e6620f2db0cd6df9625261..939ed1931492854c5854cab06730cf23
- return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon);
+ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon, key); // Purpur - add key
}
+
+ /**
+@@ -169,6 +190,13 @@ public class PotionEffect implements ConfigurationSerializable {
+ }
// Paper end
+ // Purpur start
@@ -2388,7 +2376,7 @@ index 037af5fd6d71a526c0e6620f2db0cd6df9625261..939ed1931492854c5854cab06730cf23
@NotNull
private static PotionEffectType getEffectType(@NotNull Map, ?> map) {
PotionEffectType effect;
-@@ -166,17 +206,33 @@ public class PotionEffect implements ConfigurationSerializable {
+@@ -201,6 +229,17 @@ public class PotionEffect implements ConfigurationSerializable {
return def;
}
@@ -2406,35 +2394,28 @@ index 037af5fd6d71a526c0e6620f2db0cd6df9625261..939ed1931492854c5854cab06730cf23
@Override
@NotNull
public Map serialize() {
-- return ImmutableMap.builder()
-+ // Purpur start - add key, don't serialize if null.
-+ ImmutableMap.Builder builder = ImmutableMap.builder()
- .put(TYPE, type.getKey().toString())
- .put(DURATION, duration)
- .put(AMPLIFIER, amplifier)
- .put(AMBIENT, ambient)
- .put(PARTICLES, particles)
-- .put(ICON, icon)
-- .build();
-+ .put(ICON, icon);
-+ if(key != null) {
+@@ -215,6 +254,11 @@ public class PotionEffect implements ConfigurationSerializable {
+ if (this.hiddenEffect != null) {
+ builder.put(HIDDEN_EFFECT, this.hiddenEffect);
+ }
++ // Purpur start
++ if (key != null) {
+ builder.put(KEY, key.toString());
+ }
-+ return builder.build();
+ // Purpur end
+ return builder.build();
+ // Paper end
}
-
- /**
-@@ -200,7 +256,7 @@ public class PotionEffect implements ConfigurationSerializable {
+@@ -243,7 +287,7 @@ public class PotionEffect implements ConfigurationSerializable {
return false;
}
PotionEffect that = (PotionEffect) obj;
-- return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration && this.particles == that.particles && this.icon == that.icon;
-+ return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration && this.particles == that.particles && this.icon == that.icon && this.key == that.key; // Purpur - add key
+- return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration && this.particles == that.particles && this.icon == that.icon && java.util.Objects.equals(this.hiddenEffect, that.hiddenEffect); // Paper
++ return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration && this.particles == that.particles && this.icon == that.icon && java.util.Objects.equals(this.hiddenEffect, that.hiddenEffect) && this.key == that.key; // Paper // Purpur - add key
}
/**
-@@ -296,6 +352,24 @@ public class PotionEffect implements ConfigurationSerializable {
+@@ -339,6 +383,24 @@ public class PotionEffect implements ConfigurationSerializable {
return icon;
}
@@ -2459,12 +2440,12 @@ index 037af5fd6d71a526c0e6620f2db0cd6df9625261..939ed1931492854c5854cab06730cf23
@Override
public int hashCode() {
int hash = 1;
-@@ -310,6 +384,6 @@ public class PotionEffect implements ConfigurationSerializable {
+@@ -354,6 +416,6 @@ public class PotionEffect implements ConfigurationSerializable {
@Override
public String toString() {
-- return type.getName() + (ambient ? ":(" : ":") + duration + "t-x" + amplifier + (ambient ? ")" : "");
-+ return type.getName() + (ambient ? ":(" : ":") + duration + "t-x" + amplifier + (ambient ? ")" : "") + (hasKey() ? "(" + key + ")" : ""); // Purpur - add key if not null
+- return "PotionEffect{" + "amplifier=" + amplifier + ", duration=" + duration + ", type=" + type + ", ambient=" + ambient + ", particles=" + particles + ", icon=" + icon + ", hiddenEffect=" + hiddenEffect + '}'; // Paper
++ return "PotionEffect{" + "amplifier=" + amplifier + ", duration=" + duration + ", type=" + type + ", ambient=" + ambient + ", particles=" + particles + ", icon=" + icon + ", hiddenEffect=" + hiddenEffect + ", key=" + key + '}'; // Paper // Purpur - add key
}
}
diff --git a/src/main/java/org/bukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/util/permissions/CommandPermissions.java
diff --git a/patches/api/0003-Build-system-changes.patch b/patches/api/0003-Build-system-changes.patch
index 24a7893..1563af9 100644
--- a/patches/api/0003-Build-system-changes.patch
+++ b/patches/api/0003-Build-system-changes.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Build system changes
diff --git a/build.gradle.kts b/build.gradle.kts
-index 41d7b75e904b94073dfcd12b776a7759a963b66f..c37b8a63b050dcc2ad2b33955017df48120c4393 100644
+index 0a33275fdf16bda47771bab9ddfeb2bf8616c2dc..dfc2fe81a776acc490189d96c195dea1be7ca690 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -9,11 +9,13 @@ java {
@@ -15,55 +15,59 @@ index 41d7b75e904b94073dfcd12b776a7759a963b66f..c37b8a63b050dcc2ad2b33955017df48
+/* // Plazma - Use libs.versions.toml
val annotationsVersion = "24.0.1"
val bungeeCordChatVersion = "1.20-R0.1"
- val adventureVersion = "4.14.0"
- val slf4jVersion = "1.8.0-beta4"
+ val adventureVersion = "4.15.0"
+ val slf4jVersion = "2.0.9"
val log4jVersion = "2.17.1"
+ */ // Plazma - Use libs.versions.toml
val apiAndDocs: Configuration by configurations.creating {
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
-@@ -28,15 +30,39 @@ configurations.api {
+@@ -28,6 +30,7 @@ configurations.api {
dependencies {
// api dependencies are listed transitively to API consumers
+ /* // Plazma - Use libs.versions.toml
api("com.google.guava:guava:32.1.2-jre")
api("com.google.code.gson:gson:2.10.1")
- api("net.md-5:bungeecord-chat:$bungeeCordChatVersion-deprecated+build.14") // Paper
+ // Paper start - adventure
+@@ -38,9 +41,35 @@ dependencies {
api("org.yaml:snakeyaml:2.2")
api("org.joml:joml:1.10.5")
-+ */ // Plazma - Use libs.versions.toml
// Paper start
- api("com.googlecode.json-simple:json-simple:1.1.1") {
-+ api(api.jsonsimple) { // Plazma - Use libs.versions.toml
- isTransitive = false // includes junit
- }
+ // Plazma start
++ */
+ implementation(common.bundles.asm)
+
+ compileOnly(api.findbugs)
++ compileOnly(api.annotations)
+ compileOnly(common.bundles.maven)
+
-+ compileOnly(api.annotations)
+ compileOnlyApi(api.checkerqual)
-+ testCompileOnly(api.bundles.annotations)
+
+ testImplementation(common.asm.tree)
+ testImplementation(common.bundles.test)
+ testImplementation(common.commons.lang3)
+
++ testCompileOnly(api.bundles.annotations)
++
+ api(api.bundles.api)
+ api(common.snakeyaml)
+ api(common.log4j.api)
+ api(common.maven.provider)
-+ apiAndDocs(platform(common.adventure.bom))
++
+ apiAndDocs(common.bundles.adventure)
-+ /*
++ apiAndDocs(platform(common.adventure.bom))
++
++ api(api.jsonsimple) {
+ // Plazma end
+ isTransitive = false // includes junit
+ }
++ /* // Plazma - Use libs.versions.toml
api("it.unimi.dsi:fastutil:8.5.6")
apiAndDocs(platform("net.kyori:adventure-bom:$adventureVersion"))
apiAndDocs("net.kyori:adventure-api")
-@@ -73,6 +99,7 @@ dependencies {
+@@ -76,6 +105,7 @@ dependencies {
testImplementation("org.hamcrest:hamcrest:2.2")
testImplementation("org.mockito:mockito-core:5.5.0")
testImplementation("org.ow2.asm:asm-tree:9.5")
@@ -71,7 +75,7 @@ index 41d7b75e904b94073dfcd12b776a7759a963b66f..c37b8a63b050dcc2ad2b33955017df48
}
// Paper start
-@@ -133,25 +160,27 @@ tasks.withType {
+@@ -136,25 +166,27 @@ tasks.withType {
options.use()
options.isDocFilesSubDirs = true
options.links(
@@ -108,7 +112,7 @@ index 41d7b75e904b94073dfcd12b776a7759a963b66f..c37b8a63b050dcc2ad2b33955017df48
+ "https://javadoc.io/doc/org.apache.logging.log4j/log4j-api/${common.log4j.api.orNull?.version}/",
// Paper end
- "https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3", // Paper
-+ "https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/${common.maven.transport.orNull?.version}", // Paper
++ "https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/${common.maven.connector.orNull?.version}", // Paper
+ // Plazma end
)
options.tags("apiNote:a:API Note:")
diff --git a/patches/api/0004-Plazma-Configurations.patch b/patches/api/0004-Plazma-Configurations.patch
index 87f6199..35ec470 100644
--- a/patches/api/0004-Plazma-Configurations.patch
+++ b/patches/api/0004-Plazma-Configurations.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] Plazma Configurations
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
-index dd99f53e3d559685a4b3a454a9e607c310fc6aff..3a3713573ba37530449f9254c0a7205530c9737a 100644
+index 529fb1beadefc79ce6bf5755d5223301b9933152..c78eb34b20ed1a7bf793cfd4594219923c33f66f 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
-@@ -2202,6 +2202,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
+@@ -2210,6 +2210,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
}
// Purpur end
diff --git a/patches/api/0006-Implement-No-Chat-Reports.patch b/patches/api/0006-Implement-No-Chat-Reports.patch
index b21fe38..9f07ae6 100644
--- a/patches/api/0006-Implement-No-Chat-Reports.patch
+++ b/patches/api/0006-Implement-No-Chat-Reports.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] Implement No Chat Reports
diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java
-index 2eb13c049fa917d41fa9ad17fdec9ec4c33701a8..5d50f83a76affc74f989870ca1bc8d7a75f3b2ba 100644
+index f7f864a2b46129e4d61bc87f3e23c343417aa094..eb3cc41388a210f000bf637bfae135081bee51e9 100644
--- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java
+++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java
-@@ -215,6 +215,8 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
+@@ -216,6 +216,8 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
* Fallback cause
*/
UNKNOWN,
diff --git a/patches/generated-api/0001-Purpur-Generated-API-Changes.patch b/patches/generated-api/0001-Purpur-Generated-API-Changes.patch
new file mode 100644
index 0000000..772dcdc
--- /dev/null
+++ b/patches/generated-api/0001-Purpur-Generated-API-Changes.patch
@@ -0,0 +1,49 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: granny
+Date: Thu, 18 Jan 2024 21:01:12 +0900
+Subject: [PATCH] Purpur Generated API Changes
+
+PurpurMC
+Copyright (C) 2024 PurpurMC
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+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 069f2668f5229b0368b796e65eef1648fba0a097..9b991201a2f6cc9feccccf7f4e7bcded64117764 100644
+--- a/com/destroystokyo/paper/entity/ai/VanillaGoal.java
++++ b/com/destroystokyo/paper/entity/ai/VanillaGoal.java
+@@ -442,6 +442,18 @@ public interface VanillaGoal extends Goal {
+
+ GoalKey ZOMBIE_ATTACK_TURTLE_EGG = create("zombie_attack_turtle_egg", Zombie.class);
+
++ // Purpur start
++ GoalKey MOB_HAS_RIDER = GoalKey.of(Mob.class, NamespacedKey.minecraft("has_rider"));
++ GoalKey HORSE_HAS_RIDER = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("horse_has_rider"));
++ GoalKey LLAMA_HAS_RIDER = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_has_rider"));
++ GoalKey FIND_CRYSTAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("find_crystal"));
++ GoalKey ORBIT_CRYSTAL = GoalKey.of(Phantom.class, NamespacedKey.minecraft("orbit_crystal"));
++ GoalKey DROWNED_ATTACK_VILLAGER = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack_villager"));
++ GoalKey ZOMBIE_ATTACK_VILLAGER = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_villager"));
++ GoalKey AVOID_RABID_WOLF = GoalKey.of(Wolf.class, NamespacedKey.minecraft("avoid_rabid_wolf"));
++ GoalKey RECEIVE_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("receive_flower"));
++ // Purpur end
++
+ /**
+ * Removed in 1.20.2
+ */
diff --git a/patches/server/0001-Pufferfish-Server-Changes.patch b/patches/server/0001-Pufferfish-Server-Changes.patch
index ed2b980..f225b9b 100644
--- a/patches/server/0001-Pufferfish-Server-Changes.patch
+++ b/patches/server/0001-Pufferfish-Server-Changes.patch
@@ -1,10 +1,10 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kevin Raneri
-Date: Sat, 25 Nov 2023 11:51:41 +0000
+Date: Thu, 18 Jan 2024 22:51:22 +0900
Subject: [PATCH] Pufferfish Server Changes
-Original: Kevin Raneri
-Copyright (C) 2023 Pufferfish Studios LLC
+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
@@ -20,7 +20,7 @@ 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 64479f0a892d6847f987d844efe282a6080d607b..9525f76103136dfc900c70f97416864115f75ed5 100644
+index 444ff797c70b0e285d4272ea2ce3d72453c9bda5..fd785a79b1708aadd760f5b62d49d4d4e55e9938 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -13,8 +13,12 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) {
@@ -38,9 +38,9 @@ index 64479f0a892d6847f987d844efe282a6080d607b..9525f76103136dfc900c70f974168641
// Paper start
implementation("org.jline:jline-terminal-jansi:3.21.0")
implementation("net.minecrell:terminalconsoleappender:1.3.0")
-@@ -51,6 +55,13 @@ dependencies {
- runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3")
- runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.3")
+@@ -50,6 +54,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")
@@ -52,10 +52,10 @@ index 64479f0a892d6847f987d844efe282a6080d607b..9525f76103136dfc900c70f974168641
testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
testImplementation("org.hamcrest:hamcrest:2.2")
-@@ -58,6 +69,14 @@ dependencies {
+@@ -57,6 +68,14 @@ dependencies {
}
- val craftbukkitPackageVersion = "1_20_R2" // Paper
+ val craftbukkitPackageVersion = "1_20_R3" // Paper
+
+// Pufferfish Start
+tasks.withType {
@@ -67,7 +67,7 @@ index 64479f0a892d6847f987d844efe282a6080d607b..9525f76103136dfc900c70f974168641
tasks.jar {
archiveClassifier.set("dev")
-@@ -70,7 +89,7 @@ tasks.jar {
+@@ -69,7 +88,7 @@ tasks.jar {
attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main",
"Implementation-Title" to "CraftBukkit",
@@ -76,7 +76,7 @@ index 64479f0a892d6847f987d844efe282a6080d607b..9525f76103136dfc900c70f974168641
"Implementation-Vendor" to date, // Paper
"Specification-Title" to "Bukkit",
"Specification-Version" to project.version,
-@@ -210,7 +229,5 @@ val runtimeClasspathForRunDev = sourceSets.main.flatMap { src ->
+@@ -209,7 +228,5 @@ val runtimeClasspathForRunDev = sourceSets.main.flatMap { src ->
}
tasks.registerRunTask("runDev") {
description = "Spin up a non-relocated Mojang-mapped test server"
@@ -625,10 +625,10 @@ index 0000000000000000000000000000000000000000..020368da69b9a492155f6de6297f7473
+}
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..cc66657cb4f978aa2df3ca1be6c683759952cc7a
+index 0000000000000000000000000000000000000000..61f21c0bf6658326a15b735c22001b4028b98800
--- /dev/null
+++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java
-@@ -0,0 +1,294 @@
+@@ -0,0 +1,315 @@
+package gg.pufferfish.pufferfish;
+
+import gg.pufferfish.pufferfish.simd.SIMDDetection;
@@ -811,6 +811,28 @@ index 0000000000000000000000000000000000000000..cc66657cb4f978aa2df3ca1be6c68375
+ "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 enableAsyncWorldSaving;
++ public static boolean asyncWorldSavingInitialized;
++ private static void asyncWorldSaving() {
++ boolean temp = getBoolean("enable-async-world-saving", false,
++ "Save world changes asynchronously. This is disabled by default as it is not",
++ "100% confident that this will not cause world corruption issues.");
++
++ // This prevents us from changing the value during a reload.
++ if (!asyncWorldSavingInitialized) {
++ asyncWorldSavingInitialized = true;
++ enableAsyncWorldSaving = temp;
++ }
++ }
+
+ public static boolean enableSuffocationOptimization;
+ private static void suffocationOptimization() {
@@ -913,7 +935,6 @@ index 0000000000000000000000000000000000000000..cc66657cb4f978aa2df3ca1be6c68375
+ "the ender dragon whenever a player places an end crystal.");
+ }
+
-+
+ public static boolean disableMethodProfiler;
+ public static boolean disableOutOfOrderChat;
+ private static void miscSettings() {
@@ -1464,10 +1485,10 @@ index 0000000000000000000000000000000000000000..facd55463d44cb7e3d2ca6892982f549
+ }
+}
diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java
-index 8240bb085b619f257f8c0a25775e0b15068e440f..6d9668d993bb922ae9d2b76a4d766903cc3f98a4 100644
+index 200ed770b57e1a9240abf0473968d4b85cbefe3c..0acc7cfc0fb0264dd76a58f7582e79d83fa040eb 100644
--- a/src/main/java/io/papermc/paper/util/MCUtil.java
+++ b/src/main/java/io/papermc/paper/util/MCUtil.java
-@@ -213,7 +213,7 @@ public final class MCUtil {
+@@ -212,7 +212,7 @@ public final class MCUtil {
}
public static long getCoordinateKey(final Entity entity) {
@@ -1476,11 +1497,24 @@ index 8240bb085b619f257f8c0a25775e0b15068e440f..6d9668d993bb922ae9d2b76a4d766903
}
public static long getCoordinateKey(final ChunkPos pair) {
+diff --git a/src/main/java/net/minecraft/network/chat/SignedMessageChain.java b/src/main/java/net/minecraft/network/chat/SignedMessageChain.java
+index 85a8a687b1568a56e3e646b37ef78b562c1b8a82..69971b2c59e541ac4100b84c84e2972de1b44ca9 100644
+--- a/src/main/java/net/minecraft/network/chat/SignedMessageChain.java
++++ b/src/main/java/net/minecraft/network/chat/SignedMessageChain.java
+@@ -38,7 +38,7 @@ public class SignedMessageChain {
+ throw new SignedMessageChain.DecodeException(Component.translatable("chat.disabled.chain_broken"), false); // Paper - diff on change (if disconnects, need a new kick event cause)
+ } else if (playerPublicKey.data().hasExpired()) {
+ throw new SignedMessageChain.DecodeException(Component.translatable("chat.disabled.expiredProfileKey", org.bukkit.event.player.PlayerKickEvent.Cause.EXPIRED_PROFILE_PUBLIC_KEY), false); // Paper - kick event causes
+- } else if (body.timeStamp().isBefore(this.lastTimeStamp)) {
++ } else if (!gg.pufferfish.pufferfish.PufferfishConfig.disableOutOfOrderChat && body.timeStamp().isBefore(this.lastTimeStamp)) { // Pufferfish
+ throw new SignedMessageChain.DecodeException(Component.translatable("multiplayer.disconnect.out_of_order_chat", org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT), true); // Paper - kick event causes
+ } else {
+ this.lastTimeStamp = body.timeStamp();
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index 8f31413c939cc2b0454ad3d9a1b618dbae449d00..58d076e2a8fa1cf56c4c8d15a502e85fcf48aa90 100644
+index 016b7628b289fb882f3ec15dd5b0cb4e0af72edc..1343649cd77a42dd502747581050b401840a6efe 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -308,6 +308,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) {
AtomicReference atomicreference = new AtomicReference();
-@@ -1697,7 +1699,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop needsChangeBroadcasting = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>();
@@ -1540,7 +1587,7 @@ index caa73632aee15583c6b6ed12a668c8f49b794708..3abec84383a445d3ad0d3b5f613246b6
// 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) {
-@@ -1464,8 +1464,28 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1458,8 +1458,28 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
return ChunkMap.this.level.getServer().getScaledTrackingDistance(initialDistance);
}
@@ -1569,7 +1616,7 @@ index caa73632aee15583c6b6ed12a668c8f49b794708..3abec84383a445d3ad0d3b5f613246b6
Iterator iterator = this.entity.getIndirectPassengers().iterator();
while (iterator.hasNext()) {
-@@ -1477,6 +1497,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1471,6 +1491,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
i = j;
}
}
@@ -1580,10 +1627,10 @@ index caa73632aee15583c6b6ed12a668c8f49b794708..3abec84383a445d3ad0d3b5f613246b6
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 8c33a12ca879c46893150d6adfb8aa4d397c6b4c..5d26364c0f4ed03bd9994077683c93b9883e5327 100644
+index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..5cf74fe0214191d42e74fc104eba150a95894e0f 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-@@ -75,6 +75,9 @@ public class ServerChunkCache extends ChunkSource {
+@@ -73,6 +73,9 @@ public class ServerChunkCache extends ChunkSource {
final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap loadedChunkMap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(8192, 0.5f);
private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4];
@@ -1594,77 +1641,57 @@ index 8c33a12ca879c46893150d6adfb8aa4d397c6b4c..5d26364c0f4ed03bd9994077683c93b9
private static int getChunkCacheKey(int x, int z) {
return x & 3 | ((z & 3) << 2);
@@ -521,6 +524,7 @@ public class ServerChunkCache extends ChunkSource {
- ProfilerFiller gameprofilerfiller = this.level.getProfiler();
- gameprofilerfiller.push("pollingChunks");
+ // Paper - optimise chunk tick iteration
+
+ this.level.resetIceAndSnowTick(); // Pufferfish - reset ice & snow tick random
- int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
- boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && worlddata.getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
-
-@@ -530,28 +534,35 @@ public class ServerChunkCache extends ChunkSource {
- // Paper start - per player mob spawning
- 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
-- // re-set mob counts
-- 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;
-+ // Pufferfish start - moved down when async processing
-+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning) {
-+ // re-set mob counts
-+ 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;
+ if (this.level.getServer().tickRateManager().runsNormally()) {
+ gameprofilerfiller.popPush("naturalSpawnCount");
+ this.level.timings.countNaturalMobs.startTiming(); // Paper - timings
+@@ -529,6 +533,7 @@ public class ServerChunkCache extends ChunkSource {
+ 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
+@@ -543,14 +548,18 @@ public class ServerChunkCache extends ChunkSource {
}
-- player.mobBackoffCounts[ii] = newBackoff;
-+ // Paper end - per player mob spawning backoff
+ // Paper end - per player mob spawning backoff
}
-- // Paper end - per player mob spawning backoff
-+ lastSpawnState = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, null, true);
+- 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
}
-- spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, null, true);
-+ // Pufferfish end
- } else {
-- spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
-+ // Pufferfish start
-+ lastSpawnState = NaturalSpawner.createState(l, 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
- this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
+ // Paper end
+ this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
-- this.lastSpawnState = spawnercreature_d;
-+ //this.lastSpawnState = spawnercreature_d; // Pufferfish - this is managed asynchronously
- gameprofilerfiller.popPush("filteringLoadedChunks");
- // Paper - optimise chunk tick iteration
- // Paper - optimise chunk tick iteration
-@@ -644,8 +655,8 @@ public class ServerChunkCache extends ChunkSource {
- // Paper end - optimise chunk tick iteration
- if (tick && chunk1.chunkStatus.isOrAfter(net.minecraft.server.level.FullChunkStatus.ENTITY_TICKING)) { // Paper - optimise chunk tick iteration
- chunk1.incrementInhabitedTime(j);
-- if (spawn && flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration
-- NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
-+ if (spawn && flag2 && (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning || _pufferfish_spawnCountsReady.get()) && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration // Pufferfish
-+ NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1); // Pufferfish
- }
+- 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
- if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - optimise chunk tick iteration
-@@ -691,6 +702,40 @@ public class ServerChunkCache extends ChunkSource {
+@@ -640,8 +649,8 @@ public class ServerChunkCache extends ChunkSource {
+ if (tick && chunk1.chunkStatus.isOrAfter(net.minecraft.server.level.FullChunkStatus.ENTITY_TICKING)) {
+ // Paper end - optimise chunk tick iteration
+ chunk1.incrementInhabitedTime(j);
+- if (spawn && flag && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration
+- NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
++ if (spawn && flag && (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning || _pufferfish_spawnCountsReady.get()) && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration // Pufferfish
++ NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1); // Pufferfish
+ }
+
+ if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - optimise chunk tick iteration
+@@ -688,6 +697,40 @@ public class ServerChunkCache extends ChunkSource {
+ gameprofilerfiller.pop();
gameprofilerfiller.pop();
- this.chunkMap.tick();
}
+
+ // Pufferfish start - optimize mob spawning
@@ -1704,7 +1731,7 @@ index 8c33a12ca879c46893150d6adfb8aa4d397c6b4c..5d26364c0f4ed03bd9994077683c93b9
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 35674f92a67f93382103c2766df4b678ba5c862f..d46e61640b241d32df05240dedd2c23f138725e6 100644
+index b6e5a2fa247bdee2f681739a26630dff3fc6c51a..e385a62058204ba3b01ce594e7c180f9cc6cf664 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -177,7 +177,8 @@ public class ServerEntity {
@@ -1726,10 +1753,10 @@ index 35674f92a67f93382103c2766df4b678ba5c862f..d46e61640b241d32df05240dedd2c23f
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 c88d5b9125f6ee43bf2be60fd1745d836f271b78..945783d090e44ebed1d4968c1d1ec0b68f6d494f 100644
+index e0dae41eb94da08649cba607975798dc2ac328ad..f7215d0a67e9e024af0c040c796ebcbb4f76e885 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -878,6 +878,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -899,6 +899,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
org.spigotmc.ActivationRange.activateEntities(this); // Spigot
this.timings.entityTick.startTiming(); // Spigot
this.entityTickList.forEach((entity) -> {
@@ -1737,7 +1764,7 @@ index c88d5b9125f6ee43bf2be60fd1745d836f271b78..945783d090e44ebed1d4968c1d1ec0b6
if (!entity.isRemoved()) {
if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed
entity.discard();
-@@ -897,7 +898,20 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -918,7 +919,20 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
gameprofilerfiller.push("tick");
@@ -1759,7 +1786,7 @@ index c88d5b9125f6ee43bf2be60fd1745d836f271b78..945783d090e44ebed1d4968c1d1ec0b6
gameprofilerfiller.pop();
}
}
-@@ -962,9 +976,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -983,9 +997,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
// Paper start - optimise random block ticking
private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos();
@@ -1772,7 +1799,7 @@ index c88d5b9125f6ee43bf2be60fd1745d836f271b78..945783d090e44ebed1d4968c1d1ec0b6
public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
ChunkPos chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining();
-@@ -975,7 +991,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -996,7 +1012,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
gameprofilerfiller.push("thunder");
final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change
@@ -1781,11 +1808,44 @@ index c88d5b9125f6ee43bf2be60fd1745d836f271b78..945783d090e44ebed1d4968c1d1ec0b6
blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper
if (this.isRainingAt(blockposition)) {
+@@ -1491,7 +1507,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+
+ try (co.aikar.timings.Timing ignored = this.timings.worldSave.startTiming()) {
+ if (doFull) {
+- this.saveLevelData();
++ this.saveLevelData(true); // Pufferfish
+ }
+
+ this.timings.worldSaveChunks.startTiming(); // Paper
+@@ -1527,7 +1543,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ progressListener.progressStartNoAbort(Component.translatable("menu.savingLevel"));
+ }
+
+- this.saveLevelData();
++ this.saveLevelData(!close); // Pufferfish
+ if (progressListener != null) {
+ progressListener.progressStage(Component.translatable("menu.savingChunks"));
+ }
+@@ -1550,12 +1566,12 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ // CraftBukkit end
+ }
+
+- private void saveLevelData() {
++ private void saveLevelData(boolean async) { // Pufferfish
+ if (this.dragonFight != null) {
+ this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit
+ }
+
+- this.getChunkSource().getDataStorage().save();
++ this.getChunkSource().getDataStorage().save(async); // Pufferfish
+ }
+
+ public List extends T> getEntities(EntityTypeTest filter, Predicate super T> predicate) {
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-index 65bb221993147a558995b36fb835f7b82e0eb4bd..6cc9271ba058f4af759eae34e2f6e9f892b4f6da 100644
+index 8568de90c39838e1627f286c5c3ca4b0f19002cb..04b0eb391bb524dd7af14b862d89c0f2494a8206 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-@@ -1119,6 +1119,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1124,6 +1124,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
@Override
public void handleEditBook(ServerboundEditBookPacket packet) {
@@ -1793,14 +1853,19 @@ index 65bb221993147a558995b36fb835f7b82e0eb4bd..6cc9271ba058f4af759eae34e2f6e9f8
// Paper start
if (!this.cserver.isPrimaryThread()) {
List pageList = packet.getPages();
-@@ -2274,6 +2275,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
- }
+diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
+index f2a7cb6ebed7a4b4019a09af2a025f624f6fe9c9..47636aad5fa20d1c28d3520beb0729df9b30cf6c 100644
+--- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
++++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java
+@@ -224,7 +224,7 @@ public class WorldUpgrader {
+ }
+ }
- private boolean updateChatOrder(Instant timestamp) {
-+ if (gg.pufferfish.pufferfish.PufferfishConfig.disableOutOfOrderChat) return true;
- Instant instant1;
-
- do {
+- this.overworldDataStorage.save();
++ this.overworldDataStorage.save(false); // Pufferfish
+ i = Util.getMillis() - i;
+ WorldUpgrader.LOGGER.info("World optimizaton finished after {} ms", i);
+ this.finished = true;
diff --git a/src/main/java/net/minecraft/world/CompoundContainer.java b/src/main/java/net/minecraft/world/CompoundContainer.java
index 241fec02e6869c638d3a160819b32173a081467b..6a8f9e8f5bf108674c47018def28906e2d0a729c 100644
--- a/src/main/java/net/minecraft/world/CompoundContainer.java
@@ -1914,10 +1979,10 @@ index d6cbe98e67fdbf8db46338a88ab1356dd63b50a3..20dd3a63b2f955b05a75eb240e33ae4c
int LARGE_MAX_STACK_SIZE = 64;
int DEFAULT_DISTANCE_LIMIT = 8;
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index fece91254b10b59474056aa730fd420f90cd7bec..80c9a523e94704f73e833e2255af6b0bf55da454 100644
+index 14fbaef2215f7de4acb5303ad6f677b348f855d8..a8d8d261daed2ebbbea3f4f356434942997ba541 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -306,7 +306,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -309,7 +309,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
public double yo;
public double zo;
private Vec3 position;
@@ -1926,7 +1991,7 @@ index fece91254b10b59474056aa730fd420f90cd7bec..80c9a523e94704f73e833e2255af6b0b
private ChunkPos chunkPosition;
private Vec3 deltaMovement;
private float yRot;
-@@ -434,6 +434,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -440,6 +440,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
return this.originWorld;
}
// Paper end
@@ -1939,7 +2004,7 @@ index fece91254b10b59474056aa730fd420f90cd7bec..80c9a523e94704f73e833e2255af6b0b
public float getBukkitYaw() {
return this.yRot;
}
-@@ -798,6 +804,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -808,6 +814,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
public void tick() {
@@ -1952,7 +2017,7 @@ index fece91254b10b59474056aa730fd420f90cd7bec..80c9a523e94704f73e833e2255af6b0b
this.baseTick();
}
-@@ -4362,16 +4374,18 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -4410,16 +4422,18 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
public boolean updateFluidHeightAndDoFluidPushing(TagKey tag, double speed) {
@@ -1978,7 +2043,7 @@ index fece91254b10b59474056aa730fd420f90cd7bec..80c9a523e94704f73e833e2255af6b0b
double d1 = 0.0D;
boolean flag = this.isPushedByFluid();
boolean flag1 = false;
-@@ -4379,14 +4393,61 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -4427,14 +4441,61 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
int k1 = 0;
BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
@@ -2046,7 +2111,7 @@ index fece91254b10b59474056aa730fd420f90cd7bec..80c9a523e94704f73e833e2255af6b0b
if (d2 >= axisalignedbb.minY) {
flag1 = true;
-@@ -4408,9 +4469,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -4456,9 +4517,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
// CraftBukkit end
}
}
@@ -2060,10 +2125,10 @@ index fece91254b10b59474056aa730fd420f90cd7bec..80c9a523e94704f73e833e2255af6b0b
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 73871f456a85bda1e51f54986d0e61fb629822e8..2561e74ffdf595a9b6ae13dcd738662c772db442 100644
+index 081937597a8984b52a1e92d4c6032c04c942116e..0ffd377dba738bd651b0c7f5ca0a0d61aaa1d82c 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
-@@ -301,6 +301,8 @@ public class EntityType implements FeatureElement, EntityTypeT
+@@ -305,6 +305,8 @@ public class EntityType implements FeatureElement, EntityTypeT
private final boolean canSpawnFarFromPlayer;
private final int clientTrackingRange;
private final int updateInterval;
@@ -2073,7 +2138,7 @@ index 73871f456a85bda1e51f54986d0e61fb629822e8..2561e74ffdf595a9b6ae13dcd738662c
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 15e1d8c09fad181406a6acb8b3f177cd5e6c0f52..3b9ee3324a084271862ed790e8fc0d469e877ec1 100644
+index 4cbb1f5d904191e59395df0177e76e94faae764c..9b7e786d5ae6bdeeb96df6e9c4d1b24e1e856e58 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -142,7 +142,6 @@ import org.bukkit.event.entity.EntityTeleportEvent;
@@ -2084,7 +2149,7 @@ index 15e1d8c09fad181406a6acb8b3f177cd5e6c0f52..3b9ee3324a084271862ed790e8fc0d46
public abstract class LivingEntity extends Entity implements Attackable {
-@@ -414,7 +413,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -413,7 +412,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
boolean flag = this instanceof net.minecraft.world.entity.player.Player;
if (!this.level().isClientSide) {
@@ -2113,7 +2178,7 @@ index 15e1d8c09fad181406a6acb8b3f177cd5e6c0f52..3b9ee3324a084271862ed790e8fc0d46
@Override
public boolean hurt(DamageSource source, float amount) {
if (this.isInvulnerableTo(source)) {
-@@ -2004,6 +2016,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -2002,6 +2014,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
return this.lastClimbablePos;
}
@@ -2135,10 +2200,10 @@ index 15e1d8c09fad181406a6acb8b3f177cd5e6c0f52..3b9ee3324a084271862ed790e8fc0d46
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 956d05e2ae59978ea9623ca0e167c0afe0b87306..944c22ea172796492a683d2f2bddfb0938d7a8c9 100644
+index 0b5334004b9d0489e8465824870662b467ce321b..2f3dc569ff9cdead48aa831c96c027cc7255d609 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
-@@ -220,14 +220,16 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -221,14 +221,16 @@ public abstract class Mob extends LivingEntity implements Targeting {
return this.lookControl;
}
@@ -2157,7 +2222,7 @@ index 956d05e2ae59978ea9623ca0e167c0afe0b87306..944c22ea172796492a683d2f2bddfb09
this.targetSelector.tick();
}
}
-@@ -911,16 +913,20 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -912,16 +914,20 @@ public abstract class Mob extends LivingEntity implements Targeting {
if (i % 2 != 0 && this.tickCount > 1) {
this.level().getProfiler().push("targetSelector");
@@ -2245,7 +2310,7 @@ index b738ee2d3801fadfd09313f05ae24593e56b0ec6..1635818fc4b1788c0d397085239df6dd
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 34f319ad09276c6f68dde449c79351de0d7d86f5..a719af0b512d9ef243d0d54f3b744b1b1a5f2772 100644
+index 4bbc36404b396500df0d9db380cf223b5897662e..382e9d18b81bcbeb20cb3b828b66260f07a845e6 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
@@ -119,6 +119,7 @@ public abstract class MoveToBlockGoal extends Goal {
@@ -2282,10 +2347,10 @@ index c157309ac78e7af084d3acb6e8b2bcd469a39d5e..ac5e5676b194a2a99e5cf53eb89c1152
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 5beaa849a250ea005733250ad3edfa8382224667..2c91fe46355c9a201507de5577f693ed4f5fb974 100644
+index 6b614818b14ecfc8fc82b523eeb7e21fdf9bf1ba..8820905ac733a8915cc1697259b2bef14d97e471 100644
--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
-@@ -237,13 +237,22 @@ public class Bat extends AmbientCreature {
+@@ -241,13 +241,22 @@ public class Bat extends AmbientCreature {
}
}
@@ -2326,10 +2391,10 @@ index 5ad5f22e5aa26445e5eb229958e7bf356bdd460e..d241ca4d0295f9fce39c11197bd435cf
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 d5b97d4316390028f54aa9bb9fa52b0b003e32a0..b4793b88688bd568a428aa520e880f0038de45a7 100644
+index 387006271c246362b0df1bfcadca7b7096660003..9158c5a507904c46a8fe2fdad9a0b6ba3a9b2460 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
-@@ -280,9 +280,11 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder {
- return true;
+@@ -159,9 +159,11 @@ public class Frog extends Animal implements VariantHolder {
+
}
+ private int behaviorTick = 0; // Pufferfish
@@ -2390,7 +2455,7 @@ index 111a244087e24f25ba8524a46a228da10cd9498a..ff12ba2b79cb2e7e0bfd0e3b58ff6cb9
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 c9a4feb4a52c0eb621b120e5b8c18d0a74dae0cd..256598e058db1fd34d36390e45ab9903768343cb 100644
+index 68ecf0203e23cb6360d05bec18d9c1c413d84650..1f7f6e5995c00725bf66723c75620ec416e24f87 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
@@ -150,6 +150,13 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
@@ -2408,7 +2473,7 @@ index c9a4feb4a52c0eb621b120e5b8c18d0a74dae0cd..256598e058db1fd34d36390e45ab9903
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 bd5996eef2d946e9d7765b6b315bc5951158810e..0d51f435f18f3f9d59a3241a0b7fa1c4af841b72 100644
+index 30627f330536b5c89b52452981f0a960b61e4268..ebbd0031da656c4b12debbf76a347da2865d50d1 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
@@ -333,11 +333,17 @@ public class EnderMan extends Monster implements NeutralMob {
@@ -2464,10 +2529,10 @@ index 6407ddef8442fce4f310ac4babf3e3de0dd5fc9a..cfdc1650783d6855e0d4f33ec68aab48
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 b2bc3a832c310448046ccde37a04918aa6d63197..5e43912708f9074dee1bb351efa737a7e6796fc3 100644
+index 9f1b7c629644931074293151ed58a523ca6d488c..58a7e61e02b7d72326ed4d57ee514adb63b3873c 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 {
+@@ -273,11 +273,13 @@ public class Warden extends Monster implements VibrationSystem {
}
@@ -2482,7 +2547,7 @@ index b2bc3a832c310448046ccde37a04918aa6d63197..5e43912708f9074dee1bb351efa737a7
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 cbe2a37f74f4fb2abd0b3297699e54335aaed64f..2460768aaa7b8e6d183c03c1f0f2ccd6cb61a16f 100644
+index e12f1f11386fa723f62b51ed0cc5715c1812d2bf..1e6d61673b0e3252129c04edcfa1d7d436e8ecbe 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
@@ -2516,7 +2581,7 @@ index cbe2a37f74f4fb2abd0b3297699e54335aaed64f..2460768aaa7b8e6d183c03c1f0f2ccd6
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 96d664c28738d6090f7067761c2978dd1aa0fd0e..b1c24a02b87aca7b180a6efbce177f2300db49c1 100644
+index 309acf7bd07e38043aa81e0e686edba1136bd04c..deabb3400ee2406a8ec179a96d8cfd86f8edbbd6 100644
--- a/src/main/java/net/minecraft/world/entity/player/Inventory.java
+++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java
@@ -687,6 +687,8 @@ public class Inventory implements Container, Nameable {
@@ -2548,10 +2613,10 @@ index 96d664c28738d6090f7067761c2978dd1aa0fd0e..b1c24a02b87aca7b180a6efbce177f23
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 a90317100d32974e481e14476843f66997a2cf3a..cd0629581bae5f805842157af36c2d838e01bee3 100644
+index 5b6d5c799cc8e601a01b6967917e15ba1e2db721..f0a6251cc8f612b898231e505c47fd5b2bbb4973 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
-@@ -44,6 +44,36 @@ public abstract class Projectile extends Entity implements TraceableEntity {
+@@ -45,6 +45,36 @@ public abstract class Projectile extends Entity implements TraceableEntity {
super(type, world);
}
@@ -2589,7 +2654,7 @@ index a90317100d32974e481e14476843f66997a2cf3a..cd0629581bae5f805842157af36c2d83
if (entity != null) {
this.ownerUUID = entity.getUUID();
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
-index 00187fbbeddfc17e1b6887f8bf0f50da23938470..f64edfdb03f99624daf1e05b5dc86d845c3018b6 100644
+index 6d23c39e4eadf23616080d6d08672e13b5d3c37d..e7115f1635821e0aab32e8aeea6914388dc24639 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
@@ -27,7 +27,10 @@ import org.bukkit.inventory.InventoryHolder;
@@ -2636,7 +2701,7 @@ index 00187fbbeddfc17e1b6887f8bf0f50da23938470..f64edfdb03f99624daf1e05b5dc86d84
}
diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
-index 5a19875cbc603acea95193d969d2e1dc1e0bfd78..3688e9f8c6c6d1239095e3a87060ccca90386d0c 100644
+index e1696f6b77df4c8fceaece64701d4db78b0a4c42..faa3f62d22266a3c32d6c95c3ffebd4aa3880739 100644
--- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java
+++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
@@ -55,7 +55,7 @@ public class EndCrystalItem extends Item {
@@ -2645,11 +2710,11 @@ index 5a19875cbc603acea95193d969d2e1dc1e0bfd78..3688e9f8c6c6d1239095e3a87060ccca
- if (enderdragonbattle != null) {
+ if (enderdragonbattle != null && gg.pufferfish.pufferfish.PufferfishConfig.allowEndCrystalRespawn) { // Pufferfish
- enderdragonbattle.tryRespawn(aboveBlockPosition); // Paper - pass placed end crystal position to pre-check proximity to portal
+ 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 38f7d1ece27ec1a3deda21fb6a6f0e788c8ed718..252fc22844682c0f67dc02a87478e01e49b6430d 100644
+index 27b0a79f7a7c47047216aae42944bac2a2151181..a097cfc528f709c80575f35483b6878314ea2717 100644
--- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
+++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
@@ -26,8 +26,13 @@ public class ShapelessRecipe extends io.papermc.paper.inventory.recipe.RecipeBoo
@@ -2696,19 +2761,19 @@ index 38f7d1ece27ec1a3deda21fb6a6f0e788c8ed718..252fc22844682c0f67dc02a87478e01e
autorecipestackmanager.initialize(this); // Paper - better exact choice recipes
int i = 0;
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 2354a0e5d15e9be633d9fe3a1a9feefe7b9b7782..99e1c645871be28d130319b65700a1b8db093de4 100644
+index b05e11e6b091c7616df5a9bbef867b06cafe3dc3..2902c29cd7f0b99b84cff3664fc4ec15a383e41b 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -210,6 +210,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -212,6 +212,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ // Paper end
public abstract ResourceKey getTypeKey();
-
++
+ protected final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(java.util.concurrent.ThreadLocalRandom.current().nextLong()); public net.minecraft.util.RandomSource getThreadUnsafeRandom() { return this.randomTickRandom; } // Pufferfish - move thread unsafe random initialization // Pufferfish - getter
-+
- 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 - Async-Anti-Xray - Pass executor
+
+ 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; Async-Anti-Xray: Pass executor
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
- this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper
-@@ -1308,13 +1310,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1318,13 +1320,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
try {
tickConsumer.accept(entity);
MinecraftServer.getServer().executeMidTickTasks(); // Paper - execute chunk tasks mid tick
@@ -2724,7 +2789,7 @@ index 2354a0e5d15e9be633d9fe3a1a9feefe7b9b7782..99e1c645871be28d130319b65700a1b8
// Paper end
}
}
-@@ -1779,6 +1781,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1798,6 +1800,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
public ProfilerFiller getProfiler() {
@@ -2733,7 +2798,7 @@ index 2354a0e5d15e9be633d9fe3a1a9feefe7b9b7782..99e1c645871be28d130319b65700a1b8
}
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
-index 3cdddda9c0618e95288b81b975d499c8dd30c05f..9c2d62feff1816f5729060c6192269a5b2d34153 100644
+index dc211c6aedc178ac50b7d05aab3662c422211cbd..3fb96de68b93e8d33bd5ab9137e5d4facc94d788 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
@@ -429,12 +429,12 @@ public final class NaturalSpawner {
@@ -2754,7 +2819,7 @@ index 3cdddda9c0618e95288b81b975d499c8dd30c05f..9c2d62feff1816f5729060c6192269a5
return new BlockPos(i, l, j);
}
diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java
-index 65012a12e1430956ef55ced56773e6354ac26444..ed439b7e94646141c93a7dd3704d1cdeb5c27e16 100644
+index 4f9187d9d640618c40a2fa528f36b845017b4777..efca73d4de33028cf9df944f36e51b7b50f7a4c5 100644
--- a/src/main/java/net/minecraft/world/level/biome/Biome.java
+++ b/src/main/java/net/minecraft/world/level/biome/Biome.java
@@ -66,14 +66,20 @@ public final class Biome {
@@ -2881,7 +2946,7 @@ index a71414397bd45ee7bcacfeef0041d80dfa25f114..d66806565770cb03a21794f99e5c4b0f
@Override
diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
-index d4dcf7fe26474ae07374e7761d823bc5c8b54f97..1d13fabb3f34023b4fbb1be9ad02ebc606645531 100644
+index df1c1c27b7c0065f8179d59bdb9de01dde22befa..1ddae39df4e7cb36db412ebdec8ca9d2818450a9 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -47,7 +47,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@@ -2940,23 +3005,22 @@ index d4dcf7fe26474ae07374e7761d823bc5c8b54f97..1d13fabb3f34023b4fbb1be9ad02ebc6
private static boolean isFullContainer(Container inventory, Direction direction) {
+ if (true) return inventory.isCompletelyFull(direction); // Pufferfish - use bitsets
- // Paper start - optimize hoppers
+ // Paper start - Perf: Optimize Hoppers
if (inventory instanceof WorldlyContainer worldlyContainer) {
for (final int slot : worldlyContainer.getSlotsForFace(direction)) {
-@@ -513,7 +540,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
+@@ -513,7 +540,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
private static boolean isEmptyContainer(Container inv, Direction facing) {
-- return allMatch(inv, facing, IS_EMPTY_TEST);
-+ // Paper start
+- return allMatch(inv, facing, IS_EMPTY_TEST); // Paper - Perf: Optimize Hoppers
+ // Pufferfish start - use bitsets
-+ //return allMatch(inv, facing, IS_EMPTY_TEST);
++ //return allMatch(inv, facing, IS_EMPTY_TEST); // Paper - Perf: Optimize Hoppers
+ return inv.isCompletelyEmpty(facing);
+ // Pufferfish end
}
public static boolean suckInItems(Level world, Hopper hopper) {
-@@ -713,7 +744,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
+@@ -713,7 +743,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
if (HopperBlockEntity.canPlaceItemInContainer(to, stack, slot, side)) {
boolean flag = false;
@@ -2965,7 +3029,7 @@ index d4dcf7fe26474ae07374e7761d823bc5c8b54f97..1d13fabb3f34023b4fbb1be9ad02ebc6
if (itemstack1.isEmpty()) {
// Spigot start - SPIGOT-6693, InventorySubcontainer#setItem
-@@ -908,7 +939,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
+@@ -908,7 +938,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@Override
protected void setItems(NonNullList list) {
@@ -2978,13 +3042,13 @@ index d4dcf7fe26474ae07374e7761d823bc5c8b54f97..1d13fabb3f34023b4fbb1be9ad02ebc6
public static void entityInside(Level world, BlockPos pos, BlockState state, Entity entity, HopperBlockEntity blockEntity) {
diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
-index 3e638f12956e57548f76c7e2403ba370f7baa249..02364a148b347e3669275553004391e31d77c0b5 100644
+index a94300a457b25f0e33a8eeabba6dd5720ca9ab1e..b41635dd0569ff7df909df492d3e850aef7214be 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
-@@ -96,12 +96,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
+@@ -94,12 +94,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
public boolean isEmpty() {
this.unpackLootTable((Player)null);
- // Paper start
+ // Paper start - Perf: Optimize Hoppers
- for (final ItemStack itemStack : this.getItems()) {
- if (!itemStack.isEmpty()) {
- return false;
@@ -2992,11 +3056,11 @@ index 3e638f12956e57548f76c7e2403ba370f7baa249..02364a148b347e3669275553004391e3
- }
- return true;
+ return this.isCompletelyEmpty(null); // Pufferfish - use super
- // Paper end
+ // Paper end - Perf: Optimize Hoppers
}
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 fa170cc1ce7011d201295b89718292d696c7fc24..7fd68d4aba72b15b2e21e5c88b44e677b794fe57 100644
+index 27e8ee4507460b1cc72de692b41562b9f4f13929..1afac69b5bc7055d2adb07aea4755b87b246275c 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 {
@@ -3028,7 +3092,7 @@ index fa170cc1ce7011d201295b89718292d696c7fc24..7fd68d4aba72b15b2e21e5c88b44e677
// 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 f0de72afad4bb571153436399386a6a8a70582a6..45b7527341fcb6d24f35318cedb522646b5ee1c2 100644
+index 9da74764a91bea7822c0444b48623b23e038d3f2..37228dc74463dddcc55301489c41aa253017f2d4 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -25,6 +25,7 @@ public class LevelChunkSection {
@@ -3165,6 +3229,57 @@ index e21f4c5aff3a8e97101f6efc1349fbecf326b5ea..c55f51e6db55f9fa66f53eef0e7a56af
return flag;
}
+diff --git a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java
+index 697df9a9f050c0130246ce2b08a859965bddf184..6df6a6bd89979bcd728e2f5bec948437d6ff9498 100644
+--- a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java
++++ b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java
+@@ -29,17 +29,28 @@ public abstract class SavedData {
+ return this.dirty;
+ }
+
+- public void save(File file) {
++ public void save(File file) { save(file, false); } // Pufferfish
++ public void save(File file, boolean async) { // Pufferfish
+ if (this.isDirty()) {
+ CompoundTag compoundTag = new CompoundTag();
+ compoundTag.put("data", this.save(new CompoundTag()));
+ NbtUtils.addCurrentDataVersion(compoundTag);
+
++ // Pufferfish start
++ Runnable writeRunnable = () -> {
+ try {
+ NbtIo.writeCompressed(compoundTag, file.toPath());
+ } catch (IOException var4) {
+ LOGGER.error("Could not save data {}", this, var4);
+ }
++ };
++
++ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncWorldSaving && async) {
++ net.minecraft.Util.ioPool().execute(writeRunnable);
++ } else {
++ writeRunnable.run();
++ }
++ // Pufferfish end
+
+ this.setDirty(false);
+ }
+diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
+index d051e8c1db6b5c42b8df0be54d9d48ba0e7b0077..6488a61bb05b0f2af23c77bc6df7c3014042ec5e 100644
+--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
++++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
+@@ -118,10 +118,10 @@ public class DimensionDataStorage {
+ return bl;
+ }
+
+- public void save() {
++ public void save(boolean async) { // Pufferfish
+ this.cache.forEach((id, state) -> {
+ if (state != null) {
+- state.save(this.getDataFile(id));
++ state.save(this.getDataFile(id), async); // Pufferfish
+ }
+
+ });
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 e43d07ccdd36f0c9f5b8e9c74cf0d87e17eec66a..8e441f7c2b2d911a0c0111aaa231fc6adae08730 100644
--- a/src/main/java/net/minecraft/world/level/storage/loot/LootParams.java
@@ -3269,10 +3384,10 @@ index ebe65474a4a05ff1637d7f37ebcfe690af59def5..42142c512b12e5b269c19f1e821c50e7
@Nullable
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
-index 356107688a5d40d1c462b164f61af82f4dfd3926..2ecb8bfd98c141e9f5e7f4e441c8df91e1b9fbc2 100644
+index 9ef8f911632598fd589368cedde268c8abcad3b6..cfc41926305441cb36ed67a8cb7e327cd80ff301 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
-@@ -269,7 +269,7 @@ import javax.annotation.Nullable; // Paper
+@@ -264,7 +264,7 @@ import javax.annotation.Nullable; // Paper
import javax.annotation.Nonnull; // Paper
public final class CraftServer implements Server {
@@ -3281,7 +3396,7 @@ index 356107688a5d40d1c462b164f61af82f4dfd3926..2ecb8bfd98c141e9f5e7f4e441c8df91
private final String serverVersion;
private final String bukkitVersion = Versioning.getBukkitVersion();
private final Logger logger = Logger.getLogger("Minecraft");
-@@ -1124,6 +1124,11 @@ public final class CraftServer implements Server {
+@@ -1120,6 +1120,11 @@ public final class CraftServer implements Server {
plugin.getPluginMeta().getDisplayName(),
"This plugin is not properly shutting down its async tasks when it is being shut down. This task may throw errors during the final shutdown logs and might not complete before process dies."
));
@@ -3306,10 +3421,10 @@ index 96d772eb02f79f8c478f5e6f065e387aa7665b18..c5ce412f321b8b4f31cc042893659e21
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
-index 548c77592a3520e8053483644eba805079a14f1a..397c10f64db3a4d7296fe18585b56851bc3a1f01 100644
+index ec2396f0e5d62b10450eaa7239a8c5479638b3c3..c909efd2060dc95bd3ecb8c9fec36a1e69a642ff 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
-@@ -485,7 +485,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
+@@ -482,7 +482,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
@Override
public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() {
@@ -3332,7 +3447,7 @@ index 774556a62eb240da42e84db4502e2ed43495be17..80553face9c70c2a3d897681e7761df8
if (stream != null) {
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
-index 59103744ac6beeb12719fdefcda54eeff498229e..c0333ba8e57cd284bb8ab15181da6b39d55872f9 100644
+index 2d31752478636bd21bbff5b430e5acb76b5d91c2..651063863b451d24ffe39f0a4d8db296e58ff585 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;
@@ -3391,8 +3506,8 @@ index 59103744ac6beeb12719fdefcda54eeff498229e..c0333ba8e57cd284bb8ab15181da6b39
if ( entity instanceof LivingEntity )
{
LivingEntity living = (LivingEntity) entity;
-- if ( living.onClimbable() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 ) // Paper
-+ if ( living.onClimableCached() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 ) // Paper // Pufferfish - use cached
+- 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/0002-Purpur-Server-Changes.patch
index 475cf3d..039c552 100644
--- a/patches/server/0002-Purpur-Server-Changes.patch
+++ b/patches/server/0002-Purpur-Server-Changes.patch
@@ -1,10 +1,10 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: William Blake Galbreath
-Date: Sat, 25 Nov 2023 11:56:59 +0000
+From: granny
+Date: Thu, 18 Jan 2024 22:51:23 +0900
Subject: [PATCH] Purpur Server Changes
-Original: PurpurMC
-Copyright (C) 2023 PurpurMC
+PurpurMC
+Copyright (C) 2024 PurpurMC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -25,7 +25,7 @@ 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 9525f76103136dfc900c70f97416864115f75ed5..f083d422678f5fd21825439944af888fbdc9bf3c 100644
+index fd785a79b1708aadd760f5b62d49d4d4e55e9938..5b8a28969451b12c4fc66976afd052ffa5805932 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -13,12 +13,12 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) {
@@ -45,7 +45,7 @@ index 9525f76103136dfc900c70f97416864115f75ed5..f083d422678f5fd21825439944af888f
// Paper start
implementation("org.jline:jline-terminal-jansi:3.21.0")
implementation("net.minecrell:terminalconsoleappender:1.3.0")
-@@ -62,6 +62,10 @@ dependencies {
+@@ -61,6 +61,10 @@ dependencies {
}
// Pufferfish end
@@ -56,7 +56,7 @@ index 9525f76103136dfc900c70f97416864115f75ed5..f083d422678f5fd21825439944af888f
testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
testImplementation("org.hamcrest:hamcrest:2.2")
-@@ -89,7 +93,7 @@ tasks.jar {
+@@ -88,7 +92,7 @@ tasks.jar {
attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main",
"Implementation-Title" to "CraftBukkit",
@@ -65,7 +65,7 @@ index 9525f76103136dfc900c70f97416864115f75ed5..f083d422678f5fd21825439944af888f
"Implementation-Vendor" to date, // Paper
"Specification-Title" to "Bukkit",
"Specification-Version" to project.version,
-@@ -173,7 +177,7 @@ fun TaskContainer.registerRunTask(
+@@ -172,7 +176,7 @@ fun TaskContainer.registerRunTask(
name: String,
block: JavaExec.() -> Unit
): TaskProvider = register(name) {
@@ -74,7 +74,7 @@ index 9525f76103136dfc900c70f97416864115f75ed5..f083d422678f5fd21825439944af888f
mainClass.set("org.bukkit.craftbukkit.Main")
standardInput = System.`in`
workingDir = rootProject.layout.projectDirectory
-@@ -229,5 +233,7 @@ val runtimeClasspathForRunDev = sourceSets.main.flatMap { src ->
+@@ -228,5 +232,7 @@ val runtimeClasspathForRunDev = sourceSets.main.flatMap { src ->
}
tasks.registerRunTask("runDev") {
description = "Spin up a non-relocated Mojang-mapped test server"
@@ -314,10 +314,10 @@ index c5d5648f4ca603ef2b1df723b58f9caf4dd3c722..3cb56595822799926a8141e60a42f5d1
.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 a08c00b8c0488d18be5e182f7892e5ab71d12247..338f693d098b6ab507c30f6411c9a952c34ba8e3 100644
+index cfe6a6f6bcfd7a3b29ab25f5a6745d31c18f338d..c168658d4d4ec1ddd80425e786d4435fd6576637 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 {
+@@ -137,6 +137,10 @@ public class MobGoalHelper {
static {
// TODO these kinda should be checked on each release, in case obfuscation changes
deobfuscationMap.put("abstract_skeleton_1", "abstract_skeleton_melee");
@@ -329,7 +329,7 @@ index a08c00b8c0488d18be5e182f7892e5ab71d12247..338f693d098b6ab507c30f6411c9a952
ignored.add("goal_selector_1");
ignored.add("goal_selector_2");
diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java
-index fa56cd09102a89692b42f1d14257990508c5c720..f9251183df72ddc56662fd3f02acf21641a2200c 100644
+index 066b9e4c4f0e7773548eda045cdd1ca8445221d2..92eaba96135ccddb7d682dab7e82cde9318a48ef 100644
--- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java
+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java
@@ -58,7 +58,7 @@ public class RAMDetails extends JList {
@@ -344,14 +344,14 @@ index fa56cd09102a89692b42f1d14257990508c5c720..f9251183df72ddc56662fd3f02acf216
@@ -67,7 +67,7 @@ public class RAMDetails extends JList {
vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)");
vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb");
- vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.tickTimes)) + " ms");
+ vector.add("Avg tick: " + DECIMAL_FORMAT.format(this.getAverage(server.getTickTimesNanos())) + " ms");
- vector.add("TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg));
+ vector.add("TPS from last 5s, 1m, 5m, 15m: " + String.join(", ", tpsAvg)); // Purpur
setListData(vector);
}
diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java
-index cc66657cb4f978aa2df3ca1be6c683759952cc7a..9ca1494497ae53e56b1f81fda51b0b8bd02a6d03 100644
+index 61f21c0bf6658326a15b735c22001b4028b98800..43397712cb13df5be3081c05eaa1a57c57f12c60 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 {
@@ -371,7 +371,7 @@ index cc66657cb4f978aa2df3ca1be6c683759952cc7a..9ca1494497ae53e56b1f81fda51b0b8b
if (configFile.exists()) {
try {
-@@ -224,7 +225,7 @@ public class PufferfishConfig {
+@@ -246,7 +247,7 @@ public class PufferfishConfig {
public static int activationDistanceMod;
private static void dynamicActivationOfBrains() throws IOException {
@@ -380,7 +380,7 @@ index cc66657cb4f978aa2df3ca1be6c683759952cc7a..9ca1494497ae53e56b1f81fda51b0b8b
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.");
-@@ -268,7 +269,7 @@ public class PufferfishConfig {
+@@ -290,7 +291,7 @@ public class PufferfishConfig {
public static boolean throttleInactiveGoalSelectorTick;
private static void inactiveGoalSelectorThrottle() {
@@ -390,10 +390,10 @@ index cc66657cb4f978aa2df3ca1be6c683759952cc7a..9ca1494497ae53e56b1f81fda51b0b8b
"This can improve performance by a few percent, but has minor gameplay implications.");
}
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
-index abd0217cf0bff183c8e262edc173a53403797c1a..2519ad2884b6c09b312432b933c31476b369e599 100644
+index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..e1ffd62f4ebceecb9bc5471df3da406cffea0483 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
-@@ -1315,9 +1315,9 @@ public final class ChunkHolderManager {
+@@ -1316,9 +1316,9 @@ public final class ChunkHolderManager {
}
public boolean processTicketUpdates() {
@@ -687,10 +687,10 @@ index 0000000000000000000000000000000000000000..a7d1ae53eac94bc2dcf8bc78ef1da0d3
+ }
+}
diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java
-index 1d714d3eff11ed14f218656008190017494d4830..ed3527612315e6e0649182ce4e1ae2834b0918a9 100644
+index e047dee632022abfe05865d1e71838be8d5d053a..888e31a0454888c36cb27602a28619f1f6dbf2c0 100644
--- a/src/main/java/net/minecraft/CrashReport.java
+++ b/src/main/java/net/minecraft/CrashReport.java
-@@ -123,6 +123,10 @@ public class CrashReport {
+@@ -125,6 +125,10 @@ public class CrashReport {
StringBuilder stringbuilder = new StringBuilder();
stringbuilder.append("---- Minecraft Crash Report ----\n");
@@ -702,10 +702,10 @@ index 1d714d3eff11ed14f218656008190017494d4830..ed3527612315e6e0649182ce4e1ae283
stringbuilder.append(CrashReport.getErrorComment());
stringbuilder.append("\n\n");
diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java
-index 56ae02aab93b9a698e9d2f07a0448aa4767169d9..106b27d507b16297a0a88b3b5beaaf3d0ef7e2c6 100644
+index ec4152f7372ddad216039a489fb5d72f963b4f18..7b20d0bfc54f93f0538275d89ae84d0f186db5a5 100644
--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java
+++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java
-@@ -223,6 +223,19 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy
+@@ -230,6 +230,19 @@ public class CommandSourceStack implements ExecutionCommandSource parseresults, String s, String label) { // CraftBukkit
+@@ -326,9 +334,9 @@ public class Commands {
+ public void performCommand(ParseResults parseresults, String s, String label) { // CraftBukkit
CommandSourceStack commandlistenerwrapper = (CommandSourceStack) parseresults.getContext().getSource();
- commandlistenerwrapper.getServer().getProfiler().push(() -> {
@@ -793,19 +793,19 @@ index 3eec879bf3975636739b2491cc05b8177032d16d..2fd376789bb24b14101e289733631a9a
return "/" + s;
- });
+ });*/ // Purpur
+ ContextChain contextchain = this.finishParsing(parseresults, s, commandlistenerwrapper, label); // CraftBukkit // Paper - make finishParsing not static
- byte b0;
-
-@@ -402,7 +410,7 @@ public class Commands {
- b0 = 0;
+ try {
+@@ -357,7 +365,7 @@ public class Commands {
+ Commands.LOGGER.error("'/{}' threw an exception", s, exception);
}
} finally {
- commandlistenerwrapper.getServer().getProfiler().pop();
+ //commandlistenerwrapper.getServer().getProfiler().pop(); // Purpur
}
- return b0;
-@@ -462,6 +470,7 @@ public class Commands {
+ }
+@@ -507,6 +515,7 @@ public class Commands {
private void runSync(ServerPlayer player, Collection bukkit, RootCommandNode rootcommandnode) {
// Paper end - Async command map building
new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(player.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper
@@ -813,7 +813,7 @@ index 3eec879bf3975636739b2491cc05b8177032d16d..2fd376789bb24b14101e289733631a9a
PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit));
event.getPlayer().getServer().getPluginManager().callEvent(event);
-@@ -472,6 +481,7 @@ public class Commands {
+@@ -517,6 +526,7 @@ public class Commands {
}
}
// CraftBukkit end
@@ -822,7 +822,7 @@ index 3eec879bf3975636739b2491cc05b8177032d16d..2fd376789bb24b14101e289733631a9a
}
diff --git a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java
-index 73c15a0c56a103ba4e62f0a51af8d42566b07245..d630c5a1aed706265d1e077da540c0bf723b838d 100644
+index 676a1499747b071515479130875157263d3a8352..fc1bba350030c076405711716e9830f8ae7f3953 100644
--- a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java
+++ b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java
@@ -200,10 +200,10 @@ public class EntitySelector {
@@ -875,8 +875,65 @@ index 73c15a0c56a103ba4e62f0a51af8d42566b07245..d630c5a1aed706265d1e077da540c0bf
+ }
+ // Purpur end
}
+diff --git a/src/main/java/net/minecraft/commands/execution/tasks/BuildContexts.java b/src/main/java/net/minecraft/commands/execution/tasks/BuildContexts.java
+index 89f0f68b3e2be64bcbf8b173a51d56ea3a3fb4ea..d1c7effca3592a234925657136f750717d696873 100644
+--- a/src/main/java/net/minecraft/commands/execution/tasks/BuildContexts.java
++++ b/src/main/java/net/minecraft/commands/execution/tasks/BuildContexts.java
+@@ -43,9 +43,9 @@ public class BuildContexts> {
+ ChainModifiers chainModifiers = flags;
+ List list = sources;
+ if (contextChain.getStage() != Stage.EXECUTE) {
+- context.profiler().push(() -> {
++ /*context.profiler().push(() -> { // Purpur
+ return "prepare " + this.commandInput;
+- });
++ });*/ // Purpur
+
+ try {
+ for(int i = context.forkLimit(); contextChain.getStage() != Stage.EXECUTE; contextChain = contextChain.nextStage()) {
+@@ -88,13 +88,13 @@ public class BuildContexts> {
+ }
+ }
+ } finally {
+- context.profiler().pop();
++ // context.profiler().pop(); // Purpur
+ }
+ }
+
+ if (list.isEmpty()) {
+ if (chainModifiers.isReturn()) {
+- context.queueNext(new CommandQueueEntry<>(frame, FallthroughTask.instance()));
++ context.queueNext(new CommandQueueEntry<>(frame, (EntryAction) FallthroughTask.instance())); // Purpur - decompile error
+ }
+
+ } else {
+diff --git a/src/main/java/net/minecraft/commands/execution/tasks/ExecuteCommand.java b/src/main/java/net/minecraft/commands/execution/tasks/ExecuteCommand.java
+index 821dc4aeaf48460000682604fba51b340b9738e7..3aa2ce6a2a3d3cdfc372a60419a09f49002339da 100644
+--- a/src/main/java/net/minecraft/commands/execution/tasks/ExecuteCommand.java
++++ b/src/main/java/net/minecraft/commands/execution/tasks/ExecuteCommand.java
+@@ -23,9 +23,9 @@ public class ExecuteCommand> implements Unbo
+
+ @Override
+ public void execute(T executionCommandSource, ExecutionContext executionContext, Frame frame) {
+- executionContext.profiler().push(() -> {
++ /*executionContext.profiler().push(() -> { // Purpur
+ return "execute " + this.commandInput;
+- });
++ });*/ // Purpur
+
+ try {
+ executionContext.incrementCost();
+@@ -37,7 +37,7 @@ public class ExecuteCommand> implements Unbo
+ } catch (CommandSyntaxException var9) {
+ executionCommandSource.handleError(var9, this.modifiers.isForked(), executionContext.tracer());
+ } finally {
+- executionContext.profiler().pop();
++ // executionContext.profiler().pop(); // Purpur
+ }
+
+ }
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
-index 83cab746d1d6fe25c043c8aee28c39412b90c127..ec6b58dae525c81bbb1c0e2d96fbded6f00a45b5 100644
+index c47aa87db42dea74a2e07ffe6015257fa337da23..fb672028548fbc3c026c3823024249e4e804be01 100644
--- a/src/main/java/net/minecraft/core/BlockPos.java
+++ b/src/main/java/net/minecraft/core/BlockPos.java
@@ -48,6 +48,12 @@ public class BlockPos extends Vec3i {
@@ -923,10 +980,10 @@ index 392406722b0a040c1d41fdc1154d75d39f6e9c86..b805e57d5a67d77d226cd8154e970050
throw new IllegalStateException("Unable to get CCW facing of " + this);
}
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
-index a0c7c6208314d981e8577ad69ef1c5193290a085..603eac94296c32d87dccf2c6b5fd7183864346f2 100644
+index 8e13c661a06aa2f7b5f558d39fb9e989a8145904..316fc3f81a1aee1cf67e14422d0d0557b3019b78 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
-@@ -1188,6 +1188,23 @@ public interface DispenseItemBehavior {
+@@ -1194,6 +1194,23 @@ public interface DispenseItemBehavior {
}
}
});
@@ -951,20 +1008,20 @@ index a0c7c6208314d981e8577ad69ef1c5193290a085..603eac94296c32d87dccf2c6b5fd7183
static Vec3 getEntityPokingOutOfBlockPos(BlockSource pointer, EntityType> entityType, Direction direction) {
diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
-index e17090003988ad2c890d48666c2234b14d511345..433f1f11b8b92c7d48352416f79ab5a394c33287 100644
+index 8d65cdb013706a932c2c73231108b2810b99e1c7..5b1938fc849db743e65cd7eed0f83ba059b9525e 100644
--- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
-@@ -107,7 +107,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior {
+@@ -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.MOB_LOOTING, CraftItemStack.asNMSCopy(craftItem)))); // Purpur
+ if (event.isCancelled()) {
+ // Paper end - Add drops to shear events
continue;
- }
- // CraftBukkit end
-- ishearable.shear(SoundSource.BLOCKS);
-+ ishearable.shear(SoundSource.BLOCKS, net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.MOB_LOOTING, CraftItemStack.asNMSCopy(craftItem))); // Purpur
- worldserver.gameEvent((Entity) null, GameEvent.SHEAR, blockposition);
- return true;
- }
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
-index c0ea20dcee8bb293df96bc6ee019e50ad6b383fd..ff99d6fa919391d43b7737a2819cf9ebb7e134da 100644
+index 2ae08b21c63490bbf8cd870f9585d82ed131f815..b7a6c7e737e7aba0324a5c3c61bbfbcc3b39ac43 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -569,11 +569,20 @@ public class Connection extends SimpleChannelInboundHandler> {
@@ -989,10 +1046,10 @@ index c0ea20dcee8bb293df96bc6ee019e50ad6b383fd..ff99d6fa919391d43b7737a2819cf9eb
}
// Paper end
diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
-index 2e395962b555bef0ce1a98e1d768e7738f011535..40f51062624161892c780ddae05e22859e2cd021 100644
+index b863249ff7e13cf4939c8961601f0564c62fd661..bdcfd80f937c34956911373905d66424bbff8e1d 100644
--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java
+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
-@@ -94,6 +94,8 @@ public class FriendlyByteBuf extends ByteBuf {
+@@ -95,6 +95,8 @@ public class FriendlyByteBuf extends ByteBuf {
private static final int MAX_PUBLIC_KEY_LENGTH = 512;
private static final Gson GSON = new Gson();
@@ -1001,7 +1058,7 @@ index 2e395962b555bef0ce1a98e1d768e7738f011535..40f51062624161892c780ddae05e2285
public FriendlyByteBuf(ByteBuf parent) {
this.source = parent;
}
-@@ -632,6 +634,17 @@ public class FriendlyByteBuf extends ByteBuf {
+@@ -640,6 +642,17 @@ public class FriendlyByteBuf extends ByteBuf {
this.writeBoolean(false);
} else {
this.writeBoolean(true);
@@ -1020,10 +1077,10 @@ index 2e395962b555bef0ce1a98e1d768e7738f011535..40f51062624161892c780ddae05e2285
this.writeId(BuiltInRegistries.ITEM, item);
diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
-index 9a49f5271ec1d9de17632bfffe8309cb1ba0d8b1..0be239c5c78432a6377cd7828cd49f61f8f0ac8f 100644
+index 3e2d5dcd62775b6ed7c0ce0ba51a71b635b1d644..166cd0f8e72189d10e56cd7bc095409aa919840e 100644
--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
-@@ -49,7 +49,7 @@ public class PacketUtils {
+@@ -50,7 +50,7 @@ public class PacketUtils {
if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590
if (listener.shouldHandleMessage(packet)) {
co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings
@@ -1031,7 +1088,7 @@ index 9a49f5271ec1d9de17632bfffe8309cb1ba0d8b1..0be239c5c78432a6377cd7828cd49f61
+ try { // Paper - timings // Purpur
packet.handle(listener);
} catch (Exception exception) {
- if (exception instanceof ReportedException) {
+ label25:
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 9ec6145fe04ec64bbee8ec6a837719caebdbc6f5..358d610ad020cada1bb83e393deeeaaec05a2791 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java
@@ -1046,10 +1103,10 @@ index 9ec6145fe04ec64bbee8ec6a837719caebdbc6f5..358d610ad020cada1bb83e393deeeaae
public ClientboundSetTimePacket(long time, long timeOfDay, boolean doDaylightCycle) {
this.gameTime = time;
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index 58d076e2a8fa1cf56c4c8d15a502e85fcf48aa90..b61c4d1ebb9c15a7ecd7bec5eb864851c053fb7e 100644
+index 1343649cd77a42dd502747581050b401840a6efe..6f94f01da0a2294f6fdc564653dde1fdbf508153 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -288,6 +288,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue();
public int autosavePeriod;
public Commands vanillaCommandDispatcher;
-@@ -297,10 +298,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop {
+ return false;
+ } : this::haveTime);
- this.profiler.popPush("nextTickWait");
+ //this.profiler.popPush("nextTickWait"); // Purpur
this.mayHaveDelayedTasks = true;
-- this.delayedTasksMaxNextTickTime = Math.max(Util.getMillis() + 50L, this.nextTickTime);
-+ // Purpur start - tps catchup
-+ if (org.purpurmc.purpur.PurpurConfig.tpsCatchup) {
-+ this.delayedTasksMaxNextTickTime = Math.max(Util.getMillis() + 50L, this.nextTickTime);
-+ } else {
-+ this.delayedTasksMaxNextTickTime = this.nextTickTime = curTime / 1000000L + 50L;
-+ }
-+ // Purpur end - tps catchup
+ this.delayedTasksMaxNextTickTimeNanos = Math.max(Util.getNanos() + i, this.nextTickTimeNanos);
+ // Pufferfish start - tps catchup
+- if (!gg.pufferfish.pufferfish.PufferfishConfig.tpsCatchup) {
++ if (!org.purpurmc.purpur.PurpurConfig.tpsCatchup || !gg.pufferfish.pufferfish.PufferfishConfig.tpsCatchup) {
+ this.nextTickTimeNanos = curTime + i;
+ this.delayedTasksMaxNextTickTimeNanos = nextTickTimeNanos;
+ }
+ // Pufferfish end
++ // Purpur start - tps catchup
++ //if (org.purpurmc.purpur.PurpurConfig.tpsCatchup) {
++ // this.delayedTasksMaxNextTickTimeNanos = Math.max(Util.getNanos() + i, this.nextTickTimeNanos);
++ //} else {
++ // this.delayedTasksMaxNextTickTimeNanos = this.nextTickTimeNanos = curTime + i;
++ //}
++ // Purpur end - tps catchup
this.waitUntilNextTick();
+ if (flag) {
+ this.tickRateManager.endTickWork();
+ }
+
- this.profiler.pop();
- this.endMetricsRecordingTick();
+ //this.profiler.pop(); // Purpur
+ //this.endMetricsRecordingTick(); // Purpur
this.isReady = true;
- JvmProfiler.INSTANCE.onServerTick(this.averageTickTime);
+ JvmProfiler.INSTANCE.onServerTick(this.smoothedTickTimeMillis);
}
-@@ -1322,7 +1347,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0;
try {
this.isSaving = true;
-@@ -1404,20 +1429,20 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop {
entityplayer.connection.suspendFlushing();
});
@@ -1285,7 +1375,7 @@ index 58d076e2a8fa1cf56c4c8d15a502e85fcf48aa90..b61c4d1ebb9c15a7ecd7bec5eb864851
// Paper start - Folia scheduler API
((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).tick();
getAllLevels().forEach(level -> {
-@@ -1486,22 +1511,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper
- net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper
+ 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.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
+ worldserver.hasRidableMoveEvent = org.purpurmc.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur
@@ -1372,9 +1462,9 @@ index 58d076e2a8fa1cf56c4c8d15a502e85fcf48aa90..b61c4d1ebb9c15a7ecd7bec5eb864851
- worldserver.timings.doTick.stopTiming(); // Spigot
+ //worldserver.timings.doTick.stopTiming(); // Spigot // Purpur
} catch (Throwable throwable) {
- // Spigot Start
- CrashReport crashreport;
-@@ -1569,33 +1596,33 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
-+ return org.purpurmc.purpur.PurpurConfig.serverModName; // Purpur - Purpur > Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
++ return org.purpurmc.purpur.PurpurConfig.serverModName; // Purpur - Purpur > // Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
}
public SystemReport fillSystemReport(SystemReport details) {
-@@ -2274,7 +2301,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop {
this.executeBlocking(() -> {
this.saveDebugReport(path.resolve("server"));
-@@ -2524,40 +2551,40 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop {
final io.papermc.paper.adventure.ChatDecorationProcessor processor = new io.papermc.paper.adventure.ChatDecorationProcessor(this, sender, commandSourceStack, message);
-@@ -2782,7 +2818,7 @@ 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)) {
@@ -1601,13 +1673,13 @@ index e38e2e5a7ddba9c140f362021b6be0b0974f7cd1..533a348acb53c8e7590f3d81c19e53a6
// Paper end
}
diff --git a/src/main/java/net/minecraft/server/ServerFunctionManager.java b/src/main/java/net/minecraft/server/ServerFunctionManager.java
-index d10abd28c522612934aada8124e5bb67a9b4e9da..097ac55028d66ef9ab430ff5dd103db6e3b99fc7 100644
+index df0c15f6b5b2224d53e4f8fad42b9a1e5f33dc25..5dd0dcb47211cec69189115bf4eab1dffc3ca8cf 100644
--- a/src/main/java/net/minecraft/server/ServerFunctionManager.java
+++ b/src/main/java/net/minecraft/server/ServerFunctionManager.java
-@@ -60,10 +60,10 @@ public class ServerFunctionManager {
+@@ -53,10 +53,10 @@ public class ServerFunctionManager {
}
- private void executeTagFunctions(Collection functions, ResourceLocation label) {
+ private void executeTagFunctions(Collection> functions, ResourceLocation label) {
- ProfilerFiller gameprofilerfiller = this.server.getProfiler();
+ //ProfilerFiller gameprofilerfiller = this.server.getProfiler(); // Purpur
@@ -1617,48 +1689,37 @@ index d10abd28c522612934aada8124e5bb67a9b4e9da..097ac55028d66ef9ab430ff5dd103db6
Iterator iterator = functions.iterator();
while (iterator.hasNext()) {
-@@ -72,7 +72,7 @@ public class ServerFunctionManager {
- this.execute(customfunction, this.getGameLoopSender());
+@@ -65,15 +65,15 @@ public class ServerFunctionManager {
+ this.execute(commandfunction, this.getGameLoopSender());
}
- this.server.getProfiler().pop();
+ //this.server.getProfiler().pop(); // Purpur
}
- public int execute(CommandFunction function, CommandSourceStack source) {
-@@ -97,7 +97,7 @@ public class ServerFunctionManager {
- } else {
- int i;
+ public void execute(CommandFunction function, CommandSourceStack source) {
+- ProfilerFiller gameprofilerfiller = this.server.getProfiler();
++ // ProfilerFiller gameprofilerfiller = this.server.getProfiler(); // Purpur
-- try (co.aikar.timings.Timing timing = function.getTiming().startTiming()) { // Paper
-+ try /*(co.aikar.timings.Timing timing = function.getTiming().startTiming())*/ { // Paper // Purpur
- this.context = new ServerFunctionManager.ExecutionContext(tracer);
- i = this.context.runTopCommand(customfunction1, source);
- } finally {
-@@ -195,10 +195,10 @@ public class ServerFunctionManager {
+- gameprofilerfiller.push(() -> {
++ /*gameprofilerfiller.push(() -> { // Purpur
+ return "function " + function.id();
+- });
++ });*/ // Purpur
- try {
- ServerFunctionManager.QueuedCommand customfunctiondata_queuedcommand = (ServerFunctionManager.QueuedCommand) this.commandQueue.removeFirst();
-- ProfilerFiller gameprofilerfiller = ServerFunctionManager.this.server.getProfiler();
-+ //ProfilerFiller gameprofilerfiller = ServerFunctionManager.this.server.getProfiler(); // Purpur
+ try {
+ InstantiatedFunction instantiatedfunction = function.instantiate((CompoundTag) null, this.getDispatcher(), source);
+@@ -86,7 +86,7 @@ public class ServerFunctionManager {
+ } catch (Exception exception) {
+ ServerFunctionManager.LOGGER.warn("Failed to execute function {}", function.id(), exception);
+ } finally {
+- gameprofilerfiller.pop();
++ // gameprofilerfiller.pop(); // Purpur
+ }
- Objects.requireNonNull(customfunctiondata_queuedcommand);
-- gameprofilerfiller.push(customfunctiondata_queuedcommand::toString);
-+ //gameprofilerfiller.push(customfunctiondata_queuedcommand::toString); // Purpur
- this.depth = customfunctiondata_queuedcommand.depth;
- customfunctiondata_queuedcommand.execute(ServerFunctionManager.this, this.commandQueue, i, this.tracer);
- if (this.abortCurrentDepth) {
-@@ -217,7 +217,7 @@ public class ServerFunctionManager {
-
- this.nestedCalls.clear();
- } finally {
-- ServerFunctionManager.this.server.getProfiler().pop();
-+ //ServerFunctionManager.this.server.getProfiler().pop(); // Purpur
- }
-
- ++j;
+ }
diff --git a/src/main/java/net/minecraft/server/commands/EnchantCommand.java b/src/main/java/net/minecraft/server/commands/EnchantCommand.java
-index 664cbce2e06fcb95d3d3d6c5302fc9119f938925..bc9778c705d23acd84fa1cdeff6b403b4cda3686 100644
+index 37d9c354af887c474094b1a364782007a5f2035d..ec86231077f6a1e03068507555539c5b550ddf31 100644
--- a/src/main/java/net/minecraft/server/commands/EnchantCommand.java
+++ b/src/main/java/net/minecraft/server/commands/EnchantCommand.java
@@ -48,7 +48,7 @@ public class EnchantCommand {
@@ -1703,7 +1764,7 @@ index 5cb15e2209d7b315904a1fc6d650ce1e75584271..7e21db60f3ace2a19686d6ea04b994ec
for(ServerPlayer serverPlayer : targets) {
diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java
-index d601d287e94a59ff93b8a83a44dac02544d211df..0ff3b06a98b2f4514b2d861b92dd70fe678ae86c 100644
+index 1b459a8ee8a6bc039e742d65796bc76660a1c765..599172b994d75484f7c7e0ce6d3d3d771c1c44d0 100644
--- a/src/main/java/net/minecraft/server/commands/GiveCommand.java
+++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java
@@ -59,6 +59,7 @@ public class GiveCommand {
@@ -1713,9 +1774,9 @@ index d601d287e94a59ff93b8a83a44dac02544d211df..0ff3b06a98b2f4514b2d861b92dd70fe
+ if (org.purpurmc.purpur.PurpurConfig.disableGiveCommandDrops) continue; // Purpur - add config option for toggling give command dropping
if (flag && itemstack1.isEmpty()) {
itemstack1.setCount(1);
- entityitem = entityplayer.drop(itemstack1, false, false, false); // SPIGOT-2942: Add boolean to call event
+ entityitem = entityplayer.drop(itemstack1, false, false, false); // CraftBukkit - SPIGOT-2942: Add boolean to call event
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-index e5c955e7e99bc07199feabfe9f0301016ad38b84..5c6027a3ab7c52087dfebb1e21468a511ec09fa1 100644
+index 80e1dcef1eeb33f553c7d771a00d463e99e3f147..7cc19060c24ad191b7dca779a18fbfbb65763189 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -99,6 +99,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -1726,10 +1787,10 @@ index e5c955e7e99bc07199feabfe9f0301016ad38b84..5c6027a3ab7c52087dfebb1e21468a51
new com.destroystokyo.paper.console.PaperConsole(DedicatedServer.this).start();
/*
jline.console.ConsoleReader bufferedreader = DedicatedServer.this.reader;
-@@ -218,9 +219,19 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
+@@ -219,8 +220,18 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
thread.start(); // Paper - start console thread after MinecraftServer.console & PaperConfig are initialized
- io.papermc.paper.command.PaperCommands.registerCommands(this);
- com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics();
+ io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command
+ com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics
+ // Purpur start
+ try {
+ org.purpurmc.purpur.PurpurConfig.init((java.io.File) options.valueOf("purpur-settings"));
@@ -1739,9 +1800,8 @@ index e5c955e7e99bc07199feabfe9f0301016ad38b84..5c6027a3ab7c52087dfebb1e21468a51
+ }
+ org.purpurmc.purpur.PurpurConfig.registerCommands();
+ // Purpur end
- com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
- io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider
- // Paper end
+ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
+ io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // Paper - init PaperBrigadierProvider
+ 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
@@ -1805,10 +1865,10 @@ index e5c955e7e99bc07199feabfe9f0301016ad38b84..5c6027a3ab7c52087dfebb1e21468a51
@Override
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
-index c5598adb8cbcbcf7277c2fd4dd72c243d44d9700..cda4544ae96a4fcb5c6c4483df67a59f1b53fd27 100644
+index 1643186bcb2caf5d29fd551afd35830726dbb80a..d53e0b67d847dfec2f4b118b5ca3f0ed1dc29ad6 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java
-@@ -58,6 +58,7 @@ public class DedicatedServerProperties extends Settings list = Lists.newArrayList();
List list1 = this.level.players();
ObjectIterator objectiterator = this.entityMap.values().iterator();
@@ -2024,7 +2084,7 @@ index 3abec84383a445d3ad0d3b5f613246b6ac7ee741..3771caa73b0b41428f3d629aca1f562d
ChunkMap.TrackedEntity playerchunkmap_entitytracker;
-@@ -1213,17 +1213,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1212,17 +1212,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
playerchunkmap_entitytracker.serverEntity.sendChanges();
}
}
@@ -2046,10 +2106,19 @@ index 3abec84383a445d3ad0d3b5f613246b6ac7ee741..3771caa73b0b41428f3d629aca1f562d
}
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-index 5d26364c0f4ed03bd9994077683c93b9883e5327..43a46feb5fb4bf23d71bc4f6c08caa93b1959ffc 100644
+index 5cf74fe0214191d42e74fc104eba150a95894e0f..c3c47857515a7f75d69c718f352d8bae4b2c1d26 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-@@ -279,16 +279,16 @@ public class ServerChunkCache extends ChunkSource {
+@@ -73,7 +73,7 @@ public class ServerChunkCache extends ChunkSource {
+ final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap loadedChunkMap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(8192, 0.5f);
+
+ private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4];
+-
++
+ public boolean firstRunSpawnCounts = true; // Pufferfish
+ public final java.util.concurrent.atomic.AtomicBoolean _pufferfish_spawnCountsReady = new java.util.concurrent.atomic.AtomicBoolean(false); // Pufferfish - optimize countmobs
+
+@@ -277,16 +277,16 @@ public class ServerChunkCache extends ChunkSource {
return ifLoaded;
}
// Paper end
@@ -2069,7 +2138,7 @@ index 5d26364c0f4ed03bd9994077683c93b9883e5327..43a46feb5fb4bf23d71bc4f6c08caa93
CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper
ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor;
-@@ -298,10 +298,10 @@ public class ServerChunkCache extends ChunkSource {
+@@ -296,10 +296,10 @@ public class ServerChunkCache extends ChunkSource {
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.pushChunkWait(this.level, x1, z1); // Paper - rewrite chunk system
// Paper end
com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info
@@ -2082,7 +2151,7 @@ index 5d26364c0f4ed03bd9994077683c93b9883e5327..43a46feb5fb4bf23d71bc4f6c08caa93
} // Paper
ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> {
return ichunkaccess1;
-@@ -450,17 +450,17 @@ public class ServerChunkCache extends ChunkSource {
+@@ -448,17 +448,17 @@ public class ServerChunkCache extends ChunkSource {
public void save(boolean flush) {
this.runDistanceManagerUpdates();
@@ -2104,7 +2173,7 @@ index 5d26364c0f4ed03bd9994077683c93b9883e5327..43a46feb5fb4bf23d71bc4f6c08caa93
}
// Paper end
-@@ -477,36 +477,36 @@ public class ServerChunkCache extends ChunkSource {
+@@ -475,37 +475,37 @@ public class ServerChunkCache extends ChunkSource {
// CraftBukkit start - modelled on below
public void purgeUnload() {
if (true) return; // Paper - tickets will be removed later, this behavior isn't really well accounted for by the chunk system
@@ -2140,6 +2209,7 @@ index 5d26364c0f4ed03bd9994077683c93b9883e5327..43a46feb5fb4bf23d71bc4f6c08caa93
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
@@ -2154,62 +2224,61 @@ index 5d26364c0f4ed03bd9994077683c93b9883e5327..43a46feb5fb4bf23d71bc4f6c08caa93
this.clearCache();
}
-@@ -521,15 +521,15 @@ public class ServerChunkCache extends ChunkSource {
- this.chunkMap.tick();
- } else {
- LevelData worlddata = this.level.getLevelData();
+@@ -515,19 +515,19 @@ public class ServerChunkCache extends ChunkSource {
+
+ this.lastInhabitedUpdate = i;
+ if (!this.level.isDebug()) {
- ProfilerFiller gameprofilerfiller = this.level.getProfiler();
+ //ProfilerFiller gameprofilerfiller = this.level.getProfiler(); // Purpur
- gameprofilerfiller.push("pollingChunks");
+- gameprofilerfiller.push("filteringLoadedChunks");
+ //gameprofilerfiller.push("pollingChunks"); // Purpur
++ //gameprofilerfiller.push("filteringLoadedChunks"); // Purpur
+ // Paper - optimise chunk tick iteration
+- 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 - optimise chunk tick iteration
+
this.level.resetIceAndSnowTick(); // Pufferfish - reset ice & snow tick random
- int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
- boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && worlddata.getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
-
-- gameprofilerfiller.push("naturalSpawnCount");
-- this.level.timings.countNaturalMobs.startTiming(); // Paper - timings
-+ //gameprofilerfiller.push("naturalSpawnCount"); // Purpur
-+ //this.level.timings.countNaturalMobs.startTiming(); // Paper - timings // Purpur
- int l = this.distanceManager.getNaturalSpawnChunkCount();
- // Paper start - per player mob spawning
- NaturalSpawner.SpawnState spawnercreature_d; // moved down
-@@ -560,17 +560,17 @@ public class ServerChunkCache extends ChunkSource {
- // Pufferfish end
- }
- // Paper end
-- this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
-+ //this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings // Purpur
-
- //this.lastSpawnState = spawnercreature_d; // Pufferfish - this is managed asynchronously
-- gameprofilerfiller.popPush("filteringLoadedChunks");
-+ //gameprofilerfiller.popPush("filteringLoadedChunks"); // Purpur
- // Paper - optimise chunk tick iteration
- // Paper - optimise chunk tick iteration
-- this.level.timings.chunkTicks.startTiming(); // Paper
-+ //this.level.timings.chunkTicks.startTiming(); // Paper // Purpur
-
- // Paper - optimise chunk tick iteration
-
-- gameprofilerfiller.popPush("spawnAndTick");
-+ //gameprofilerfiller.popPush("spawnAndTick"); // Purpur
- boolean flag2 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
-
- // Paper start - optimise chunk tick iteration
-@@ -672,17 +672,17 @@ public class ServerChunkCache extends ChunkSource {
+ if (this.level.getServer().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 - per player mob spawning
+ int naturalSpawnChunkCount = k;
+@@ -557,10 +557,10 @@ public class ServerChunkCache extends ChunkSource {
+ // Pufferfish end
+ }
+ // Paper end
+- this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
++ // this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings // Purpur
+
+ // 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
+
+ // Paper start - optimise chunk tick iteration
+@@ -666,19 +666,19 @@ public class ServerChunkCache extends ChunkSource {
+ }
+ }
+ // Paper end - optimise chunk tick iteration
+- 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
}
- }
- // Paper end - optimise chunk tick iteration
-- this.level.timings.chunkTicks.stopTiming(); // Paper
-- gameprofilerfiller.popPush("customSpawners");
-+ //this.level.timings.chunkTicks.stopTiming(); // Paper // Purpur
-+ //gameprofilerfiller.popPush("customSpawners"); // Purpur
- if (flag2) {
-- 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
}
- gameprofilerfiller.popPush("broadcast");
@@ -2220,7 +2289,7 @@ index 5d26364c0f4ed03bd9994077683c93b9883e5327..43a46feb5fb4bf23d71bc4f6c08caa93
// Paper start - optimise chunk tick iteration
if (!this.chunkMap.needsChangeBroadcasting.isEmpty()) {
it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet copy = this.chunkMap.needsChangeBroadcasting.clone();
-@@ -696,10 +696,10 @@ public class ServerChunkCache extends ChunkSource {
+@@ -692,12 +692,12 @@ public class ServerChunkCache extends ChunkSource {
}
}
// Paper end - optimise chunk tick iteration
@@ -2231,10 +2300,13 @@ index 5d26364c0f4ed03bd9994077683c93b9883e5327..43a46feb5fb4bf23d71bc4f6c08caa93
- gameprofilerfiller.pop();
+ //gameprofilerfiller.pop(); // Purpur
+ //gameprofilerfiller.pop(); // Purpur
- this.chunkMap.tick();
}
-
-@@ -906,7 +906,7 @@ public class ServerChunkCache extends ChunkSource {
+-
++
+ // Pufferfish start - optimize mob spawning
+ if (gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning) {
+ for (ServerPlayer player : this.level.players) {
+@@ -901,7 +901,7 @@ public class ServerChunkCache extends ChunkSource {
@Override
protected void doRunTask(Runnable task) {
@@ -2244,7 +2316,7 @@ index 5d26364c0f4ed03bd9994077683c93b9883e5327..43a46feb5fb4bf23d71bc4f6c08caa93
}
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
-index d46e61640b241d32df05240dedd2c23f138725e6..c6ef510d335b8baea58c4491853414a52a06b66b 100644
+index e385a62058204ba3b01ce594e7c180f9cc6cf664..92ca330bee2f58bde93c8da12a8f5c14e29de540 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -73,7 +73,7 @@ public class ServerEntity {
@@ -2257,10 +2329,10 @@ index d46e61640b241d32df05240dedd2c23f138725e6..c6ef510d335b8baea58c4491853414a5
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 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442b7a6df83 100644
+index f7215d0a67e9e024af0c040c796ebcbb4f76e885..1309c9e63095a0484ee0fa119a41c29ef1da3a01 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -214,6 +214,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -215,6 +215,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
private final StructureManager structureManager;
private final StructureCheck structureCheck;
private final boolean tickTime;
@@ -2269,7 +2341,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
private final RandomSequences randomSequences;
public long lastMidTickExecuteFailure; // Paper - execute chunk tasks mid tick
-@@ -223,6 +225,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -224,6 +226,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
public boolean hasPhysicsEvent = true; // Paper
public boolean hasEntityMoveEvent = false; // Paper
private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current)
@@ -2277,7 +2349,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
public static Throwable getAddToWorldStackTrace(Entity entity) {
final Throwable thr = new Throwable(entity + " Added to world at " + new java.util.Date());
io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(thr);
-@@ -706,7 +709,24 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -712,7 +715,24 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.dragonParts = new Int2ObjectOpenHashMap();
this.tickTime = flag1;
this.server = minecraftserver;
@@ -2303,7 +2375,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
this.serverLevelData = iworlddataserver;
ChunkGenerator chunkgenerator = worlddimension.generator();
// CraftBukkit start
-@@ -768,6 +788,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -774,6 +794,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.chunkTaskScheduler = new io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler(this, io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.workerThreads); // Paper - rewrite chunk system
this.entityLookup = new io.papermc.paper.chunk.system.entity.EntityLookup(this, new EntityCallbacks()); // Paper - rewrite chunk system
@@ -2311,7 +2383,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
}
// Paper start
-@@ -802,17 +823,17 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -808,23 +829,23 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
public void tick(BooleanSupplier shouldKeepTicking) {
@@ -2319,12 +2391,18 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
+ //ProfilerFiller gameprofilerfiller = this.getProfiler(); // Purpur
this.handlingTick = true;
-- gameprofilerfiller.push("world border");
-+ //gameprofilerfiller.push("world border"); // Purpur
- this.getWorldBorder().tick();
-- gameprofilerfiller.popPush("weather");
-+ //gameprofilerfiller.popPush("weather"); // Purpur
- this.advanceWeatherCycle();
+ TickRateManager tickratemanager = this.tickRateManager();
+ boolean flag = tickratemanager.runsNormally();
+
+ if (flag) {
+- gameprofilerfiller.push("world border");
++ // gameprofilerfiller.push("world border"); // Purpur
+ this.getWorldBorder().tick();
+- gameprofilerfiller.popPush("weather");
++ // gameprofilerfiller.popPush("weather"); // Purpur
+ this.advanceWeatherCycle();
+ }
+
int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
long j;
@@ -2333,15 +2411,15 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
// CraftBukkit start
j = this.levelData.getDayTime() + 24000L;
TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (j - j % 24000L) - this.getDayTime());
-@@ -834,32 +855,32 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -849,38 +870,38 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ this.tickTime();
+ }
- this.updateSkyBrightness();
- this.tickTime();
- gameprofilerfiller.popPush("tickPending");
- this.timings.scheduledBlocks.startTiming(); // Paper
+ //gameprofilerfiller.popPush("tickPending"); // Purpur
+ //this.timings.scheduledBlocks.startTiming(); // Paper // Purpur
- if (!this.isDebug()) {
+ if (!this.isDebug() && flag) {
j = this.getGameTime();
- gameprofilerfiller.push("blockTicks");
+ //gameprofilerfiller.push("blockTicks"); // Purpur
@@ -2356,41 +2434,47 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
+ //this.timings.scheduledBlocks.stopTiming(); // Paper // Purpur
- gameprofilerfiller.popPush("raid");
-- this.timings.raids.startTiming(); // Paper - timings
+ //gameprofilerfiller.popPush("raid"); // Purpur
-+ //this.timings.raids.startTiming(); // Paper - timings // Purpur
- this.raids.tick();
-- this.timings.raids.stopTiming(); // Paper - timings
+ 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
-+ //this.timings.raids.stopTiming(); // Paper - timings // Purpur
+ //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.doSounds.startTiming(); // Spigot
+ //this.timings.chunkProviderTick.stopTiming(); // Paper - timings // Purpur
+ //gameprofilerfiller.popPush("blockEvents"); // Purpur
-+ //this.timings.doSounds.startTiming(); // Spigot // Purpur
- this.runBlockEvents();
-- this.timings.doSounds.stopTiming(); // Spigot
-+ //this.timings.doSounds.stopTiming(); // Spigot // 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;
- gameprofilerfiller.pop();
+ //gameprofilerfiller.pop(); // Purpur
- boolean flag = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players
+ boolean flag1 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players
- if (flag) {
-@@ -867,25 +888,25 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ if (flag1) {
+@@ -888,25 +909,25 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
- if (flag || this.emptyTime++ < 300) {
+ 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) {
+ if (this.dragonFight != null && flag) {
- gameprofilerfiller.push("dragonFight");
+ //gameprofilerfiller.push("dragonFight"); // Purpur
this.dragonFight.tick();
@@ -2406,7 +2490,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
if (!entity.isRemoved()) {
if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed
entity.discard();
- } else {
+ } else if (!tickratemanager.isEntityFrozen(entity)) {
- gameprofilerfiller.push("checkDespawn");
+ //gameprofilerfiller.push("checkDespawn"); // Purpur
entity.checkDespawn();
@@ -2415,7 +2499,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
if (true || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { // Paper - now always true if in the ticking list
Entity entity1 = entity.getVehicle();
-@@ -897,7 +918,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -918,7 +939,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
entity.stopRiding();
}
@@ -2424,7 +2508,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
// Pufferfish start - copied from this.guardEntityTick
try {
this.tickNonPassenger(entity); // Pufferfish - changed
-@@ -912,20 +933,19 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -933,20 +954,19 @@ public class ServerLevel extends Level implements WorldGenLevel {
// Paper end
}
// Pufferfish end
@@ -2450,7 +2534,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
}
@Override
-@@ -943,6 +963,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -964,6 +984,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.serverLevelData.setGameTime(i);
this.serverLevelData.getScheduledEvents().tick(this.server, i);
if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) {
@@ -2464,7 +2548,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
this.setDayTime(this.levelData.getDayTime() + 1L);
}
-@@ -951,7 +978,21 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -972,7 +999,21 @@ public class ServerLevel extends Level implements WorldGenLevel {
public void setDayTime(long timeOfDay) {
this.serverLevelData.setDayTime(timeOfDay);
@@ -2486,7 +2570,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
public void tickCustomSpawners(boolean spawnMonsters, boolean spawnAnimals) {
Iterator iterator = this.customSpawners.iterator();
-@@ -976,7 +1017,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -997,7 +1038,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
// Paper start - optimise random block ticking
private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos();
@@ -2495,7 +2579,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
// Paper end
private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Pufferfish
-@@ -986,9 +1027,9 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1007,9 +1048,9 @@ public class ServerLevel extends Level implements WorldGenLevel {
boolean flag = this.isRaining();
int j = chunkcoordintpair.getMinBlockX();
int k = chunkcoordintpair.getMinBlockZ();
@@ -2507,7 +2591,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change
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 - disable thunder // Pufferfish - replace random with shouldDoLightning
-@@ -999,10 +1040,18 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1020,10 +1061,18 @@ public class ServerLevel extends Level implements WorldGenLevel {
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
if (flag1) {
@@ -2528,7 +2612,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
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
-@@ -1019,7 +1068,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1040,7 +1089,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
}
@@ -2537,18 +2621,18 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
if (!this.paperConfig().environment.disableIceAndSnow) { // Paper
for (int l = 0; l < randomTickSpeed; ++l) {
-@@ -1031,8 +1080,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1053,8 +1102,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ }
} // Paper
- // Paper start - optimise random block ticking
- gameprofilerfiller.popPush("tickBlocks");
- timings.chunkTicksBlocks.startTiming(); // Paper
+ //gameprofilerfiller.popPush("tickBlocks"); // Purpur
+ //timings.chunkTicksBlocks.startTiming(); // Paper // Purpur
if (randomTickSpeed > 0) {
+ // Paper start - optimize random block ticking
LevelChunkSection[] sections = chunk.getSections();
- final int minSection = io.papermc.paper.util.WorldUtil.getMinSection(this);
-@@ -1065,8 +1114,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1088,8 +1137,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
// Paper end - optimise random block ticking
@@ -2558,8 +2642,8 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
+ //gameprofilerfiller.pop(); // Purpur
}
- private void tickIceAndSnow(boolean raining, BlockPos.MutableBlockPos blockposition1, final LevelChunk chunk) { // Paper - optimise chunk ticking
-@@ -1120,7 +1169,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ @VisibleForTesting
+@@ -1147,7 +1196,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
return holder.is(PoiTypes.LIGHTNING_ROD);
}, (blockposition1) -> {
return blockposition1.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockposition1.getX(), blockposition1.getZ()) - 1;
@@ -2568,7 +2652,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
return optional.map((blockposition1) -> {
return blockposition1.above(1);
-@@ -1169,11 +1218,27 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1196,11 +1245,27 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (this.canSleepThroughNights()) {
if (!this.getServer().isSingleplayer() || this.getServer().isPublished()) {
int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
@@ -2597,15 +2681,15 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
ichatmutablecomponent = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(i));
}
-@@ -1312,6 +1377,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
-
- private void resetWeatherCycle() {
+@@ -1340,6 +1405,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ @VisibleForTesting
+ public void resetWeatherCycle() {
// CraftBukkit start
+ if (this.purpurConfig.rainStopsAfterSleep) // Purpur
this.serverLevelData.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night
// 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....
-@@ -1319,6 +1385,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1347,6 +1413,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.serverLevelData.setRainTime(0);
}
// CraftBukkit end
@@ -2613,7 +2697,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
this.serverLevelData.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - when passing the night
// CraftBukkit start
// If we stop due to everyone sleeping we should reset the weather duration to some other random value.
-@@ -1386,24 +1453,24 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1414,24 +1481,24 @@ public class ServerLevel extends Level implements WorldGenLevel {
// Spigot end
// Paper start- timings
final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity);
@@ -2646,7 +2730,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
Iterator iterator = entity.getPassengers().iterator();
while (iterator.hasNext()) {
-@@ -1426,17 +1493,17 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1454,17 +1521,17 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (passenger instanceof Player || this.entityTickList.contains(passenger)) {
// Paper - EAR 2
final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger);
@@ -2670,7 +2754,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
// Paper start - EAR 2
if (isActive) {
passenger.rideTick();
-@@ -1448,7 +1515,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1476,7 +1543,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
vehicle.positionRider(passenger);
}
// Paper end - EAR 2
@@ -2679,7 +2763,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
Iterator iterator = passenger.getPassengers().iterator();
while (iterator.hasNext()) {
-@@ -1457,7 +1524,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1485,7 +1552,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.tickPassenger(passenger, entity2);
}
@@ -2688,14 +2772,14 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
}
} else {
passenger.stopRiding();
-@@ -1477,14 +1544,14 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1505,14 +1572,14 @@ public class ServerLevel extends Level implements WorldGenLevel {
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();
+ this.saveLevelData(true); // Pufferfish
}
- this.timings.worldSaveChunks.startTiming(); // Paper
@@ -2706,7 +2790,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
// Copied from save()
// CraftBukkit start - moved from MinecraftServer.saveChunks
-@@ -1496,7 +1563,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1524,7 +1591,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData());
}
// CraftBukkit end
@@ -2715,7 +2799,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
}
// Paper end
-@@ -1510,7 +1577,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1538,7 +1605,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (!savingDisabled) {
org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(this.getWorld())); // CraftBukkit
@@ -2724,7 +2808,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
if (progressListener != null) {
progressListener.progressStartNoAbort(Component.translatable("menu.savingLevel"));
}
-@@ -1520,11 +1587,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -1548,11 +1615,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
progressListener.progressStage(Component.translatable("menu.savingChunks"));
}
@@ -2739,7 +2823,7 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
// Paper - rewrite chunk system - entity saving moved into ChunkHolder
} else if (close) { chunkproviderserver.close(false); } // Paper - rewrite chunk system
-@@ -2810,7 +2877,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -2861,7 +2928,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
// 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
@@ -2749,11 +2833,11 @@ index 945783d090e44ebed1d4968c1d1ec0b68f6d494f..1c8724fb56e790922c7e8fc73bc97442
}
// Paper end
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc75ef9eeb7 100644
+index 0a1977905de97522cf3311f59a2cdc6c0a5f98f9..d5a5406284bf764c9f7a31a4ad85bbcda18f4df8 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-@@ -274,6 +274,10 @@ public class ServerPlayer extends Player {
- public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
+@@ -281,6 +281,10 @@ public class ServerPlayer extends Player {
+ public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
public @Nullable String clientBrandName = null; // Paper - Brand name
public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event
+ public boolean purpurClient = false; // Purpur
@@ -2763,7 +2847,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
// Paper start - replace player chunk loader
private final java.util.concurrent.atomic.AtomicReference viewDistances = new java.util.concurrent.atomic.AtomicReference<>(new io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.ViewDistances(-1, -1, -1));
-@@ -561,6 +565,9 @@ public class ServerPlayer extends Player {
+@@ -568,6 +572,9 @@ public class ServerPlayer extends Player {
}
}
@@ -2773,7 +2857,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
}
@Override
-@@ -627,6 +634,9 @@ public class ServerPlayer extends Player {
+@@ -634,6 +641,9 @@ public class ServerPlayer extends Player {
}
this.getBukkitEntity().setExtraData(nbt); // CraftBukkit
@@ -2783,7 +2867,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
}
// CraftBukkit start - World fallback code, either respawn location or global spawn
-@@ -755,6 +765,15 @@ public class ServerPlayer extends Player {
+@@ -762,6 +772,15 @@ public class ServerPlayer extends Player {
this.trackStartFallingPosition();
this.trackEnteredOrExitedLavaOnVehicle();
this.advancements.flushDirty(this);
@@ -2799,15 +2883,15 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
}
public void doTick() {
-@@ -991,6 +1010,7 @@ public class ServerPlayer extends Player {
+@@ -999,6 +1018,7 @@ public class ServerPlayer extends Player {
}));
- Team scoreboardteambase = this.getTeam();
+ PlayerTeam scoreboardteam = this.getTeam();
+ if (org.purpurmc.purpur.PurpurConfig.deathMessageOnlyBroadcastToAffectedPlayer) this.sendSystemMessage(ichatbasecomponent); else // Purpur
- if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != Team.Visibility.ALWAYS) {
- if (scoreboardteambase.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) {
+ if (scoreboardteam != null && scoreboardteam.getDeathMessageVisibility() != Team.Visibility.ALWAYS) {
+ if (scoreboardteam.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) {
this.server.getPlayerList().broadcastSystemToTeam(this, ichatbasecomponent);
-@@ -1097,6 +1117,16 @@ public class ServerPlayer extends Player {
+@@ -1102,6 +1122,16 @@ public class ServerPlayer extends Player {
if (this.isInvulnerableTo(source)) {
return false;
} else {
@@ -2824,7 +2908,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
boolean flag = this.server.isDedicatedServer() && this.isPvpAllowed() && source.is(DamageTypeTags.IS_FALL);
if (!flag && this.spawnInvulnerableTime > 0 && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) {
-@@ -1208,7 +1238,7 @@ public class ServerPlayer extends Player {
+@@ -1213,7 +1243,7 @@ public class ServerPlayer extends Player {
PortalInfo shapedetectorshape = this.findDimensionEntryPoint(worldserver);
if (shapedetectorshape != null) {
@@ -2833,7 +2917,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
worldserver = shapedetectorshape.world; // CraftBukkit
if (worldserver == null) { } else // CraftBukkit - empty to fall through to null to event
if (resourcekey == LevelStem.OVERWORLD && worldserver.getTypeKey() == LevelStem.NETHER) { // CraftBukkit
-@@ -1231,8 +1261,8 @@ public class ServerPlayer extends Player {
+@@ -1236,8 +1266,8 @@ public class ServerPlayer extends Player {
worldserver = ((CraftWorld) exit.getWorld()).getHandle();
// CraftBukkit end
@@ -2844,7 +2928,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
if (true) { // CraftBukkit
this.isChangingDimension = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds
-@@ -1243,13 +1273,14 @@ public class ServerPlayer extends Player {
+@@ -1248,13 +1278,14 @@ public class ServerPlayer extends Player {
playerlist.sendPlayerPermissionLevel(this);
worldserver1.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION);
this.unsetRemoved();
@@ -2860,7 +2944,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
this.triggerDimensionChangeTriggers(worldserver1);
this.connection.send(new ClientboundPlayerAbilitiesPacket(this.getAbilities()));
playerlist.sendLevelInfo(this, worldserver);
-@@ -1399,7 +1430,7 @@ public class ServerPlayer extends Player {
+@@ -1404,7 +1435,7 @@ public class ServerPlayer extends Player {
return entitymonster.isPreventingPlayerRest(this);
});
@@ -2869,7 +2953,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
return Either.left(Player.BedSleepingProblem.NOT_SAFE);
}
}
-@@ -1439,7 +1470,19 @@ public class ServerPlayer extends Player {
+@@ -1444,7 +1475,19 @@ public class ServerPlayer extends Player {
});
if (!this.serverLevel().canSleepThroughNights()) {
@@ -2890,7 +2974,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
}
((ServerLevel) this.level()).updateSleepingPlayerList();
-@@ -1536,6 +1579,7 @@ public class ServerPlayer extends Player {
+@@ -1549,6 +1592,7 @@ public class ServerPlayer extends Player {
@Override
public void openTextEdit(SignBlockEntity sign, boolean front) {
@@ -2898,7 +2982,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
this.connection.send(new ClientboundBlockUpdatePacket(this.level(), sign.getBlockPos()));
this.connection.send(new ClientboundOpenSignEditorPacket(sign.getBlockPos(), front));
}
-@@ -1781,6 +1825,26 @@ public class ServerPlayer extends Player {
+@@ -1883,6 +1927,26 @@ public class ServerPlayer extends Player {
this.lastSentExp = -1; // CraftBukkit - Added to reset
}
@@ -2925,7 +3009,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
@Override
public void displayClientMessage(Component message, boolean overlay) {
this.sendSystemMessage(message, overlay);
-@@ -2102,8 +2166,68 @@ public class ServerPlayer extends Player {
+@@ -2204,8 +2268,68 @@ public class ServerPlayer extends Player {
public void resetLastActionTime() {
this.lastActionTime = Util.getMillis();
@@ -2994,7 +3078,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
public ServerStatsCounter getStats() {
return this.stats;
}
-@@ -2654,4 +2778,50 @@ public class ServerPlayer extends Player {
+@@ -2757,4 +2881,50 @@ public class ServerPlayer extends Player {
return (CraftPlayer) super.getBukkitEntity();
}
// CraftBukkit end
@@ -3046,7 +3130,7 @@ index 907c8f15f5247f9972c6677ff0f9e1aa22764a04..7b72be8dcaf3fc5c7151c847faa2dfc7
+ // 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 3706e94108f68a16fea63e734f3e3b6871dcb0b8..6f8d990cbc15c3fa11acdf59fc1ec1fa583f60ec 100644
+index 3c567a9ea921a6ae36f4dc5e16a8394ab62460a8..5e18507e6d799e51f555ffc0a5f14cb76959023d 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -397,6 +397,7 @@ public class ServerPlayerGameMode {
@@ -3057,15 +3141,6 @@ index 3706e94108f68a16fea63e734f3e3b6871dcb0b8..6f8d990cbc15c3fa11acdf59fc1ec1fa
}
// CraftBukkit end
-@@ -427,7 +428,7 @@ public class ServerPlayerGameMode {
-
- ItemStack mainHandStack = null; // Paper
- boolean isCorrectTool = false; // Paper
-- if (this.isCreative()) {
-+ if (this.isCreative() || (this.level.purpurConfig.shulkerBoxAllowOversizedStacks && block instanceof net.minecraft.world.level.block.ShulkerBoxBlock)) { // Purpur
- // return true; // CraftBukkit
- } else {
- ItemStack itemstack = this.player.getMainHandItem();
@@ -516,6 +517,7 @@ public class ServerPlayerGameMode {
public InteractionHand interactHand;
public ItemStack interactItemStack;
@@ -3103,7 +3178,7 @@ index 3706e94108f68a16fea63e734f3e3b6871dcb0b8..6f8d990cbc15c3fa11acdf59fc1ec1fa
+ // 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 50ed7cfe1ecef6d075ba484804827cec83ba2bf2..54f9cd80ac925aa95ff4fdb4d52cbcc2b04263a5 100644
+index 277c8e429481ca9763ddac9e700735d25aba78e9..3632957dfd39dc5dcb288fb86c0cadc37f1b4d27 100644
--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java
+++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
@@ -318,6 +318,7 @@ public class WorldGenRegion implements WorldGenLevel {
@@ -3115,23 +3190,24 @@ index 50ed7cfe1ecef6d075ba484804827cec83ba2bf2..54f9cd80ac925aa95ff4fdb4d52cbcc2
Util.logAndPauseIfInIde("Detected setBlock in a far chunk [" + i + ", " + j + "], pos: " + pos + ", status: " + this.generatingStatus + (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 598f807f0d0caac98b81e0e2991f1bd497c4534e..b19c59a87d4136da583a0b687f6b27fef3456f09 100644
+index d28d0ef6105ddeb562ddf31ae9088739856941fc..da499e0b21eba40d24d95047e3a9220567d4bae7 100644
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
-@@ -51,10 +51,12 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
+@@ -51,11 +51,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
private long keepAliveTime = Util.getMillis(); // Paper
private boolean keepAlivePending;
private long keepAliveChallenge;
+ private it.unimi.dsi.fastutil.longs.LongList keepAlives = new it.unimi.dsi.fastutil.longs.LongArrayList(); // Purpur
private int latency;
private volatile boolean suspendFlushingOnServerThread = false;
+ public final java.util.Map packCallbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - adventure resource pack callbacks
private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit
protected static final ResourceLocation MINECRAFT_BRAND = new ResourceLocation("brand"); // Paper - Brand support
+ protected static final ResourceLocation PURPUR_CLIENT = new ResourceLocation("purpur", "client"); // Purpur
public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit
this.server = minecraftserver;
-@@ -90,6 +92,16 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
+@@ -91,6 +93,16 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
@Override
public void handleKeepAlive(ServerboundKeepAlivePacket packet) {
@@ -3148,7 +3224,7 @@ index 598f807f0d0caac98b81e0e2991f1bd497c4534e..b19c59a87d4136da583a0b687f6b27fe
//PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // CraftBukkit // Paper - This shouldn't be on the main thread
if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) {
int i = (int) (Util.getMillis() - this.keepAliveTime);
-@@ -137,6 +149,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
+@@ -138,6 +150,13 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex);
this.disconnect("Invalid payload REGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause
}
@@ -3162,7 +3238,7 @@ index 598f807f0d0caac98b81e0e2991f1bd497c4534e..b19c59a87d4136da583a0b687f6b27fe
} else if (identifier.equals(ServerCommonPacketListenerImpl.CUSTOM_UNREGISTER)) {
try {
String channels = payload.toString(com.google.common.base.Charsets.UTF_8);
-@@ -190,12 +209,27 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
+@@ -203,12 +222,27 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
}
protected void keepConnectionAlive() {
@@ -3191,7 +3267,7 @@ index 598f807f0d0caac98b81e0e2991f1bd497c4534e..b19c59a87d4136da583a0b687f6b27fe
if (this.keepAlivePending) {
if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info
-@@ -211,7 +245,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
+@@ -224,7 +258,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
}
// Paper end
@@ -3201,11 +3277,11 @@ index 598f807f0d0caac98b81e0e2991f1bd497c4534e..b19c59a87d4136da583a0b687f6b27fe
public void suspendFlushing() {
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f019072006a3ef31f 100644
+index 04b0eb391bb524dd7af14b862d89c0f2494a8206..0b37acd48517d28efec716b93c33da6aa97c54f2 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-@@ -323,6 +323,20 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
- private boolean hasMoved; // Spigot
+@@ -325,6 +325,20 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+ private boolean justTeleported = false;
// CraftBukkit end
+ // Purpur start
@@ -3225,7 +3301,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
@Override
public void tick() {
if (this.ackBlockChangesUpTo > -1) {
-@@ -390,6 +404,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -392,6 +406,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
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.
@@ -3238,16 +3314,16 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854
this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause
}
-@@ -638,6 +658,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -642,6 +662,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.lastYaw = to.getYaw();
this.lastPitch = to.getPitch();
+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetLastActionTime(); // Purpur
+
- // Skip the first time we do this
- if (true) { // Spigot - don't skip any move events
- Location oldTo = to.clone();
-@@ -714,6 +736,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+ Location oldTo = to.clone();
+ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
+ this.cserver.getPluginManager().callEvent(event);
+@@ -715,6 +737,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
if (packet.getId() == this.awaitingTeleport) {
if (this.awaitingPositionFromClient == null) {
this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause
@@ -3255,7 +3331,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
return;
}
-@@ -1127,10 +1150,15 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1132,10 +1155,15 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
int maxBookPageSize = io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.bookSize.pageMax;
double multiplier = Math.max(0.3D, Math.min(1D, io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.bookSize.totalMultiplier));
long byteAllowed = maxBookPageSize;
@@ -3271,7 +3347,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause
return;
}
-@@ -1154,6 +1182,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1159,6 +1187,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
if (byteTotal > byteAllowed) {
ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size());
@@ -3279,7 +3355,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause
return;
}
-@@ -1207,13 +1236,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1212,13 +1241,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
itemstack1.setTag(nbttagcompound.copy());
}
@@ -3299,7 +3375,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
this.updateBookPages(pages, (s) -> {
return Component.Serializer.toJson(Component.literal(s));
-@@ -1225,10 +1257,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1230,10 +1262,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
private void updateBookPages(List list, UnaryOperator unaryoperator, ItemStack itemstack, int slot, ItemStack handItem) { // CraftBukkit
ListTag nbttaglist = new ListTag();
@@ -3315,7 +3391,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
Objects.requireNonNull(nbttaglist);
stream.forEach(nbttaglist::add);
-@@ -1238,11 +1273,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1243,11 +1278,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
for (int j = list.size(); i < j; ++i) {
FilteredText filteredtext = (FilteredText) list.get(i);
@@ -3329,7 +3405,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
}
}
-@@ -1255,6 +1290,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1260,6 +1295,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.player.getInventory().setItem(slot, CraftEventFactory.handleEditBookEvent(this.player, slot, handItem, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent)
}
@@ -3346,7 +3422,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
@Override
public void handleEntityTagQuery(ServerboundEntityTagQuery packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
-@@ -1284,8 +1329,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1309,8 +1354,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
@Override
public void handleMovePlayer(ServerboundMovePlayerPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
@@ -3364,25 +3440,25 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
} else {
ServerLevel worldserver = this.player.serverLevel();
-@@ -1468,7 +1521,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1496,7 +1549,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
if (!event.isAllowed()) {
flag2 = true; // Paper - diff on change, this should be moved wrongly
if (event.getLogWarning())
- ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
+ ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!, ({})", this.player.getName().getString(), d11); // Purpur
}
- // Paper end
+ // Paper end - Add fail move event
}
-@@ -1530,6 +1583,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1566,6 +1619,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.lastYaw = to.getYaw();
this.lastPitch = to.getPitch();
+ if (!to.getWorld().getUID().equals(from.getWorld().getUID()) || to.getBlockX() != from.getBlockX() || to.getBlockY() != from.getBlockY() || to.getBlockZ() != from.getBlockZ() || to.getYaw() != from.getYaw() || to.getPitch() != from.getPitch()) this.player.resetLastActionTime(); // Purpur
+
- // Skip the first time we do this
- if (from.getX() != Double.MAX_VALUE) {
- Location oldTo = to.clone();
-@@ -1568,6 +1623,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+ Location oldTo = to.clone();
+ PlayerMoveEvent event = new PlayerMoveEvent(player, from, to);
+ this.cserver.getPluginManager().callEvent(event);
+@@ -1601,6 +1656,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.player.resetFallDistance();
}
@@ -3396,7 +3472,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
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();
-@@ -1619,6 +1681,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1652,6 +1714,13 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
return false;
}
// Paper end - optimise out extra getCubes
@@ -3410,7 +3486,16 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
private boolean isPlayerCollidingWithAnythingNew(LevelReader world, AABB box, double newX, double newY, double newZ) {
AABB axisalignedbb1 = this.player.getBoundingBox().move(newX - this.player.getX(), newY - this.player.getY(), newZ - this.player.getZ());
Iterable iterable = world.getCollisions(this.player, axisalignedbb1.deflate(9.999999747378752E-6D));
-@@ -1964,6 +2033,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1662,7 +1731,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+
+ do {
+ if (!iterator.hasNext()) {
+- return false;
++ return !org.purpurmc.purpur.PurpurConfig.kickForOutOfOrderChat; // Purpur
+ }
+
+ voxelshape1 = (VoxelShape) iterator.next();
+@@ -1997,6 +2066,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
boolean cancelled;
if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) {
@@ -3418,16 +3503,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemstack, enumhand);
cancelled = event.useItemInHand() == Event.Result.DENY;
} else {
-@@ -2281,7 +2351,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
- do {
- instant1 = (Instant) this.lastChatTimeStamp.get();
- if (timestamp.isBefore(instant1)) {
-- return false;
-+ return !org.purpurmc.purpur.PurpurConfig.kickForOutOfOrderChat; // Purpur
- }
- } while (!this.lastChatTimeStamp.compareAndSet(instant1, timestamp));
-
-@@ -2391,7 +2461,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -2401,7 +2471,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
public void handleCommand(String s) { // Paper - private -> public
org.spigotmc.AsyncCatcher.catchOp("Command Dispatched Async: " + s); // Paper - Add async catcher
@@ -3436,7 +3512,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot
this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s);
-@@ -2401,7 +2471,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -2411,7 +2481,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.cserver.getPluginManager().callEvent(event);
if (event.isCancelled()) {
@@ -3445,7 +3521,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
return;
}
-@@ -2414,7 +2484,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -2424,7 +2494,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
return;
} finally {
@@ -3454,7 +3530,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
}
}
// CraftBukkit end
-@@ -2701,6 +2771,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -2711,6 +2781,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
AABB axisalignedbb = entity.getBoundingBox();
if (axisalignedbb.distanceToSqr(this.player.getEyePosition()) < ServerGamePacketListenerImpl.MAX_INTERACTION_DISTANCE) {
@@ -3462,7 +3538,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
packet.dispatch(new ServerboundInteractPacket.Handler() {
private void performInteraction(InteractionHand enumhand, ServerGamePacketListenerImpl.EntityInteraction playerconnection_a, PlayerInteractEntityEvent event) { // CraftBukkit
ItemStack itemstack = ServerGamePacketListenerImpl.this.player.getItemInHand(enumhand);
-@@ -2714,6 +2785,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -2724,6 +2795,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
ServerGamePacketListenerImpl.this.cserver.getPluginManager().callEvent(event);
@@ -3471,7 +3547,7 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
// Entity in bucket - SPIGOT-4048 and SPIGOT-6859a
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.getEntityData().resendPossiblyDesyncedEntity(player); // Paper - The entire mob gets deleted, so resend it.
-@@ -3299,6 +3372,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -3309,6 +3382,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
}
}
@@ -3485,19 +3561,10 @@ index 6cc9271ba058f4af759eae34e2f6e9f892b4f6da..a7e82f95db5c6c054175192f01907200
boolean flag1 = packet.getSlotNum() >= 1 && packet.getSlotNum() <= 45;
boolean flag2 = itemstack.isEmpty() || itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty();
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
-index 1c4f272219e68373eaae93fc5ea9af7d8f3fd6f9..3dcccca8ede9b203c24ba29b2020a583297b895c 100644
+index b9117be53b8b8b37af54621f54480f275546f0fd..cbcb16a6ccab1681dea22407f859f86dc1b9fe22 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
-@@ -141,6 +141,8 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
- return false;
- }
-
-+ if (true) return org.purpurmc.purpur.PurpurConfig.usernameValidCharactersPattern.matcher(in).matches(); // Purpur
-+
- for (int i = 0, len = in.length(); i < len; ++i) {
- char c = in.charAt(i);
-
-@@ -296,7 +298,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
+@@ -270,7 +270,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
ServerLoginPacketListenerImpl.LOGGER.warn("Failed to verify username but will let them in anyway!");
ServerLoginPacketListenerImpl.this.startClientVerification(ServerLoginPacketListenerImpl.this.createOfflineProfile(s1)); // Spigot
} else {
@@ -3539,10 +3606,10 @@ index 9ddbfcf80d9a381dace78a62880f85a4d767e0eb..7383c7d3820dce06108eaafd236a7c6c
}
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
-index 33abcf12b4426572b74ca4c813e4392c823494bc..182acaad79e14e5e120094916a0d295a4584de7a 100644
+index ed11fec21b0c3a60fe8c14e699eb3a3823044d66..92717b7aa7ac94a2b1d11b5ba46522057903f981 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
-@@ -488,6 +488,7 @@ public abstract class PlayerList {
+@@ -486,6 +486,7 @@ public abstract class PlayerList {
scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam);
}
// Paper end
@@ -3550,7 +3617,7 @@ index 33abcf12b4426572b74ca4c813e4392c823494bc..182acaad79e14e5e120094916a0d295a
// CraftBukkit - Moved from above, added world
PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ());
}
-@@ -601,6 +602,7 @@ public abstract class PlayerList {
+@@ -599,6 +600,7 @@ public abstract class PlayerList {
}
public net.kyori.adventure.text.Component remove(ServerPlayer entityplayer, net.kyori.adventure.text.Component leaveMessage) {
// Paper end
@@ -3558,7 +3625,7 @@ index 33abcf12b4426572b74ca4c813e4392c823494bc..182acaad79e14e5e120094916a0d295a
ServerLevel worldserver = entityplayer.serverLevel();
entityplayer.awardStat(Stats.LEAVE_GAME);
-@@ -755,7 +757,7 @@ public abstract class PlayerList {
+@@ -753,7 +755,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;
@@ -3567,7 +3634,7 @@ index 33abcf12b4426572b74ca4c813e4392c823494bc..182acaad79e14e5e120094916a0d295a
event.disallow(PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure
}
}
-@@ -1060,6 +1062,20 @@ public abstract class PlayerList {
+@@ -1064,6 +1066,20 @@ public abstract class PlayerList {
}
// CraftBukkit end
@@ -3588,7 +3655,7 @@ index 33abcf12b4426572b74ca4c813e4392c823494bc..182acaad79e14e5e120094916a0d295a
public void broadcastAll(Packet> packet, ResourceKey dimension) {
Iterator iterator = this.players.iterator();
-@@ -1163,6 +1179,7 @@ public abstract class PlayerList {
+@@ -1167,6 +1183,7 @@ public abstract class PlayerList {
} else {
b0 = (byte) (24 + permissionLevel);
}
@@ -3596,7 +3663,7 @@ index 33abcf12b4426572b74ca4c813e4392c823494bc..182acaad79e14e5e120094916a0d295a
player.connection.send(new ClientboundEntityEventPacket(player, b0));
}
-@@ -1171,6 +1188,27 @@ public abstract class PlayerList {
+@@ -1175,6 +1192,27 @@ public abstract class PlayerList {
player.getBukkitEntity().recalculatePermissions(); // CraftBukkit
this.server.getCommands().sendCommands(player);
} // Paper
@@ -3624,7 +3691,7 @@ index 33abcf12b4426572b74ca4c813e4392c823494bc..182acaad79e14e5e120094916a0d295a
}
public boolean isWhiteListed(GameProfile profile) {
-@@ -1232,7 +1270,7 @@ public abstract class PlayerList {
+@@ -1236,7 +1274,7 @@ public abstract class PlayerList {
public void saveAll(int interval) {
io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
@@ -3633,7 +3700,7 @@ index 33abcf12b4426572b74ca4c813e4392c823494bc..182acaad79e14e5e120094916a0d295a
int numSaved = 0;
long now = MinecraftServer.currentTick;
for (int i = 0; i < this.players.size(); ++i) {
-@@ -1243,7 +1281,7 @@ public abstract class PlayerList {
+@@ -1247,7 +1285,7 @@ public abstract class PlayerList {
}
// Paper end
}
@@ -3943,7 +4010,7 @@ index 25a5a3b949a0eb632611355e74ccd4865be108ca..c8860f20956a2819da001e9393824945
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 4604f8b38460e9113e966889a679d4547f24aff6..4a5d2e263d2bbee96bde7012d3385fa33860bc1b 100644
+index f339475185645f7be30963e4f980ce81a6f7e536..530a180a607636265c1b1244f05a772f7adfe7b6 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSources.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
@@ -267,4 +267,17 @@ public class DamageSources {
@@ -3978,31 +4045,23 @@ index 3aad6bd0a1fb7bb3f9b7dab2c10c875864900750..31bd845130e363dd11c225dfd1e9dd89
}
diff --git a/src/main/java/net/minecraft/world/effect/MobEffectInstance.java b/src/main/java/net/minecraft/world/effect/MobEffectInstance.java
-index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6c5b7ed91 100644
+index bf304db1f9506d3e83d16cd632b9155c39346634..d94497083f3da89dbef6479ef8f70591e630e3e7 100644
--- a/src/main/java/net/minecraft/world/effect/MobEffectInstance.java
+++ b/src/main/java/net/minecraft/world/effect/MobEffectInstance.java
-@@ -16,6 +16,7 @@ import net.minecraft.util.ExtraCodecs;
- import net.minecraft.util.Mth;
- import net.minecraft.world.entity.LivingEntity;
- import org.slf4j.Logger;
-+import org.bukkit.NamespacedKey;
-
- public class MobEffectInstance implements Comparable {
- private static final Logger LOGGER = LogUtils.getLogger();
-@@ -35,6 +36,7 @@ public class MobEffectInstance implements Comparable {
- private boolean visible;
+@@ -36,6 +36,7 @@ public class MobEffectInstance implements Comparable {
private boolean showIcon;
@Nullable
-+ private NamespacedKey key; // Purpur - add key
- private MobEffectInstance hiddenEffect;
+ public MobEffectInstance hiddenEffect;
++ private org.bukkit.NamespacedKey key; // Purpur - add key
private final Optional factorData;
-@@ -54,17 +56,36 @@ public class MobEffectInstance implements Comparable {
+ public MobEffectInstance(MobEffect type) {
+@@ -54,17 +55,36 @@ public class MobEffectInstance implements Comparable {
this(type, duration, amplifier, ambient, visible, visible);
}
+ // Purpur start
-+ public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean visible, @Nullable NamespacedKey key) {
++ public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean visible, @Nullable org.bukkit.NamespacedKey key) {
+ this(type, duration, amplifier, ambient, visible, visible, key);
+ }
+ // Purpur end
@@ -4010,20 +4069,20 @@ index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6
public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon) {
- this(type, duration, amplifier, ambient, showParticles, showIcon, (MobEffectInstance)null, type.createFactorData());
+ // Purpur start
-+ this(type, duration, amplifier, ambient, showParticles, showIcon, (MobEffectInstance)null, type.createFactorData(), (NamespacedKey)null);
++ this(type, duration, amplifier, ambient, showParticles, showIcon, (MobEffectInstance)null, type.createFactorData(), (org.bukkit.NamespacedKey)null);
+ }
+
-+ public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon, @Nullable NamespacedKey key) {
++ public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon, @Nullable org.bukkit.NamespacedKey key) {
+ this(type, duration, amplifier, ambient, showParticles, showIcon, (MobEffectInstance)null, type.createFactorData(), key);
+ // Purpur end
}
public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon, @Nullable MobEffectInstance hiddenEffect, Optional factorCalculationData) {
+ // Purpur start
-+ this(type, duration, amplifier, ambient, showParticles, showIcon, hiddenEffect, factorCalculationData, (NamespacedKey) null);
++ this(type, duration, amplifier, ambient, showParticles, showIcon, hiddenEffect, factorCalculationData, (org.bukkit.NamespacedKey) null);
+ }
+
-+ public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon, @Nullable MobEffectInstance hiddenEffect, Optional factorCalculationData, @Nullable NamespacedKey key) {
++ public MobEffectInstance(MobEffect type, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon, @Nullable MobEffectInstance hiddenEffect, Optional factorCalculationData, @Nullable org.bukkit.NamespacedKey key) {
+ // Purpur end
this.effect = type;
this.duration = duration;
@@ -4035,7 +4094,7 @@ index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6
this.hiddenEffect = hiddenEffect;
this.factorData = factorCalculationData;
}
-@@ -85,6 +106,7 @@ public class MobEffectInstance implements Comparable {
+@@ -85,6 +105,7 @@ public class MobEffectInstance implements Comparable {
this.ambient = that.ambient;
this.visible = that.visible;
this.showIcon = that.showIcon;
@@ -4043,7 +4102,7 @@ index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6
}
public boolean update(MobEffectInstance that) {
-@@ -129,6 +151,13 @@ public class MobEffectInstance implements Comparable {
+@@ -129,6 +150,13 @@ public class MobEffectInstance implements Comparable {
bl = true;
}
@@ -4057,7 +4116,7 @@ index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6
return bl;
}
-@@ -172,6 +201,17 @@ public class MobEffectInstance implements Comparable {
+@@ -172,6 +200,17 @@ public class MobEffectInstance implements Comparable {
return this.showIcon;
}
@@ -4067,7 +4126,7 @@ index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6
+ }
+
+ @Nullable
-+ public NamespacedKey getKey() {
++ public org.bukkit.NamespacedKey getKey() {
+ return this.key;
+ }
+ // Purpur end
@@ -4075,7 +4134,7 @@ index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6
public boolean tick(LivingEntity entity, Runnable overwriteCallback) {
if (this.hasRemainingDuration()) {
int i = this.isInfiniteDuration() ? entity.tickCount : this.duration;
-@@ -232,6 +272,12 @@ public class MobEffectInstance implements Comparable {
+@@ -232,6 +271,12 @@ public class MobEffectInstance implements Comparable {
string = string + ", Show Icon: false";
}
@@ -4088,7 +4147,7 @@ index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6
return string;
}
-@@ -247,7 +293,7 @@ public class MobEffectInstance implements Comparable {
+@@ -247,7 +292,7 @@ public class MobEffectInstance implements Comparable {
return false;
} else {
MobEffectInstance mobEffectInstance = (MobEffectInstance)object;
@@ -4097,7 +4156,7 @@ index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6
}
}
-@@ -272,6 +318,11 @@ public class MobEffectInstance implements Comparable {
+@@ -272,6 +317,11 @@ public class MobEffectInstance implements Comparable {
nbt.putBoolean("ambient", this.isAmbient());
nbt.putBoolean("show_particles", this.isVisible());
nbt.putBoolean("show_icon", this.showIcon());
@@ -4109,21 +4168,21 @@ index 68e1b8271475996020af50b3b2cf04cd25aa6c85..4f2fcbcf90d6f5ee89e35c993a65cae6
if (this.hiddenEffect != null) {
CompoundTag compoundTag = new CompoundTag();
this.hiddenEffect.save(compoundTag);
-@@ -306,6 +357,13 @@ public class MobEffectInstance implements Comparable {
+@@ -306,6 +356,13 @@ public class MobEffectInstance implements Comparable {
bl3 = nbt.getBoolean("show_icon");
}
+ // Purpur start
-+ NamespacedKey key = null;
++ org.bukkit.NamespacedKey key = null;
+ if (nbt.contains("key")) {
-+ key = NamespacedKey.fromString(nbt.getString("key"));
++ key = org.bukkit.NamespacedKey.fromString(nbt.getString("key"));
+ }
+ // Purpur end
+
MobEffectInstance mobEffectInstance = null;
if (nbt.contains("hidden_effect", 10)) {
mobEffectInstance = loadSpecifiedEffect(type, nbt.getCompound("hidden_effect"));
-@@ -318,7 +376,7 @@ public class MobEffectInstance implements Comparable {
+@@ -318,7 +375,7 @@ public class MobEffectInstance implements Comparable {
optional = Optional.empty();
}
@@ -4187,19 +4246,19 @@ index 1f9e0c139988c4c44a26552881647d36965aa4fa..b8d612d22aca74a08b53393c0723a2ae
@Override
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48082750ef 100644
+index a8d8d261daed2ebbbea3f4f356434942997ba541..93e558e1cfcdee33abf6f1c57e4cf47c7f53f750 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -156,7 +156,7 @@ import org.bukkit.plugin.PluginManager;
+@@ -159,7 +159,7 @@ import org.bukkit.plugin.PluginManager;
// CraftBukkit end
- public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+ public abstract class Entity implements Nameable, EntityAccess, CommandSource, ScoreHolder {
-
+ public static javax.script.ScriptEngine scriptEngine = new javax.script.ScriptEngineManager().getEngineByName("rhino"); // Purpur
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation
-@@ -334,7 +334,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -337,7 +337,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
public double xOld;
public double yOld;
public double zOld;
@@ -4208,7 +4267,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
public boolean noPhysics;
public final RandomSource random;
public int tickCount;
-@@ -376,7 +376,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -379,7 +379,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
private final Set tags;
private final double[] pistonDeltas;
private long pistonDeltasGameTime;
@@ -4217,15 +4276,15 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
private float eyeHeight;
public boolean isInPowderSnow;
public boolean wasInPowderSnow;
-@@ -418,6 +418,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -424,6 +424,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
+ private UUID originWorld;
public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
- public boolean collidingWithWorldBorder; // Paper
- public boolean fixedPose = false; // Paper
+ 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();
-@@ -493,6 +494,25 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -499,6 +500,25 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
return false;
}
@@ -4251,7 +4310,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
public final boolean hardCollides() {
return this.hardCollides;
}
-@@ -575,7 +595,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -581,7 +601,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
this.bb = Entity.INITIAL_AABB;
this.stuckSpeedMultiplier = Vec3.ZERO;
this.nextStep = 1.0F;
@@ -4260,7 +4319,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
this.remainingFireTicks = -this.getFireImmuneTicks();
this.fluidHeight = new Object2DoubleArrayMap(2);
this.fluidOnEyes = new HashSet();
-@@ -823,7 +843,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -833,7 +853,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
// CraftBukkit end
public void baseTick() {
@@ -4269,7 +4328,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
if (firstTick && this instanceof net.minecraft.world.entity.NeutralMob neutralMob) neutralMob.tickInitialPersistentAnger(level); // Paper - Update last hurt when ticking
this.feetBlockState = null;
if (this.isPassenger() && this.getVehicle().isRemoved()) {
-@@ -884,7 +904,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -894,7 +914,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
this.firstTick = false;
@@ -4278,7 +4337,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
}
public void setSharedFlagOnFire(boolean onFire) {
-@@ -893,10 +913,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -903,10 +923,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
public void checkBelowWorld() {
// Paper start - Configurable nether ceiling damage
@@ -4291,7 +4350,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
this.onBelowWorld();
}
-@@ -1103,7 +1124,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -1113,7 +1134,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
}
@@ -4300,7 +4359,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
if (this.stuckSpeedMultiplier.lengthSqr() > 1.0E-7D) {
movement = movement.multiply(this.stuckSpeedMultiplier);
this.stuckSpeedMultiplier = Vec3.ZERO;
-@@ -1112,7 +1133,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -1122,7 +1143,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
// Paper start - ignore movement changes while inactive.
if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof net.minecraft.world.entity.vehicle.AbstractMinecart) && movement == getDeltaMovement() && movementType == MoverType.SELF) {
setDeltaMovement(Vec3.ZERO);
@@ -4309,7 +4368,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
return;
}
// Paper end
-@@ -1133,8 +1154,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -1143,8 +1164,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
this.setPos(this.getX() + vec3d1.x, this.getY() + vec3d1.y, this.getZ() + vec3d1.z);
}
@@ -4320,7 +4379,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
boolean flag = !Mth.equal(movement.x, vec3d1.x);
boolean flag1 = !Mth.equal(movement.z, vec3d1.z);
-@@ -1153,7 +1174,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -1163,7 +1184,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
this.checkFallDamage(vec3d1.y, this.onGround(), iblockdata, blockposition);
if (this.isRemoved()) {
@@ -4329,7 +4388,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
} else {
if (this.horizontalCollision) {
Vec3 vec3d2 = this.getDeltaMovement();
-@@ -1291,7 +1312,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -1301,7 +1322,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
this.setRemainingFireTicks(-this.getFireImmuneTicks());
}
@@ -4338,7 +4397,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
}
}
// Paper start - detailed watchdog information
-@@ -1793,7 +1814,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -1799,7 +1820,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
public boolean fireImmune() {
@@ -4347,7 +4406,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
}
public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) {
-@@ -1866,7 +1887,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -1872,7 +1893,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
return this.isInWater() || flag;
}
@@ -4356,32 +4415,31 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
Entity entity = this.getVehicle();
if (entity instanceof Boat) {
-@@ -2467,6 +2488,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
- nbt.putBoolean("Paper.FreezeLock", true);
+@@ -2491,6 +2512,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
+ nbttagcompound.putBoolean("Paper.FreezeLock", true);
}
// Paper end
+ // Purpur start
+ if (immuneToFire != null) {
-+ nbt.putBoolean("Purpur.FireImmune", immuneToFire);
++ nbttagcompound.putBoolean("Purpur.FireImmune", immuneToFire);
+ }
+ // Purpur end
- return nbt;
+ return nbttagcompound;
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT");
-@@ -2614,7 +2640,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -2638,6 +2664,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
freezeLocked = nbt.getBoolean("Paper.FreezeLock");
}
// Paper end
--
+ // Purpur start
+ if (nbt.contains("Purpur.FireImmune")) {
+ immuneToFire = nbt.getBoolean("Purpur.FireImmune");
+ }
+ // Purpur end
+
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT");
- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded");
-@@ -2984,6 +3014,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -3013,6 +3044,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
this.passengers = ImmutableList.copyOf(list);
}
@@ -4395,20 +4453,22 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
this.gameEvent(GameEvent.ENTITY_MOUNT, passenger);
}
}
-@@ -3024,6 +3061,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -3052,6 +3090,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
return false;
}
- // Spigot end
+ // CraftBukkit end
++
+ // Purpur start
+ if (this.rider != null && this.passengers.get(0) == this.rider) {
+ onDismount(this.rider);
+ this.rider = null;
+ }
+ // Purpur end
++
if (this.passengers.size() == 1 && this.passengers.get(0) == entity) {
this.passengers = ImmutableList.of();
} else {
-@@ -3103,12 +3146,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -3131,12 +3177,15 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
return Vec3.directionFromRotation(this.getRotationVector());
}
@@ -4425,7 +4485,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
}
this.isInsidePortal = true;
-@@ -3126,7 +3172,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -3154,7 +3203,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
ServerLevel worldserver1 = minecraftserver.getLevel(resourcekey);
if (true && !this.isPassenger() && this.portalTime++ >= i) { // CraftBukkit
@@ -4434,7 +4494,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
this.portalTime = i;
// Paper start
io.papermc.paper.event.entity.EntityPortalReadyEvent event = new io.papermc.paper.event.entity.EntityPortalReadyEvent(this.getBukkitEntity(), worldserver1 == null ? null : worldserver1.getWorld(), org.bukkit.PortalType.NETHER);
-@@ -3144,7 +3190,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -3172,7 +3221,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
} // Paper
// CraftBukkit end
@@ -4443,15 +4503,16 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
}
this.isInsidePortal = false;
-@@ -3159,6 +3205,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -3187,7 +3236,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
this.processPortalCooldown();
-+ if (this.level().purpurConfig.endPortalSafeTeleporting) // Purpur
- this.tickEndPortal(); // Paper - make end portalling safe
+- this.tickEndPortal(); // Paper - make end portalling safe
++ if (this.level().purpurConfig.endPortalSafeTeleporting) this.tickEndPortal(); // Paper - make end portalling safe // Purpur
}
}
-@@ -3349,7 +3396,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+
+@@ -3377,7 +3426,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
public int getMaxAirSupply() {
@@ -4460,7 +4521,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
}
public int getAirSupply() {
-@@ -3619,14 +3666,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -3647,14 +3696,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
// Paper end
if (this.level() instanceof ServerLevel && !this.isRemoved()) {
@@ -4477,7 +4538,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
PortalInfo shapedetectorshape = (location == null) ? this.findDimensionEntryPoint(worldserver) : new PortalInfo(new Vec3(location.x(), location.y(), location.z()), Vec3.ZERO, this.yRot, this.xRot, worldserver, null); // CraftBukkit
if (shapedetectorshape == null) {
-@@ -3665,7 +3712,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -3693,7 +3742,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
this.unRide();
// CraftBukkit end
@@ -4486,7 +4547,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
// Paper start - Change lead drop timing to prevent dupe
if (this instanceof Mob) {
((Mob) this).dropLeash(true, true); // Paper drop lead
-@@ -3688,10 +3735,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -3720,10 +3769,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
this.removeAfterChangingDimensions();
@@ -4499,7 +4560,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
return entity;
}
} else {
-@@ -3811,7 +3858,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -3843,7 +3892,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
public boolean canChangeDimensions() {
@@ -4508,7 +4569,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
}
public float getBlockExplosionResistance(Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState, float max) {
-@@ -4104,6 +4151,20 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -4141,6 +4190,20 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
return SlotAccess.NULL;
}
@@ -4529,7 +4590,7 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
@Override
public void sendSystemMessage(Component message) {}
-@@ -4373,6 +4434,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -4421,6 +4484,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
this.yRotO = this.getYRot();
}
@@ -4542,11 +4603,10 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
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;
-@@ -4938,4 +5005,45 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -4986,4 +5055,44 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
return ((net.minecraft.server.level.ServerChunkCache) level.getChunkSource()).isPositionTicking(this);
}
// Paper end
-+
+ // Purpur start
+ @Nullable
+ private Player rider = null;
@@ -4589,22 +4649,22 @@ index 80c9a523e94704f73e833e2255af6b0bf55da454..a13e6d41584a55e3e17d55d568b23f48
+ // 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 3ff999734d14e2b6e7828e117f5ee32a60c26bc1..cfa9607241c3e69777ffc317206996c2f783437a 100644
+index dbbce471c35849ea7d7ad07e9db9b7d8d85690df..5eb63d857fea0f1c4dc1e6e4c7af8ea653dc7963 100644
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
-@@ -39,6 +39,7 @@ public final class EntitySelector {
+@@ -40,6 +40,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
+ // Paper end - Ability to control player's insomnia and phantoms
+ public static Predicate notAfk = (player) -> !player.isAfk(); // Purpur
private EntitySelector() {}
// Paper start
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
-index 2561e74ffdf595a9b6ae13dcd738662c772db442..5930e45bae5aa86b3cedb811c4c9bb92099bc1b5 100644
+index 0ffd377dba738bd651b0c7f5ca0a0d61aaa1d82c..bf4338521cfb3527164f83baf0c6c7065215771d 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
-@@ -309,13 +309,24 @@ public class EntityType implements FeatureElement, EntityTypeT
+@@ -313,13 +313,24 @@ public class EntityType implements FeatureElement, EntityTypeT
private Component description;
@Nullable
private ResourceLocation lootTable;
@@ -4630,7 +4690,7 @@ index 2561e74ffdf595a9b6ae13dcd738662c772db442..5930e45bae5aa86b3cedb811c4c9bb92
public static ResourceLocation getKey(EntityType> type) {
return BuiltInRegistries.ENTITY_TYPE.getKey(type);
}
-@@ -531,6 +542,16 @@ public class EntityType implements FeatureElement, EntityTypeT
+@@ -535,6 +546,16 @@ public class EntityType implements FeatureElement, EntityTypeT
return this.category;
}
@@ -4647,7 +4707,7 @@ index 2561e74ffdf595a9b6ae13dcd738662c772db442..5930e45bae5aa86b3cedb811c4c9bb92
public String getDescriptionId() {
if (this.descriptionId == null) {
this.descriptionId = Util.makeDescriptionId("entity", BuiltInRegistries.ENTITY_TYPE.getKey(this));
-@@ -592,6 +613,12 @@ public class EntityType implements FeatureElement, EntityTypeT
+@@ -602,6 +623,12 @@ public class EntityType implements FeatureElement, EntityTypeT
entity.load(nbt);
}, () -> {
EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id"));
@@ -4661,7 +4721,7 @@ index 2561e74ffdf595a9b6ae13dcd738662c772db442..5930e45bae5aa86b3cedb811c4c9bb92
}
diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
-index 6dac7cd4c9abfbde299f5d279acc2739195fc312..2bcbfe5516e30a150aa133cf8c1561b784443778 100644
+index b37e13c5de1a0a22a3713d04b203afc6c03ccbac..798cd8e0aae377122995155f4031d186ac4e35f7 100644
--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
@@ -313,7 +313,7 @@ public class ExperienceOrb extends Entity {
@@ -4745,10 +4805,10 @@ index 1bb8b6e91c44cd13411d96d749fa64835c75a267..b18cbe85330e26de6f6cbfcc3d51a741
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 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b26bfd5947 100644
+index 9b7e786d5ae6bdeeb96df6e9c4d1b24e1e856e58..3b1c09f8afe1a008df4b75b605a796bfb1bf3899 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-@@ -218,9 +218,9 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -217,9 +217,9 @@ public abstract class LivingEntity extends Entity implements Attackable {
protected int deathScore;
public float lastHurt;
public boolean jumping;
@@ -4761,23 +4821,23 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
protected int lerpSteps;
protected double lerpX;
protected double lerpY;
-@@ -253,6 +253,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
- private boolean skipDropExperience;
+@@ -252,6 +252,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+ protected boolean skipDropExperience;
// CraftBukkit start
public int expToDrop;
+ public float safeFallDistance = 3.0F; // Purpur
public boolean forceDrops;
- public ArrayList drops = new ArrayList<>(); // Paper
+ public ArrayList drops = new ArrayList<>(); // Paper - Restore vanilla drops behavior
public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes;
-@@ -262,6 +263,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -261,6 +262,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
+ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
+ protected boolean shouldBurnInDay = false; public boolean shouldBurnInDay() { return this.shouldBurnInDay; } public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } // Purpur
@Override
public float getBukkitYaw() {
-@@ -286,7 +288,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -285,7 +287,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.effectsDirty = true;
this.useItem = ItemStack.EMPTY;
this.lastClimbablePos = Optional.empty();
@@ -4787,7 +4847,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
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());
-@@ -302,6 +305,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -301,6 +304,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()))));
}
@@ -4796,7 +4856,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
public Brain> getBrain() {
return this.brain;
}
-@@ -337,6 +342,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -336,6 +341,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);
}
@@ -4804,7 +4864,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
@Override
protected void checkFallDamage(double heightDifference, boolean onGround, BlockState state, BlockPos landedPosition) {
-@@ -349,7 +355,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -348,7 +354,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.tryAddSoulSpeed();
}
@@ -4813,7 +4873,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
double d1 = this.getX();
double d2 = this.getY();
double d3 = this.getZ();
-@@ -364,7 +370,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -363,7 +369,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
d3 = (double) landedPosition.getZ() + 0.5D + d5 / d6 * 0.5D;
}
@@ -4822,7 +4882,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
double d7 = Math.min((double) (0.2F + f / 15.0F), 2.5D);
int i = (int) (150.0D * d7);
-@@ -404,7 +410,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -403,7 +409,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
super.baseTick();
@@ -4831,7 +4891,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
if (this.fireImmune() || this.level().isClientSide) {
this.clearFire();
}
-@@ -422,6 +428,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -421,6 +427,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
double d1 = this.level().getWorldBorder().getDamagePerBlock();
if (d1 > 0.0D) {
@@ -4839,7 +4899,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
this.hurt(this.damageSources().outOfBorder(), (float) Math.max(1, Mth.floor(-d0 * d1)));
}
}
-@@ -433,7 +440,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -432,7 +439,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
if (flag1) {
this.setAirSupply(this.decreaseAirSupply(this.getAirSupply()));
@@ -4848,7 +4908,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
this.setAirSupply(0);
Vec3 vec3d = this.getDeltaMovement();
-@@ -445,7 +452,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -444,7 +451,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);
}
@@ -4857,7 +4917,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
}
}
-@@ -506,7 +513,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -505,7 +512,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.yHeadRotO = this.yHeadRot;
this.yRotO = this.getYRot();
this.xRotO = this.getXRot();
@@ -4866,7 +4926,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
}
public boolean canSpawnSoulSpeedParticle() {
-@@ -798,6 +805,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -797,6 +804,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> {
nbt.put("Brain", nbtbase);
});
@@ -4886,7 +4946,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
}
// CraftBukkit start
-@@ -1027,9 +1040,29 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -1027,9 +1040,31 @@ public abstract class LivingEntity extends Entity implements Attackable {
ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD);
EntityType> entitytypes = entity.getType();
@@ -4905,7 +4965,9 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
+ else if ((entitytypes == EntityType.PIGLIN || entitytypes == EntityType.PIGLIN_BRUTE) && itemstack.is(Items.PIGLIN_HEAD)) {
+ d0 *= entity.level().purpurConfig.piglinHeadVisibilityPercent;
+ }
++ // Purpur end
+
++ // Purpur start
+ if (entity instanceof LivingEntity entityliving) {
+ if (entityliving.hasEffect(MobEffects.BLINDNESS)) {
+ int amplifier = entityliving.getEffect(MobEffects.BLINDNESS).getAmplifier();
@@ -4918,7 +4980,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
}
return d0;
-@@ -1089,6 +1122,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -1089,6 +1124,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
for (flag = false; iterator.hasNext(); flag = true) {
// CraftBukkit start
MobEffectInstance effect = (MobEffectInstance) iterator.next();
@@ -4926,7 +4988,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED);
if (event.isCancelled()) {
continue;
-@@ -1511,13 +1545,13 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -1511,13 +1547,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;
@@ -4942,7 +5004,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
LivingEntity entityliving2 = entitywolf.getOwner();
if (entityliving2 instanceof net.minecraft.world.entity.player.Player) {
-@@ -1625,6 +1659,18 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -1625,6 +1661,18 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
}
@@ -4961,7 +5023,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
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);
-@@ -1792,7 +1838,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -1790,7 +1838,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
boolean flag = false;
if (this.dead && adversary instanceof WitherBoss) { // Paper
@@ -4970,7 +5032,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
BlockPos blockposition = this.blockPosition();
BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState();
-@@ -1838,6 +1884,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -1836,6 +1884,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.dropEquipment(); // CraftBukkit - from below
if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
@@ -4978,7 +5040,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
this.dropFromLootTable(source, flag);
// Paper start
final boolean prev = this.clearEquipmentSlots;
-@@ -1846,6 +1893,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -1844,6 +1893,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
// Paper end
this.dropCustomDeathLoot(source, i, flag);
this.clearEquipmentSlots = prev; // Paper
@@ -4986,7 +5048,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
}
// CraftBukkit start - Call death event // Paper start - call advancement triggers with correct entity equipment
org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops, () -> {
-@@ -2093,7 +2141,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -2091,7 +2141,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
MobEffectInstance mobeffect = this.getEffect(MobEffects.JUMP);
float f2 = mobeffect == null ? 0.0F : (float) (mobeffect.getAmplifier() + 1);
@@ -4995,28 +5057,28 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
}
}
-@@ -2316,6 +2364,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -2314,6 +2364,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
}
-+ // Purpur start
-+ if (damagesource.getEntity() instanceof net.minecraft.world.entity.player.Player player && damagesource.getEntity().level().purpurConfig.creativeOnePunch) {
-+ if (player.isCreative()) {
-+ double attackDamage = 0;
-+ for (AttributeModifier modifier : player.getMainHandItem().getAttributeModifiers(EquipmentSlot.MAINHAND).get(Attributes.ATTACK_DAMAGE)) {
-+ attackDamage += modifier.getAmount();
-+ }
-+ if (attackDamage == 0) {
-+ this.setHealth(0);
-+ }
-+ }
-+ }
-+ // Purpur end
++ // Purpur start
++ if (damagesource.getEntity() instanceof net.minecraft.world.entity.player.Player player && damagesource.getEntity().level().purpurConfig.creativeOnePunch) {
++ if (player.isCreative()) {
++ double attackDamage = 0;
++ for (AttributeModifier modifier : player.getMainHandItem().getAttributeModifiers(EquipmentSlot.MAINHAND).get(Attributes.ATTACK_DAMAGE)) {
++ attackDamage += modifier.getAmount();
++ }
++ if (attackDamage == 0) {
++ this.setHealth(0);
++ }
++ }
++ }
++ // Purpur end
+
if (f > 0 || !human) {
if (human) {
// PAIL: Be sure to drag all this code from the EntityHuman subclass each update.
-@@ -2536,7 +2598,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -2534,7 +2598,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
@Override
protected void onBelowWorld() {
@@ -5025,7 +5087,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
}
protected void updateSwingTime() {
-@@ -2730,7 +2792,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -2728,7 +2792,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
protected long lastJumpTime = 0L; // Paper
@@ -5034,7 +5096,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
Vec3 vec3d = this.getDeltaMovement();
// Paper start
long time = System.nanoTime();
-@@ -2882,6 +2944,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -2880,6 +2944,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
if (f3 > 0.0F) {
this.playSound(this.getFallDamageSound((int) f3), 1.0F, 1.0F);
@@ -5042,7 +5104,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
this.hurt(this.damageSources().flyIntoWall(), f3);
}
}
-@@ -3103,10 +3166,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -3101,10 +3166,10 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
this.run += (f3 - this.run) * 0.3F;
@@ -5056,7 +5118,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
// Paper start - stop large pitch and yaw changes from crashing the server
this.yRotO += Math.round((this.getYRot() - this.yRotO) / 360.0F) * 360.0F;
-@@ -3118,7 +3181,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -3116,7 +3181,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.yHeadRotO += Math.round((this.yHeadRot - this.yHeadRotO) / 360.0F) * 360.0F;
// Paper end
@@ -5065,7 +5127,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
this.animStep += f2;
if (this.isFallFlying()) {
++this.fallFlyTicks;
-@@ -3408,19 +3471,19 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -3411,19 +3476,19 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
this.setDeltaMovement(d0, d1, d2);
@@ -5090,7 +5152,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
if (this.jumping && this.isAffectedByFluids()) {
double d3;
-@@ -3447,8 +3510,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -3450,8 +3515,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.noJumpDelay = 0;
}
@@ -5101,7 +5163,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
this.xxa *= 0.98F;
this.zza *= 0.98F;
this.updateFallFlying();
-@@ -3475,8 +3538,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -3478,8 +3543,8 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.travel(vec3d1);
}
@@ -5109,10 +5171,10 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
- this.level().getProfiler().push("freezing");
+ //this.level().getProfiler().pop(); // Purpur
+ //this.level().getProfiler().push("freezing"); // Purpur
- if (!this.level().isClientSide && !this.isDeadOrDying() && !freezeLocked) { // Paper - Freeze Tick Lock API
+ if (!this.level().isClientSide && !this.isDeadOrDying() && !this.freezeLocked) { // Paper - Freeze Tick Lock API
int i = this.getTicksFrozen();
-@@ -3493,18 +3556,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -3496,18 +3561,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
this.hurt(this.damageSources().freeze(), 1.0F);
}
@@ -5138,7 +5200,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
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());
-@@ -3514,12 +3579,48 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -3517,12 +3584,48 @@ 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());
}
}
@@ -5187,7 +5249,7 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
}
public boolean isSensitiveToWater() {
-@@ -3540,7 +3641,16 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -3543,7 +3646,16 @@ public abstract class LivingEntity extends Entity implements Attackable {
int j = i / 10;
if (j % 2 == 0) {
@@ -5206,10 +5268,10 @@ index 3b9ee3324a084271862ed790e8fc0d469e877ec1..7fdb4d5eb1ab6c45c88ca18112d5b1b2
});
}
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
-index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c57a05fd4 100644
+index 2f3dc569ff9cdead48aa831c96c027cc7255d609..4c0d710d20e074ad4a0fdd1cd4c0c3d3383b68a5 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
-@@ -65,6 +65,7 @@ import net.minecraft.world.item.ProjectileWeaponItem;
+@@ -66,6 +66,7 @@ import net.minecraft.world.item.ProjectileWeaponItem;
import net.minecraft.world.item.SpawnEggItem;
import net.minecraft.world.item.SwordItem;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
@@ -5217,7 +5279,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.Level;
-@@ -134,6 +135,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -135,6 +136,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
private BlockPos restrictCenter;
private float restrictRadius;
@@ -5225,7 +5287,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
public boolean aware = true; // CraftBukkit
protected Mob(EntityType extends Mob> type, Level world) {
-@@ -147,8 +149,8 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -148,8 +150,8 @@ public abstract class Mob extends LivingEntity implements Targeting {
this.restrictRadius = -1.0F;
this.goalSelector = new GoalSelector(world.getProfilerSupplier());
this.targetSelector = new GoalSelector(world.getProfilerSupplier());
@@ -5236,7 +5298,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
this.jumpControl = new JumpControl(this);
this.bodyRotationControl = this.createBodyControl();
this.navigation = this.createNavigation(world);
-@@ -323,6 +325,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -324,6 +326,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
entityliving = null;
}
}
@@ -5244,7 +5306,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
this.target = entityliving;
return true;
// CraftBukkit end
-@@ -363,15 +366,35 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -364,15 +367,35 @@ public abstract class Mob extends LivingEntity implements Targeting {
@Override
public void baseTick() {
super.baseTick();
@@ -5282,7 +5344,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
@Override
protected void playHurtSound(DamageSource source) {
this.resetAmbientSoundTime();
-@@ -561,6 +584,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -562,6 +585,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
}
nbt.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit
@@ -5290,7 +5352,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
}
@Override
-@@ -631,6 +655,11 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -632,6 +656,11 @@ public abstract class Mob extends LivingEntity implements Targeting {
this.aware = nbt.getBoolean("Bukkit.Aware");
}
// CraftBukkit end
@@ -5302,7 +5364,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
}
@Override
-@@ -674,8 +703,8 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -675,8 +704,8 @@ public abstract class Mob extends LivingEntity implements Targeting {
@Override
public void aiStep() {
super.aiStep();
@@ -5313,7 +5375,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
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();
-@@ -694,7 +723,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -695,7 +724,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
}
}
@@ -5322,7 +5384,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
}
protected Vec3i getPickupReach() {
-@@ -906,46 +935,46 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -907,46 +936,46 @@ public abstract class Mob extends LivingEntity implements Targeting {
return;
}
// Paper end
@@ -5348,7 +5410,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
+ //this.level().getProfiler().pop(); // Purpur
} else {
- this.level().getProfiler().push("targetSelector");
-+ //this.level().getProfiler().push("targetSelector");
++ //this.level().getProfiler().push("targetSelector"); // Purpur
if (this.targetSelector.inactiveTick(this.activatedPriority, false)) // Pufferfish - use this to alternate ticking
this.targetSelector.tick();
- this.level().getProfiler().pop();
@@ -5389,7 +5451,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
this.sendDebugPackets();
}
-@@ -1174,6 +1203,12 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -1175,6 +1204,12 @@ public abstract class Mob extends LivingEntity implements Targeting {
}
@@ -5402,7 +5464,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
@Nullable
public static Item getEquipmentForSlot(EquipmentSlot equipmentSlot, int equipmentLevel) {
switch (equipmentSlot) {
-@@ -1268,7 +1303,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -1269,7 +1304,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
RandomSource randomsource = world.getRandom();
this.getAttribute(Attributes.FOLLOW_RANGE).addPermanentModifier(new AttributeModifier("Random spawn bonus", randomsource.triangle(0.0D, 0.11485000000000001D), AttributeModifier.Operation.MULTIPLY_BASE));
@@ -5411,7 +5473,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
this.setLeftHanded(true);
} else {
this.setLeftHanded(false);
-@@ -1316,6 +1351,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -1317,6 +1352,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
if (!this.isAlive()) {
return InteractionResult.PASS;
} else if (this.getLeashHolder() == player) {
@@ -5419,7 +5481,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
// CraftBukkit start - fire PlayerUnleashEntityEvent
// Paper start - drop leash variable
org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, hand, !player.getAbilities().instabuild);
-@@ -1389,7 +1425,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -1390,7 +1426,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
protected void onOffspringSpawnedFromEgg(Player player, Mob child) {}
protected InteractionResult mobInteract(Player player, InteractionHand hand) {
@@ -5428,7 +5490,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
}
public boolean isWithinRestriction() {
-@@ -1700,6 +1736,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -1701,6 +1737,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
this.setLastHurtMob(target);
}
@@ -5436,7 +5498,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
return flag;
}
-@@ -1716,17 +1753,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -1721,17 +1758,7 @@ public abstract class Mob extends LivingEntity implements Targeting {
}
public boolean isSunBurnTick() {
@@ -5455,7 +5517,7 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
}
@Override
-@@ -1773,4 +1800,56 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -1779,4 +1806,56 @@ public abstract class Mob extends LivingEntity implements Targeting {
return itemmonsteregg == null ? null : new ItemStack(itemmonsteregg);
}
@@ -5513,24 +5575,18 @@ index 944c22ea172796492a683d2f2bddfb0938d7a8c9..80c03bd4e5d7e20bb8a4e14af5620f5c
+ // 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 5e8cc5cfac8888628c6d513148f41be09ca65a2c..a089fc61ec09be6b7490375489178dc6ba5a644b 100644
+index 2ee48ac3b665db2b02bcb1a30ec972d43a3725b0..59e8f5431ce5026209e1428b5fa5b5485dcfebc7 100644
--- a/src/main/java/net/minecraft/world/entity/Shearable.java
+++ b/src/main/java/net/minecraft/world/entity/Shearable.java
-@@ -3,7 +3,13 @@ package net.minecraft.world.entity;
- import net.minecraft.sounds.SoundSource;
-
- public interface Shearable {
-- void shear(SoundSource shearedSoundCategory);
-+ // Purpur start
-+ default void shear(SoundSource shearedSoundCategory) {
-+ shear(shearedSoundCategory, 0);
-+ }
-+
-+ void shear(SoundSource shearedSoundCategory, int looting);
-+ // Purpur end
+@@ -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 3087f8359b098682a345399c85395de8a15b6eed..6b0855cffb901dbc7dcc5fd44506275206bc9a2d 100644
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
@@ -5568,96 +5624,97 @@ index 3087f8359b098682a345399c85395de8a15b6eed..6b0855cffb901dbc7dcc5fd445062752
}
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 8a720f9ae81d7ea856e28cb27a66adcf04bcb0eb..e0b70d9732a2b7d96999b7e4a497ffa1d8cf86a7 100644
+index 0a13e076b42bc8c0e7d4962379c207dea89f0435..2d7afaa67c762107717486cb9dbbf6f8f967396c 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
-@@ -80,7 +80,88 @@ import org.slf4j.Logger;
+@@ -81,7 +81,89 @@ import org.slf4j.Logger;
public class DefaultAttributes {
private static final Logger LOGGER = LogUtils.getLogger();
-- private static final Map, AttributeSupplier> SUPPLIERS = ImmutableMap., AttributeSupplier>builder().put(EntityType.ALLAY, Allay.createAttributes().build()).put(EntityType.ARMOR_STAND, LivingEntity.createLivingAttributes().build()).put(EntityType.AXOLOTL, Axolotl.createAttributes().build()).put(EntityType.BAT, Bat.createAttributes().build()).put(EntityType.BEE, Bee.createAttributes().build()).put(EntityType.BLAZE, Blaze.createAttributes().build()).put(EntityType.CAT, Cat.createAttributes().build()).put(EntityType.CAMEL, Camel.createAttributes().build()).put(EntityType.CAVE_SPIDER, CaveSpider.createCaveSpider().build()).put(EntityType.CHICKEN, Chicken.createAttributes().build()).put(EntityType.COD, AbstractFish.createAttributes().build()).put(EntityType.COW, Cow.createAttributes().build()).put(EntityType.CREEPER, Creeper.createAttributes().build()).put(EntityType.DOLPHIN, Dolphin.createAttributes().build()).put(EntityType.DONKEY, AbstractChestedHorse.createBaseChestedHorseAttributes().build()).put(EntityType.DROWNED, Zombie.createAttributes().build()).put(EntityType.ELDER_GUARDIAN, ElderGuardian.createAttributes().build()).put(EntityType.ENDERMAN, EnderMan.createAttributes().build()).put(EntityType.ENDERMITE, Endermite.createAttributes().build()).put(EntityType.ENDER_DRAGON, EnderDragon.createAttributes().build()).put(EntityType.EVOKER, Evoker.createAttributes().build()).put(EntityType.FOX, Fox.createAttributes().build()).put(EntityType.FROG, Frog.createAttributes().build()).put(EntityType.GHAST, Ghast.createAttributes().build()).put(EntityType.GIANT, Giant.createAttributes().build()).put(EntityType.GLOW_SQUID, GlowSquid.createAttributes().build()).put(EntityType.GOAT, Goat.createAttributes().build()).put(EntityType.GUARDIAN, Guardian.createAttributes().build()).put(EntityType.HOGLIN, Hoglin.createAttributes().build()).put(EntityType.HORSE, AbstractHorse.createBaseHorseAttributes().build()).put(EntityType.HUSK, Zombie.createAttributes().build()).put(EntityType.ILLUSIONER, Illusioner.createAttributes().build()).put(EntityType.IRON_GOLEM, IronGolem.createAttributes().build()).put(EntityType.LLAMA, Llama.createAttributes().build()).put(EntityType.MAGMA_CUBE, MagmaCube.createAttributes().build()).put(EntityType.MOOSHROOM, Cow.createAttributes().build()).put(EntityType.MULE, AbstractChestedHorse.createBaseChestedHorseAttributes().build()).put(EntityType.OCELOT, Ocelot.createAttributes().build()).put(EntityType.PANDA, Panda.createAttributes().build()).put(EntityType.PARROT, Parrot.createAttributes().build()).put(EntityType.PHANTOM, Monster.createMonsterAttributes().build()).put(EntityType.PIG, Pig.createAttributes().build()).put(EntityType.PIGLIN, Piglin.createAttributes().build()).put(EntityType.PIGLIN_BRUTE, PiglinBrute.createAttributes().build()).put(EntityType.PILLAGER, Pillager.createAttributes().build()).put(EntityType.PLAYER, Player.createAttributes().build()).put(EntityType.POLAR_BEAR, PolarBear.createAttributes().build()).put(EntityType.PUFFERFISH, AbstractFish.createAttributes().build()).put(EntityType.RABBIT, Rabbit.createAttributes().build()).put(EntityType.RAVAGER, Ravager.createAttributes().build()).put(EntityType.SALMON, AbstractFish.createAttributes().build()).put(EntityType.SHEEP, Sheep.createAttributes().build()).put(EntityType.SHULKER, Shulker.createAttributes().build()).put(EntityType.SILVERFISH, Silverfish.createAttributes().build()).put(EntityType.SKELETON, AbstractSkeleton.createAttributes().build()).put(EntityType.SKELETON_HORSE, SkeletonHorse.createAttributes().build()).put(EntityType.SLIME, Monster.createMonsterAttributes().build()).put(EntityType.SNIFFER, Sniffer.createAttributes().build()).put(EntityType.SNOW_GOLEM, SnowGolem.createAttributes().build()).put(EntityType.SPIDER, Spider.createAttributes().build()).put(EntityType.SQUID, Squid.createAttributes().build()).put(EntityType.STRAY, AbstractSkeleton.createAttributes().build()).put(EntityType.STRIDER, Strider.createAttributes().build()).put(EntityType.TADPOLE, Tadpole.createAttributes().build()).put(EntityType.TRADER_LLAMA, Llama.createAttributes().build()).put(EntityType.TROPICAL_FISH, AbstractFish.createAttributes().build()).put(EntityType.TURTLE, Turtle.createAttributes().build()).put(EntityType.VEX, Vex.createAttributes().build()).put(EntityType.VILLAGER, Villager.createAttributes().build()).put(EntityType.VINDICATOR, Vindicator.createAttributes().build()).put(EntityType.WARDEN, Warden.createAttributes().build()).put(EntityType.WANDERING_TRADER, Mob.createMobAttributes().build()).put(EntityType.WITCH, Witch.createAttributes().build()).put(EntityType.WITHER, WitherBoss.createAttributes().build()).put(EntityType.WITHER_SKELETON, AbstractSkeleton.createAttributes().build()).put(EntityType.WOLF, Wolf.createAttributes().build()).put(EntityType.ZOGLIN, Zoglin.createAttributes().build()).put(EntityType.ZOMBIE, Zombie.createAttributes().build()).put(EntityType.ZOMBIE_HORSE, ZombieHorse.createAttributes().build()).put(EntityType.ZOMBIE_VILLAGER, Zombie.createAttributes().build()).put(EntityType.ZOMBIFIED_PIGLIN, ZombifiedPiglin.createAttributes().build()).build();
+- private static final Map, AttributeSupplier> SUPPLIERS = ImmutableMap., AttributeSupplier>builder().put(EntityType.ALLAY, Allay.createAttributes().build()).put(EntityType.ARMOR_STAND, LivingEntity.createLivingAttributes().build()).put(EntityType.AXOLOTL, Axolotl.createAttributes().build()).put(EntityType.BAT, Bat.createAttributes().build()).put(EntityType.BEE, Bee.createAttributes().build()).put(EntityType.BLAZE, Blaze.createAttributes().build()).put(EntityType.CAT, Cat.createAttributes().build()).put(EntityType.CAMEL, Camel.createAttributes().build()).put(EntityType.CAVE_SPIDER, CaveSpider.createCaveSpider().build()).put(EntityType.CHICKEN, Chicken.createAttributes().build()).put(EntityType.COD, AbstractFish.createAttributes().build()).put(EntityType.COW, Cow.createAttributes().build()).put(EntityType.CREEPER, Creeper.createAttributes().build()).put(EntityType.DOLPHIN, Dolphin.createAttributes().build()).put(EntityType.DONKEY, AbstractChestedHorse.createBaseChestedHorseAttributes().build()).put(EntityType.DROWNED, Zombie.createAttributes().build()).put(EntityType.ELDER_GUARDIAN, ElderGuardian.createAttributes().build()).put(EntityType.ENDERMAN, EnderMan.createAttributes().build()).put(EntityType.ENDERMITE, Endermite.createAttributes().build()).put(EntityType.ENDER_DRAGON, EnderDragon.createAttributes().build()).put(EntityType.EVOKER, Evoker.createAttributes().build()).put(EntityType.BREEZE, Breeze.createAttributes().build()).put(EntityType.FOX, Fox.createAttributes().build()).put(EntityType.FROG, Frog.createAttributes().build()).put(EntityType.GHAST, Ghast.createAttributes().build()).put(EntityType.GIANT, Giant.createAttributes().build()).put(EntityType.GLOW_SQUID, GlowSquid.createAttributes().build()).put(EntityType.GOAT, Goat.createAttributes().build()).put(EntityType.GUARDIAN, Guardian.createAttributes().build()).put(EntityType.HOGLIN, Hoglin.createAttributes().build()).put(EntityType.HORSE, AbstractHorse.createBaseHorseAttributes().build()).put(EntityType.HUSK, Zombie.createAttributes().build()).put(EntityType.ILLUSIONER, Illusioner.createAttributes().build()).put(EntityType.IRON_GOLEM, IronGolem.createAttributes().build()).put(EntityType.LLAMA, Llama.createAttributes().build()).put(EntityType.MAGMA_CUBE, MagmaCube.createAttributes().build()).put(EntityType.MOOSHROOM, Cow.createAttributes().build()).put(EntityType.MULE, AbstractChestedHorse.createBaseChestedHorseAttributes().build()).put(EntityType.OCELOT, Ocelot.createAttributes().build()).put(EntityType.PANDA, Panda.createAttributes().build()).put(EntityType.PARROT, Parrot.createAttributes().build()).put(EntityType.PHANTOM, Monster.createMonsterAttributes().build()).put(EntityType.PIG, Pig.createAttributes().build()).put(EntityType.PIGLIN, Piglin.createAttributes().build()).put(EntityType.PIGLIN_BRUTE, PiglinBrute.createAttributes().build()).put(EntityType.PILLAGER, Pillager.createAttributes().build()).put(EntityType.PLAYER, Player.createAttributes().build()).put(EntityType.POLAR_BEAR, PolarBear.createAttributes().build()).put(EntityType.PUFFERFISH, AbstractFish.createAttributes().build()).put(EntityType.RABBIT, Rabbit.createAttributes().build()).put(EntityType.RAVAGER, Ravager.createAttributes().build()).put(EntityType.SALMON, AbstractFish.createAttributes().build()).put(EntityType.SHEEP, Sheep.createAttributes().build()).put(EntityType.SHULKER, Shulker.createAttributes().build()).put(EntityType.SILVERFISH, Silverfish.createAttributes().build()).put(EntityType.SKELETON, AbstractSkeleton.createAttributes().build()).put(EntityType.SKELETON_HORSE, SkeletonHorse.createAttributes().build()).put(EntityType.SLIME, Monster.createMonsterAttributes().build()).put(EntityType.SNIFFER, Sniffer.createAttributes().build()).put(EntityType.SNOW_GOLEM, SnowGolem.createAttributes().build()).put(EntityType.SPIDER, Spider.createAttributes().build()).put(EntityType.SQUID, Squid.createAttributes().build()).put(EntityType.STRAY, AbstractSkeleton.createAttributes().build()).put(EntityType.STRIDER, Strider.createAttributes().build()).put(EntityType.TADPOLE, Tadpole.createAttributes().build()).put(EntityType.TRADER_LLAMA, Llama.createAttributes().build()).put(EntityType.TROPICAL_FISH, AbstractFish.createAttributes().build()).put(EntityType.TURTLE, Turtle.createAttributes().build()).put(EntityType.VEX, Vex.createAttributes().build()).put(EntityType.VILLAGER, Villager.createAttributes().build()).put(EntityType.VINDICATOR, Vindicator.createAttributes().build()).put(EntityType.WARDEN, Warden.createAttributes().build()).put(EntityType.WANDERING_TRADER, Mob.createMobAttributes().build()).put(EntityType.WITCH, Witch.createAttributes().build()).put(EntityType.WITHER, WitherBoss.createAttributes().build()).put(EntityType.WITHER_SKELETON, AbstractSkeleton.createAttributes().build()).put(EntityType.WOLF, Wolf.createAttributes().build()).put(EntityType.ZOGLIN, Zoglin.createAttributes().build()).put(EntityType.ZOMBIE, Zombie.createAttributes().build()).put(EntityType.ZOMBIE_HORSE, ZombieHorse.createAttributes().build()).put(EntityType.ZOMBIE_VILLAGER, Zombie.createAttributes().build()).put(EntityType.ZOMBIFIED_PIGLIN, ZombifiedPiglin.createAttributes().build()).build();
+ private static final Map, AttributeSupplier> SUPPLIERS = ImmutableMap., AttributeSupplier>builder()
-+ .put(EntityType.ALLAY, Allay.createAttributes().build())
-+ .put(EntityType.ARMOR_STAND, LivingEntity.createLivingAttributes().build())
-+ .put(EntityType.AXOLOTL, Axolotl.createAttributes().build())
-+ .put(EntityType.BAT, Bat.createAttributes().build())
-+ .put(EntityType.BEE, Bee.createAttributes().build())
-+ .put(EntityType.BLAZE, Blaze.createAttributes().build())
-+ .put(EntityType.CAT, Cat.createAttributes().build())
-+ .put(EntityType.CAMEL, Camel.createAttributes().build())
-+ .put(EntityType.CAVE_SPIDER, CaveSpider.createCaveSpider().build())
-+ .put(EntityType.CHICKEN, Chicken.createAttributes().build())
-+ .put(EntityType.COD, AbstractFish.createAttributes().build())
-+ .put(EntityType.COW, Cow.createAttributes().build())
-+ .put(EntityType.CREEPER, Creeper.createAttributes().build())
-+ .put(EntityType.DOLPHIN, Dolphin.createAttributes().build())
-+ .put(EntityType.DONKEY, AbstractChestedHorse.createBaseChestedHorseAttributes().build())
-+ .put(EntityType.DROWNED, Zombie.createAttributes().build())
-+ .put(EntityType.ELDER_GUARDIAN, ElderGuardian.createAttributes().build())
-+ .put(EntityType.ENDERMAN, EnderMan.createAttributes().build())
-+ .put(EntityType.ENDERMITE, Endermite.createAttributes().build())
-+ .put(EntityType.ENDER_DRAGON, EnderDragon.createAttributes().build())
-+ .put(EntityType.EVOKER, Evoker.createAttributes().build())
-+ .put(EntityType.FOX, Fox.createAttributes().build())
-+ .put(EntityType.FROG, Frog.createAttributes().build())
-+ .put(EntityType.GHAST, Ghast.createAttributes().build())
-+ .put(EntityType.GIANT, Giant.createAttributes().build())
-+ .put(EntityType.GLOW_SQUID, GlowSquid.createAttributes().build())
-+ .put(EntityType.GOAT, Goat.createAttributes().build())
-+ .put(EntityType.GUARDIAN, Guardian.createAttributes().build())
-+ .put(EntityType.HOGLIN, Hoglin.createAttributes().build())
-+ .put(EntityType.HORSE, AbstractHorse.createBaseHorseAttributes().build())
-+ .put(EntityType.HUSK, Zombie.createAttributes().build())
-+ .put(EntityType.ILLUSIONER, Illusioner.createAttributes().build())
-+ .put(EntityType.IRON_GOLEM, IronGolem.createAttributes().build())
-+ .put(EntityType.LLAMA, Llama.createAttributes().build())
-+ .put(EntityType.MAGMA_CUBE, MagmaCube.createAttributes().build())
-+ .put(EntityType.MOOSHROOM, Cow.createAttributes().build())
-+ .put(EntityType.MULE, AbstractChestedHorse.createBaseChestedHorseAttributes().build())
-+ .put(EntityType.OCELOT, Ocelot.createAttributes().build())
-+ .put(EntityType.PANDA, Panda.createAttributes().build())
-+ .put(EntityType.PARROT, Parrot.createAttributes().build())
-+ .put(EntityType.PHANTOM, net.minecraft.world.entity.monster.Phantom.createAttributes().build()) // Purpur
-+ .put(EntityType.PIG, Pig.createAttributes().build())
-+ .put(EntityType.PIGLIN, Piglin.createAttributes().build())
-+ .put(EntityType.PIGLIN_BRUTE, PiglinBrute.createAttributes().build())
-+ .put(EntityType.PILLAGER, Pillager.createAttributes().build())
-+ .put(EntityType.PLAYER, Player.createAttributes().build())
-+ .put(EntityType.POLAR_BEAR, PolarBear.createAttributes().build())
-+ .put(EntityType.PUFFERFISH, AbstractFish.createAttributes().build())
-+ .put(EntityType.RABBIT, Rabbit.createAttributes().build())
-+ .put(EntityType.RAVAGER, Ravager.createAttributes().build())
-+ .put(EntityType.SALMON, AbstractFish.createAttributes().build())
-+ .put(EntityType.SHEEP, Sheep.createAttributes().build())
-+ .put(EntityType.SHULKER, Shulker.createAttributes().build())
-+ .put(EntityType.SILVERFISH, Silverfish.createAttributes().build())
-+ .put(EntityType.SKELETON, AbstractSkeleton.createAttributes().build())
-+ .put(EntityType.SKELETON_HORSE, SkeletonHorse.createAttributes().build())
-+ .put(EntityType.SLIME, Monster.createMonsterAttributes().build())
-+ .put(EntityType.SNIFFER, Sniffer.createAttributes().build())
-+ .put(EntityType.SNOW_GOLEM, SnowGolem.createAttributes().build())
-+ .put(EntityType.SPIDER, Spider.createAttributes().build())
-+ .put(EntityType.SQUID, Squid.createAttributes().build())
-+ .put(EntityType.STRAY, AbstractSkeleton.createAttributes().build())
-+ .put(EntityType.STRIDER, Strider.createAttributes().build())
-+ .put(EntityType.TADPOLE, Tadpole.createAttributes().build())
-+ .put(EntityType.TRADER_LLAMA, Llama.createAttributes().build())
-+ .put(EntityType.TROPICAL_FISH, AbstractFish.createAttributes().build())
-+ .put(EntityType.TURTLE, Turtle.createAttributes().build())
-+ .put(EntityType.VEX, Vex.createAttributes().build())
-+ .put(EntityType.VILLAGER, Villager.createAttributes().build())
-+ .put(EntityType.VINDICATOR, Vindicator.createAttributes().build())
-+ .put(EntityType.WARDEN, Warden.createAttributes().build())
-+ .put(EntityType.WANDERING_TRADER, Mob.createMobAttributes().build())
-+ .put(EntityType.WITCH, Witch.createAttributes().build())
-+ .put(EntityType.WITHER, WitherBoss.createAttributes().build())
-+ .put(EntityType.WITHER_SKELETON, AbstractSkeleton.createAttributes().build())
-+ .put(EntityType.WOLF, Wolf.createAttributes().build())
-+ .put(EntityType.ZOGLIN, Zoglin.createAttributes().build())
-+ .put(EntityType.ZOMBIE, Zombie.createAttributes().build())
-+ .put(EntityType.ZOMBIE_HORSE, ZombieHorse.createAttributes().build())
-+ .put(EntityType.ZOMBIE_VILLAGER, Zombie.createAttributes().build())
-+ .put(EntityType.ZOMBIFIED_PIGLIN, ZombifiedPiglin.createAttributes().build()).build();
++ .put(EntityType.ALLAY, Allay.createAttributes().build())
++ .put(EntityType.ARMOR_STAND, LivingEntity.createLivingAttributes().build())
++ .put(EntityType.AXOLOTL, Axolotl.createAttributes().build())
++ .put(EntityType.BAT, Bat.createAttributes().build())
++ .put(EntityType.BEE, Bee.createAttributes().build())
++ .put(EntityType.BLAZE, Blaze.createAttributes().build())
++ .put(EntityType.CAT, Cat.createAttributes().build())
++ .put(EntityType.CAMEL, Camel.createAttributes().build())
++ .put(EntityType.CAVE_SPIDER, CaveSpider.createCaveSpider().build())
++ .put(EntityType.CHICKEN, Chicken.createAttributes().build())
++ .put(EntityType.COD, AbstractFish.createAttributes().build())
++ .put(EntityType.COW, Cow.createAttributes().build())
++ .put(EntityType.CREEPER, Creeper.createAttributes().build())
++ .put(EntityType.DOLPHIN, Dolphin.createAttributes().build())
++ .put(EntityType.DONKEY, AbstractChestedHorse.createBaseChestedHorseAttributes().build())
++ .put(EntityType.DROWNED, Zombie.createAttributes().build())
++ .put(EntityType.ELDER_GUARDIAN, ElderGuardian.createAttributes().build())
++ .put(EntityType.ENDERMAN, EnderMan.createAttributes().build())
++ .put(EntityType.ENDERMITE, Endermite.createAttributes().build())
++ .put(EntityType.ENDER_DRAGON, EnderDragon.createAttributes().build())
++ .put(EntityType.EVOKER, Evoker.createAttributes().build())
++ .put(EntityType.BREEZE, Breeze.createAttributes().build())
++ .put(EntityType.FOX, Fox.createAttributes().build())
++ .put(EntityType.FROG, Frog.createAttributes().build())
++ .put(EntityType.GHAST, Ghast.createAttributes().build())
++ .put(EntityType.GIANT, Giant.createAttributes().build())
++ .put(EntityType.GLOW_SQUID, GlowSquid.createAttributes().build())
++ .put(EntityType.GOAT, Goat.createAttributes().build())
++ .put(EntityType.GUARDIAN, Guardian.createAttributes().build())
++ .put(EntityType.HOGLIN, Hoglin.createAttributes().build())
++ .put(EntityType.HORSE, AbstractHorse.createBaseHorseAttributes().build())
++ .put(EntityType.HUSK, Zombie.createAttributes().build())
++ .put(EntityType.ILLUSIONER, Illusioner.createAttributes().build())
++ .put(EntityType.IRON_GOLEM, IronGolem.createAttributes().build())
++ .put(EntityType.LLAMA, Llama.createAttributes().build())
++ .put(EntityType.MAGMA_CUBE, MagmaCube.createAttributes().build())
++ .put(EntityType.MOOSHROOM, Cow.createAttributes().build())
++ .put(EntityType.MULE, AbstractChestedHorse.createBaseChestedHorseAttributes().build())
++ .put(EntityType.OCELOT, Ocelot.createAttributes().build())
++ .put(EntityType.PANDA, Panda.createAttributes().build())
++ .put(EntityType.PARROT, Parrot.createAttributes().build())
++ .put(EntityType.PHANTOM, net.minecraft.world.entity.monster.Phantom.createAttributes().build()) // Purpur
++ .put(EntityType.PIG, Pig.createAttributes().build())
++ .put(EntityType.PIGLIN, Piglin.createAttributes().build())
++ .put(EntityType.PIGLIN_BRUTE, PiglinBrute.createAttributes().build())
++ .put(EntityType.PILLAGER, Pillager.createAttributes().build())
++ .put(EntityType.PLAYER, Player.createAttributes().build())
++ .put(EntityType.POLAR_BEAR, PolarBear.createAttributes().build())
++ .put(EntityType.PUFFERFISH, AbstractFish.createAttributes().build())
++ .put(EntityType.RABBIT, Rabbit.createAttributes().build())
++ .put(EntityType.RAVAGER, Ravager.createAttributes().build())
++ .put(EntityType.SALMON, AbstractFish.createAttributes().build())
++ .put(EntityType.SHEEP, Sheep.createAttributes().build())
++ .put(EntityType.SHULKER, Shulker.createAttributes().build())
++ .put(EntityType.SILVERFISH, Silverfish.createAttributes().build())
++ .put(EntityType.SKELETON, AbstractSkeleton.createAttributes().build())
++ .put(EntityType.SKELETON_HORSE, SkeletonHorse.createAttributes().build())
++ .put(EntityType.SLIME, Monster.createMonsterAttributes().build())
++ .put(EntityType.SNIFFER, Sniffer.createAttributes().build())
++ .put(EntityType.SNOW_GOLEM, SnowGolem.createAttributes().build())
++ .put(EntityType.SPIDER, Spider.createAttributes().build())
++ .put(EntityType.SQUID, Squid.createAttributes().build())
++ .put(EntityType.STRAY, AbstractSkeleton.createAttributes().build())
++ .put(EntityType.STRIDER, Strider.createAttributes().build())
++ .put(EntityType.TADPOLE, Tadpole.createAttributes().build())
++ .put(EntityType.TRADER_LLAMA, Llama.createAttributes().build())
++ .put(EntityType.TROPICAL_FISH, AbstractFish.createAttributes().build())
++ .put(EntityType.TURTLE, Turtle.createAttributes().build())
++ .put(EntityType.VEX, Vex.createAttributes().build())
++ .put(EntityType.VILLAGER, Villager.createAttributes().build())
++ .put(EntityType.VINDICATOR, Vindicator.createAttributes().build())
++ .put(EntityType.WARDEN, Warden.createAttributes().build())
++ .put(EntityType.WANDERING_TRADER, Mob.createMobAttributes().build())
++ .put(EntityType.WITCH, Witch.createAttributes().build())
++ .put(EntityType.WITHER, WitherBoss.createAttributes().build())
++ .put(EntityType.WITHER_SKELETON, AbstractSkeleton.createAttributes().build())
++ .put(EntityType.WOLF, Wolf.createAttributes().build())
++ .put(EntityType.ZOGLIN, Zoglin.createAttributes().build())
++ .put(EntityType.ZOMBIE, Zombie.createAttributes().build())
++ .put(EntityType.ZOMBIE_HORSE, ZombieHorse.createAttributes().build())
++ .put(EntityType.ZOMBIE_VILLAGER, Zombie.createAttributes().build())
++ .put(EntityType.ZOMBIFIED_PIGLIN, ZombifiedPiglin.createAttributes().build()).build();
public static AttributeSupplier getSupplier(EntityType extends LivingEntity> type) {
return SUPPLIERS.get(type);
@@ -5929,7 +5986,7 @@ index a85885ee51df585fa11ae9f8fcd67ff2a71c5a18..d81509e08e70ec5b2f837c9dc66b1254
@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 93bbda61f0eb2dd52573602b1f9cc7b031d1fc5a..63f9e5e2490e5b2fec6f2395077e21e601804ca5 100644
+index 4e2c23ccdf4e4a4d65b291dbe20952bae1838bff..0da884a833f6c707fea512e826658c3bb73f7a77 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 {
@@ -6039,7 +6096,7 @@ index 87fb10096fc9dade33c663234b1cecc34d3d77bb..874c7b29a261b1b5ad6e86ca219ff935
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 509317a26c79f453335df1c19dc4c9ec570046af..8e4d673e4f2d7f50ea5ed13794da08b1d20e6665 100644
+index 5580a396a56c6e0f364a5368985ee99b9e2be0a8..3facfd6eee17cb0b59425494c966e19833660dd2 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 {
@@ -6191,10 +6248,10 @@ index ac5e5676b194a2a99e5cf53eb89c1152cac963b8..872454743f6dedc27519a13566559195
if (baseEntity == null) {
if (this.isCombat && (!targetEntity.canBeSeenAsEnemy() || targetEntity.level().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 2c91fe46355c9a201507de5577f693ed4f5fb974..1eab1393a2636c4a247f25dae317cea60cc7021c 100644
+index 8820905ac733a8915cc1697259b2bef14d97e471..bae3c516b0d13358603576d87a18602a0522a9ff 100644
--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
-@@ -18,6 +18,7 @@ import net.minecraft.world.entity.EntityDimensions;
+@@ -19,6 +19,7 @@ import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.MobSpawnType;
@@ -6202,7 +6259,7 @@ index 2c91fe46355c9a201507de5577f693ed4f5fb974..1eab1393a2636c4a247f25dae317cea6
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attributes;
-@@ -43,12 +44,59 @@ public class Bat extends AmbientCreature {
+@@ -46,12 +47,59 @@ public class Bat extends AmbientCreature {
public Bat(EntityType extends Bat> type, Level world) {
super(type, world);
@@ -6261,8 +6318,8 @@ index 2c91fe46355c9a201507de5577f693ed4f5fb974..1eab1393a2636c4a247f25dae317cea6
+
@Override
public boolean isFlapping() {
- return !this.isResting() && this.tickCount % Bat.TICKS_PER_FLAP == 0;
-@@ -98,7 +146,7 @@ public class Bat extends AmbientCreature {
+ return !this.isResting() && (float) this.tickCount % 10.0F == 0.0F;
+@@ -101,7 +149,7 @@ public class Bat extends AmbientCreature {
protected void pushEntities() {}
public static AttributeSupplier.Builder createAttributes() {
@@ -6271,7 +6328,7 @@ index 2c91fe46355c9a201507de5577f693ed4f5fb974..1eab1393a2636c4a247f25dae317cea6
}
public boolean isResting() {
-@@ -130,6 +178,14 @@ public class Bat extends AmbientCreature {
+@@ -134,6 +182,14 @@ public class Bat extends AmbientCreature {
@Override
protected void customServerAiStep() {
@@ -6286,7 +6343,7 @@ index 2c91fe46355c9a201507de5577f693ed4f5fb974..1eab1393a2636c4a247f25dae317cea6
super.customServerAiStep();
BlockPos blockposition = this.blockPosition();
BlockPos blockposition1 = blockposition.above();
-@@ -208,6 +264,28 @@ public class Bat extends AmbientCreature {
+@@ -212,6 +268,28 @@ public class Bat extends AmbientCreature {
}
}
@@ -6315,7 +6372,7 @@ index 2c91fe46355c9a201507de5577f693ed4f5fb974..1eab1393a2636c4a247f25dae317cea6
@Override
public void readAdditionalSaveData(CompoundTag nbt) {
super.readAdditionalSaveData(nbt);
-@@ -227,7 +305,7 @@ public class Bat extends AmbientCreature {
+@@ -231,7 +309,7 @@ public class Bat extends AmbientCreature {
int i = world.getMaxLocalRawBrightness(pos);
byte b0 = 4;
@@ -6324,7 +6381,7 @@ index 2c91fe46355c9a201507de5577f693ed4f5fb974..1eab1393a2636c4a247f25dae317cea6
b0 = 7;
} else if (random.nextBoolean()) {
return false;
-@@ -241,6 +319,7 @@ public class Bat extends AmbientCreature {
+@@ -245,6 +323,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;
@@ -6389,7 +6446,7 @@ index 2249fc6dd98afb8d52623b5864955fdd3b3fc042..2ccfaab0a02cf5ff9779e250fb79a75a
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 a836bfd2ea8af8098a20fb37ca25a5a613226f67..a434d91b8dfff30cff81df964ea8149caa8cb604 100644
+index 081d1e38b7b1f286e138b0981aaa760e58761215..a64ab2058d4e3439bf6ee418f3192b83c346eb85 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Animal.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java
@@ -42,6 +42,7 @@ public abstract class Animal extends AgeableMob {
@@ -6400,16 +6457,16 @@ index a836bfd2ea8af8098a20fb37ca25a5a613226f67..a434d91b8dfff30cff81df964ea8149c
protected Animal(EntityType extends Animal> type, Level world) {
super(type, world);
-@@ -149,7 +150,7 @@ public abstract class Animal extends AgeableMob {
+@@ -151,7 +152,7 @@ public abstract class Animal extends AgeableMob {
if (this.isFood(itemstack)) {
int i = this.getAge();
- if (!this.level().isClientSide && i == 0 && this.canFallInLove()) {
+ if (!this.level().isClientSide && i == 0 && this.canFallInLove() && (this.level().purpurConfig.animalBreedingCooldownSeconds <= 0 || !this.level().hasBreedingCooldown(player.getUUID(), this.getClass()))) { // Purpur
- final ItemStack breedCopy = itemstack.copy(); // Paper
+ final ItemStack breedCopy = itemstack.copy(); // Paper - Fix EntityBreedEvent copying
this.usePlayerItem(player, hand, itemstack);
- this.setInLove(player, breedCopy); // Paper
-@@ -240,12 +241,20 @@ public abstract class Animal extends AgeableMob {
+ this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
+@@ -242,12 +243,20 @@ public abstract class Animal extends AgeableMob {
AgeableMob entityageable = this.getBreedOffspring(world, other);
if (entityageable != null) {
@@ -6433,7 +6490,7 @@ index a836bfd2ea8af8098a20fb37ca25a5a613226f67..a434d91b8dfff30cff81df964ea8149c
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()) {
-@@ -273,8 +282,10 @@ public abstract class Animal extends AgeableMob {
+@@ -275,8 +284,10 @@ public abstract class Animal extends AgeableMob {
entityplayer.awardStat(Stats.ANIMALS_BRED);
CriteriaTriggers.BRED_ANIMALS.trigger(entityplayer, this, entityanimal, entityageable);
} // Paper
@@ -6447,7 +6504,7 @@ index a836bfd2ea8af8098a20fb37ca25a5a613226f67..a434d91b8dfff30cff81df964ea8149c
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 9a7956befc346e1b58f064213800fd099a052fc6..38a3dcec138d9233a46e5d523bcc6d64bc7fffd0 100644
+index a87a34b0c4c8e5d0cf079025c230b1434c919b54..bdb78cc701543cfe91a6bafd1786fe2ea0bf1ddc 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
@@ -43,6 +43,7 @@ import net.minecraft.world.entity.EntityType;
@@ -6553,7 +6610,7 @@ index 9a7956befc346e1b58f064213800fd099a052fc6..38a3dcec138d9233a46e5d523bcc6d64
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));
-@@ -348,7 +399,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
+@@ -355,7 +406,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
boolean wantsToEnterHive() {
if (this.stayOutOfHiveCountdown <= 0 && !this.beePollinateGoal.isPollinating() && !this.hasStung() && this.getTarget() == null) {
@@ -6562,7 +6619,7 @@ index 9a7956befc346e1b58f064213800fd099a052fc6..38a3dcec138d9233a46e5d523bcc6d64
return flag && !this.isHiveNearFire();
} else {
-@@ -388,6 +439,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
+@@ -395,6 +446,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
this.hurt(this.damageSources().drown(), 1.0F);
}
@@ -6570,7 +6627,7 @@ index 9a7956befc346e1b58f064213800fd099a052fc6..38a3dcec138d9233a46e5d523bcc6d64
if (flag) {
++this.timeSinceSting;
if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, 1, 1200)) == 0) {
-@@ -420,6 +472,26 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
+@@ -427,6 +479,26 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
}
}
@@ -6597,7 +6654,7 @@ index 9a7956befc346e1b58f064213800fd099a052fc6..38a3dcec138d9233a46e5d523bcc6d64
@Override
public int getRemainingPersistentAngerTime() {
return (Integer) this.entityData.get(Bee.DATA_REMAINING_ANGER_TIME);
-@@ -735,6 +807,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
+@@ -742,6 +814,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);
@@ -6605,7 +6662,7 @@ index 9a7956befc346e1b58f064213800fd099a052fc6..38a3dcec138d9233a46e5d523bcc6d64
return true;
} else {
Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60);
-@@ -791,6 +864,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
+@@ -798,6 +871,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
this.pollinating = false;
Bee.this.navigation.stop();
Bee.this.remainingCooldownBeforeLocatingNewFlower = 200;
@@ -6613,7 +6670,7 @@ index 9a7956befc346e1b58f064213800fd099a052fc6..38a3dcec138d9233a46e5d523bcc6d64
}
@Override
-@@ -837,6 +911,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
+@@ -844,6 +918,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
this.setWantedPos();
}
@@ -6621,7 +6678,7 @@ index 9a7956befc346e1b58f064213800fd099a052fc6..38a3dcec138d9233a46e5d523bcc6d64
++this.successfulPollinatingTicks;
if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) {
this.lastSoundPlayedTick = this.successfulPollinatingTicks;
-@@ -881,16 +956,16 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
+@@ -888,16 +963,16 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
}
}
@@ -7058,7 +7115,7 @@ index 3cdd9f379c7e2d46ea47c9ef55b121c93ec0bb4a..6d00b3cd4a9cb0fc8a9e9c27f37429a2
+ // 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 c528cb7c18650863eaf8e2c6c0d9276c02712cc9..1807c7bac6f5012da8130dd41edeb9dd4df32a47 100644
+index e555fd8ca61e1ce7a52ecd475cc3ea11dedcab08..ed2769d8049bb304c1ee3b8e162046855951a624 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Dolphin.java
@@ -82,19 +82,104 @@ public class Dolphin extends WaterAnimal {
@@ -7167,7 +7224,7 @@ index c528cb7c18650863eaf8e2c6c0d9276c02712cc9..1807c7bac6f5012da8130dd41edeb9dd
return super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityNbt);
}
-@@ -164,17 +249,21 @@ public class Dolphin extends WaterAnimal {
+@@ -159,17 +244,21 @@ public class Dolphin extends WaterAnimal {
protected void registerGoals() {
this.goalSelector.addGoal(0, new BreathAirGoal(this));
this.goalSelector.addGoal(0, new TryFindWaterGoal(this));
@@ -7190,7 +7247,7 @@ index c528cb7c18650863eaf8e2c6c0d9276c02712cc9..1807c7bac6f5012da8130dd41edeb9dd
}
public static AttributeSupplier.Builder createAttributes() {
-@@ -225,7 +314,7 @@ public class Dolphin extends WaterAnimal {
+@@ -220,7 +309,7 @@ public class Dolphin extends WaterAnimal {
@Override
protected boolean canRide(Entity entity) {
@@ -7199,7 +7256,7 @@ index c528cb7c18650863eaf8e2c6c0d9276c02712cc9..1807c7bac6f5012da8130dd41edeb9dd
}
@Override
-@@ -260,6 +349,11 @@ public class Dolphin extends WaterAnimal {
+@@ -255,6 +344,11 @@ public class Dolphin extends WaterAnimal {
@Override
public void tick() {
super.tick();
@@ -7211,7 +7268,7 @@ index c528cb7c18650863eaf8e2c6c0d9276c02712cc9..1807c7bac6f5012da8130dd41edeb9dd
if (this.isNoAi()) {
this.setAirSupply(this.getMaxAirSupply());
} else {
-@@ -405,6 +499,7 @@ public class Dolphin extends WaterAnimal {
+@@ -400,6 +494,7 @@ public class Dolphin extends WaterAnimal {
@Override
public boolean canUse() {
@@ -7220,7 +7277,7 @@ index c528cb7c18650863eaf8e2c6c0d9276c02712cc9..1807c7bac6f5012da8130dd41edeb9dd
}
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 9e2af80c6a87f5849710266149cbca8cabfad4f8..075554f28dab5809d0f2d346bad40efc16b38371 100644
+index 3d771b137dc29579614aa4c15d12bd456cdc608a..0f631ba08d255ce5a1e28f51b591a4d9ae1a68fe 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java
@@ -36,6 +36,7 @@ import net.minecraft.util.RandomSource;
@@ -7537,7 +7594,7 @@ index f383928fc5b331ddf128bdcb6a23010d8fe088d3..64aba511e615983988cdb6a0fd45b7d9
}
}
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 e42b0b19019ef74733fd19b08f882cccff920142..6ce116dc3173d17b19c4c03fe9cf494dd022f0d5 100644
+index 7a82ba6e29fde33841c049e8520300aa66608f34..3f00d40125b63a76ed549755d4c9d9a2ff2d4adf 100644
--- a/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
+++ b/src/main/java/net/minecraft/world/entity/animal/MushroomCow.java
@@ -63,6 +63,43 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder drops = this.generateDefaultDrops();
++ List drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getMobLooting(player)); // 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());
}
- // CraftBukkit end
-- this.shear(SoundSource.PLAYERS);
-+ this.shear(SoundSource.PLAYERS, net.minecraft.world.item.enchantment.EnchantmentHelper.getMobLooting(player)); // Purpur
- this.gameEvent(GameEvent.SHEAR, player);
- if (!this.level().isClientSide) {
- itemstack.hurtAndBreak(1, player, (entityhuman1) -> {
-@@ -144,7 +181,7 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder> optional = this.getEffectsFromItemStack(itemstack);
if (optional.isEmpty()) {
@@ -7606,16 +7664,24 @@ index e42b0b19019ef74733fd19b08f882cccff920142..6ce116dc3173d17b19c4c03fe9cf494d
}
if (!player.getAbilities().instabuild) {
-@@ -166,7 +203,7 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder generateDefaultDrops() {
++ public List generateDefaultDrops(int looting) { // Purpur
+ 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;
+@@ -199,7 +236,13 @@ public class MushroomCow extends Cow implements Shearable, VariantHolder type, Level world) {
super(type, world);
@@ -7938,7 +7995,7 @@ index 397264d31992fd43bd57736c25693ae001330b6d..d97ca9d567df224c34eba306b4c9b7df
@Nullable
@Override
public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType spawnReason, @Nullable SpawnGroupData entityData, @Nullable CompoundTag entityNbt) {
-@@ -154,8 +230,11 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
-@@ -307,13 +387,13 @@ public class Parrot extends ShoulderRidingEntity implements VariantHolder {
- entityhuman1.broadcastBreakEvent(hand);
-@@ -272,14 +310,15 @@ public class Sheep extends Animal implements Shearable {
+@@ -254,7 +292,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.getMobLooting(player)); // Purpur
+ org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
+ if (event != null) {
+ if (event.isCancelled()) {
+@@ -281,12 +319,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 void shear(SoundSource shearedSoundCategory) {
-+ public void shear(SoundSource shearedSoundCategory, int looting) { // Purpur
- this.level().playSound((Player) null, (Entity) this, SoundEvents.SHEEP_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
- this.setSheared(true);
- int i = 1 + this.random.nextInt(3);
-+ if (org.purpurmc.purpur.PurpurConfig.allowShearsLooting) i += looting; // Purpur
-
- for (int j = 0; j < i; ++j) {
- this.forceDrops = true; // CraftBukkit
-- ItemEntity entityitem = this.spawnAtLocation((ItemLike) Sheep.ITEM_BY_DYE.get(this.getColor()), 1);
-+ ItemEntity entityitem = this.spawnAtLocation((ItemLike) Sheep.ITEM_BY_DYE.get(this.level().purpurConfig.sheepShearJebRandomColor && hasCustomName() && getCustomName().getString().equals("jeb_") ? DyeColor.random(this.level().random) : this.getColor()), 1); // Purpur
- this.forceDrops = false; // CraftBukkit
-
- if (entityitem != null) {
+- 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 8adcfc8f6772a32b5915e4a07100e8eb735f907a..8b364fe9f3a3d47ae6daa331b8f16941ca17432a 100644
+index b5d6857eaf2bed14adcb5f5e80d91b44eb8b0dcc..c30b00e5637d3def256c93cc227a15ddaf99bc56 100644
--- a/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
+++ b/src/main/java/net/minecraft/world/entity/animal/SnowGolem.java
@@ -49,17 +49,56 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
@@ -8637,20 +8692,21 @@ index 8adcfc8f6772a32b5915e4a07100e8eb735f907a..8b364fe9f3a3d47ae6daa331b8f16941
BlockState iblockdata = Blocks.SNOW.defaultBlockState();
for (int i = 0; i < 4; ++i) {
-@@ -154,10 +196,10 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
+@@ -154,11 +196,11 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
if (itemstack.is(Items.SHEARS) && this.readyForShearing()) {
// CraftBukkit start
- if (!CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) {
-- return InteractionResult.PASS;
-+ return tryRide(player, hand); // Purpur
+ // Paper start - custom shear drops
+- java.util.List drops = this.generateDefaultDrops();
++ java.util.List drops = this.generateDefaultDrops(net.minecraft.world.item.enchantment.EnchantmentHelper.getMobLooting(player)); // 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());
}
- // CraftBukkit end
-- this.shear(SoundSource.PLAYERS);
-+ this.shear(SoundSource.PLAYERS, net.minecraft.world.item.enchantment.EnchantmentHelper.getMobLooting(player)); // Purpur
- this.gameEvent(GameEvent.SHEAR, player);
- if (!this.level().isClientSide) {
- itemstack.hurtAndBreak(1, player, (entityhuman1) -> {
-@@ -166,17 +208,27 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
+@@ -173,19 +215,36 @@ public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackM
}
return InteractionResult.sidedSuccess(this.level().isClientSide);
@@ -8669,17 +8725,27 @@ index 8adcfc8f6772a32b5915e4a07100e8eb735f907a..8b364fe9f3a3d47ae6daa331b8f16941
}
@Override
-- public void shear(SoundSource shearedSoundCategory) {
-+ public void shear(SoundSource shearedSoundCategory, int looting) { // Purpur
- this.level().playSound((Player) null, (Entity) this, SoundEvents.SNOW_GOLEM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
- if (!this.level().isClientSide()) {
- this.setPumpkin(false);
- this.forceDrops = true; // CraftBukkit
-+ if (level().purpurConfig.snowGolemDropsPumpkin) // Purpur
-+ for (int i = 0; i < 1 + (org.purpurmc.purpur.PurpurConfig.allowShearsLooting ? looting : 0); i++) // Purpur
- this.spawnAtLocation(new ItemStack(Items.CARVED_PUMPKIN), 1.7F);
- this.forceDrops = false; // CraftBukkit
- }
+ 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 f60c4cd0543fd5d50fa7e2c1a9e8381227adb540..dd7f2beabf0edad4143ac2365ac04a22edf1f75e 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java
@@ -8842,7 +8908,7 @@ index b05b560b7570e97bc234b75f26233909fcf575b3..87b6f6b10ba6e3d9c6a42298a2019a52
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 490472bb618e9ac07da5883a71dff8920525b1e2..c8f3be5fd869f62472d5a248f9c02700dac0ac69 100644
+index d8056421249c8e75e96a55ec07dce84d2bba9c5c..8f891e9fd9fc0bf4a9c022a3415b371cea9b92fa 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
@@ -86,6 +86,43 @@ public class Turtle extends Animal {
@@ -8897,7 +8963,7 @@ index 490472bb618e9ac07da5883a71dff8920525b1e2..c8f3be5fd869f62472d5a248f9c02700
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));
-@@ -351,13 +389,15 @@ public class Turtle extends Animal {
+@@ -346,13 +384,15 @@ public class Turtle extends Animal {
return new Vector3f(0.0F, dimensions.height + (this.isBaby() ? 0.0F : 0.15625F) * scaleFactor, -0.25F * scaleFactor);
}
@@ -8914,27 +8980,16 @@ index 490472bb618e9ac07da5883a71dff8920525b1e2..c8f3be5fd869f62472d5a248f9c02700
}
private void updateSpeed() {
-@@ -376,8 +416,18 @@ public class Turtle extends Animal {
-
+@@ -372,7 +412,7 @@ public class Turtle extends Animal {
}
-+ // Purpur start
-+ public void purpurTick(Player rider) {
-+ if (turtle.isInWater()) {
-+ waterController.purpurTick(rider);
-+ } else {
-+ super.purpurTick(rider);
-+ }
-+ }
-+ // Purpur end
-+
@Override
- public void tick() {
+ public void vanillaTick() { // Purpur
this.updateSpeed();
if (this.operation == MoveControl.Operation.MOVE_TO && !this.turtle.getNavigation().isDone()) {
double d0 = this.wantedX - this.turtle.getX();
-@@ -393,7 +443,7 @@ public class Turtle extends Animal {
+@@ -388,7 +428,7 @@ public class Turtle extends Animal {
this.turtle.setYRot(this.rotlerp(this.turtle.getYRot(), f, 90.0F));
this.turtle.yBodyRot = this.turtle.getYRot();
@@ -8944,10 +8999,10 @@ index 490472bb618e9ac07da5883a71dff8920525b1e2..c8f3be5fd869f62472d5a248f9c02700
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 cd2ce5bcb8c30e4657cd0e340d80544c7e805905..c8c6fed3f93903bb5c6145930538d415f6f59738 100644
+index 827912174ee08cd19249797d351887149b25c880..5b02848ea9f14060353014cada2d55397609e5ac 100644
--- a/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java
+++ b/src/main/java/net/minecraft/world/entity/animal/WaterAnimal.java
-@@ -82,6 +82,6 @@ public abstract class WaterAnimal extends PathfinderMob {
+@@ -77,6 +77,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
@@ -9323,7 +9378,7 @@ index d241ca4d0295f9fce39c11197bd435cfac7f6e54..c783ce59ea766e6c46a3313628b961f2
private boolean allayConsidersItemEqual(ItemStack stack, ItemStack stack2) {
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 b4793b88688bd568a428aa520e880f0038de45a7..7369290820f726c28c87bc63dba2a74f415bb126 100644
+index 9158c5a507904c46a8fe2fdad9a0b6ba3a9b2460..e4d529825e681bbc656113b1fd44894338e23d21 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
@@ -98,6 +98,43 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder getModelRotationValues() {
return this.modelRotationValues;
-@@ -283,13 +320,13 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder optional = this.getBrain().getMemory(MemoryModuleType.PLAY_DEAD_TICKS);
-@@ -516,14 +553,22 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder {
@@ -9563,7 +9618,7 @@ index c8e3d47b3f2dc919cca8ad397095437f1da6c762..9417ce67cc231d5bfa6813f78ec27196
@Override
protected Brain.Provider brainProvider() {
return Brain.provider(MEMORY_TYPES, SENSOR_TYPES);
-@@ -167,13 +220,13 @@ public class Frog extends Animal implements VariantHolder {
+@@ -162,13 +215,13 @@ public class Frog extends Animal implements VariantHolder {
private int behaviorTick = 0; // Pufferfish
@Override
protected void customServerAiStep() {
@@ -9582,7 +9637,7 @@ index c8e3d47b3f2dc919cca8ad397095437f1da6c762..9417ce67cc231d5bfa6813f78ec27196
super.customServerAiStep();
}
-@@ -354,7 +407,7 @@ public class Frog extends Animal implements VariantHolder {
+@@ -349,7 +402,7 @@ public class Frog extends Animal implements VariantHolder {
return world.getBlockState(pos.below()).is(BlockTags.FROGS_SPAWNABLE_ON) && isBrightEnoughToSpawn(world, pos);
}
@@ -9592,7 +9647,7 @@ index c8e3d47b3f2dc919cca8ad397095437f1da6c762..9417ce67cc231d5bfa6813f78ec27196
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 6ed4ac06c76b8d0d6e8db778cade15dbd1e3e5f5..6b012bea26e8ef0c04571f43da67f6e108188830 100644
+index 6ed4ac06c76b8d0d6e8db778cade15dbd1e3e5f5..14135dac80dec4224715e21cef6556d22e569026 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
@@ -45,13 +45,50 @@ public class Tadpole extends AbstractFish {
@@ -9647,17 +9702,17 @@ index 6ed4ac06c76b8d0d6e8db778cade15dbd1e3e5f5..6b012bea26e8ef0c04571f43da67f6e1
@Override
protected PathNavigation createNavigation(Level world) {
return new WaterBoundPathNavigation(this, world);
-@@ -80,13 +117,13 @@ public class Tadpole extends AbstractFish {
+@@ -80,13 +117,12 @@ public class Tadpole extends AbstractFish {
private int behaviorTick = 0; // Pufferfish
@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.getBrain().tick((ServerLevel) this.level(), this);
- this.level().getProfiler().pop();
- this.level().getProfiler().push("tadpoleActivityUpdate");
++ //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.level().getProfiler().pop(); // Purpur
+ //this.level().getProfiler().push("tadpoleActivityUpdate"); // Purpur
TadpoleAi.updateActivity(this);
@@ -9737,7 +9792,7 @@ index ff12ba2b79cb2e7e0bfd0e3b58ff6cb9e770092b..5d7b20c30bc5e3be8511b300c318d12a
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 a0628b9d74c29d02bfba583edf7ee6f2cde2cff6..bab9e413bd55d48e3e54bee66a6cd5be19a8f415 100644
+index d9539f5275c4cb63910ba79aa522d9569ad35a89..97684d00c79ab2e5712a3d44b7690b1bca15b4a7 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
@@ -149,12 +149,60 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
@@ -9818,7 +9873,7 @@ index a0628b9d74c29d02bfba583edf7ee6f2cde2cff6..bab9e413bd55d48e3e54bee66a6cd5be
}
protected int getInventorySize() {
-@@ -1234,7 +1283,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
+@@ -1231,7 +1280,7 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
entityData = new AgeableMob.AgeableMobGroupData(0.2F);
}
@@ -9924,7 +9979,7 @@ index 5f5dc651d570989ec1294c31a14dcfede466b80a..3b1faa63e46a48e83ea672cf6da444a1
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 9120663b63fc0e365e8edb359892b0db1ee97875..b414572411e5b2b78fd66e860273656d53df9d9d 100644
+index 4863586b1c54192e0228342a0c36561348ebb3fb..0d0f0067d64de6ccf59b1d30ad0e77f530c5af6e 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,9 +75,84 @@ public class Llama extends AbstractChestedHorse implements VariantHolder entitytypes, Level world) {
super(EntityType.ENDER_DRAGON, world);
-+ this.explosionSource = new Explosion(world, this, null, null, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, Explosion.BlockInteraction.DESTROY); // Purpur - moved instantiation from field
- this.fightOrigin = BlockPos.ZERO;
- this.growlTime = 100;
- this.nodes = new Node[24];
-@@ -128,7 +130,37 @@ public class EnderDragon extends Mob implements Enemy {
- this.noPhysics = true;
+@@ -129,6 +130,37 @@ public class EnderDragon extends Mob implements Enemy {
this.noCulling = 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); // CraftBukkit
+ 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
+
+ // Purpur start
+ this.moveControl = new org.purpurmc.purpur.controller.FlyingMoveControllerWASD(this) {
@@ -10671,7 +10721,7 @@ index a288180da1996103eb7dc3bb87b4615f86630bb8..7f3c914358a3d623b07dbb69abc23e13
short0 = 12000;
}
-@@ -1102,6 +1188,7 @@ public class EnderDragon extends Mob implements Enemy {
+@@ -1103,6 +1189,7 @@ public class EnderDragon extends Mob implements Enemy {
@Override
protected boolean canRide(Entity entity) {
@@ -10680,7 +10730,7 @@ index a288180da1996103eb7dc3bb87b4615f86630bb8..7f3c914358a3d623b07dbb69abc23e13
}
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 256598e058db1fd34d36390e45ab9903768343cb..b300ebd589f2ce7393dd435cab5b80f3ec9289ee 100644
+index 1f7f6e5995c00725bf66723c75620ec416e24f87..d75f6032734ec76b498d32c952b15cb015f32674 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
@@ -84,20 +84,59 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
@@ -10866,16 +10916,15 @@ index 256598e058db1fd34d36390e45ab9903768343cb..b300ebd589f2ce7393dd435cab5b80f3
}
@Override
-@@ -141,7 +281,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
+@@ -141,6 +281,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
if (this.hasCustomName()) {
this.bossEvent.setName(this.getDisplayName());
}
--
+ if (nbt.contains("Purpur.Summoner")) setSummoner(nbt.getUUID("Purpur.Summoner")); // Purpur
+
}
- @Override
-@@ -263,6 +403,15 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
+@@ -263,6 +404,16 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
@Override
protected void customServerAiStep() {
@@ -10888,10 +10937,11 @@ index 256598e058db1fd34d36390e45ab9903768343cb..b300ebd589f2ce7393dd435cab5b80f3
+ shootCooldown--;
+ }
+ // Purpur end
++
int i;
if (this.getInvulnerableTicks() > 0) {
-@@ -279,7 +428,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
+@@ -279,7 +430,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
}
// CraftBukkit end
@@ -10900,7 +10950,7 @@ index 256598e058db1fd34d36390e45ab9903768343cb..b300ebd589f2ce7393dd435cab5b80f3
// 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;
-@@ -303,7 +452,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
+@@ -304,7 +455,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
this.setInvulnerableTicks(i);
if (this.tickCount % 10 == 0) {
@@ -10909,7 +10959,7 @@ index 256598e058db1fd34d36390e45ab9903768343cb..b300ebd589f2ce7393dd435cab5b80f3
}
} else {
-@@ -363,7 +512,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
+@@ -364,7 +515,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
if (this.destroyBlocksTick > 0) {
--this.destroyBlocksTick;
@@ -10918,7 +10968,7 @@ index 256598e058db1fd34d36390e45ab9903768343cb..b300ebd589f2ce7393dd435cab5b80f3
i = Mth.floor(this.getY());
j = Mth.floor(this.getX());
int i1 = Mth.floor(this.getZ());
-@@ -396,8 +545,10 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
+@@ -397,8 +548,10 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
}
}
@@ -10931,7 +10981,7 @@ index 256598e058db1fd34d36390e45ab9903768343cb..b300ebd589f2ce7393dd435cab5b80f3
}
this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth());
-@@ -583,11 +734,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
+@@ -584,11 +737,11 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
}
public int getAlternativeTarget(int headIndex) {
@@ -10945,7 +10995,7 @@ index 256598e058db1fd34d36390e45ab9903768343cb..b300ebd589f2ce7393dd435cab5b80f3
}
@Override
-@@ -602,6 +753,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
+@@ -603,6 +756,7 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
@Override
protected boolean canRide(Entity entity) {
@@ -10954,7 +11004,7 @@ index 256598e058db1fd34d36390e45ab9903768343cb..b300ebd589f2ce7393dd435cab5b80f3
}
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 523f14916073fb137578da777a23ba8265fd8af6..2b9b0acd20d2bf16d08ed89ba625dfb15c630988 100644
+index a9c1f99ba2461333bd154ac16e812031f234f7a6..526943db39a61c6b281d44a1159ebbd8452b5798 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -99,10 +99,12 @@ public class ArmorStand extends LivingEntity {
@@ -10978,7 +11028,7 @@ index 523f14916073fb137578da777a23ba8265fd8af6..2b9b0acd20d2bf16d08ed89ba625dfb1
}
public ArmorStand(Level world, double x, double y, double z) {
-@@ -619,7 +622,7 @@ public class ArmorStand extends LivingEntity {
+@@ -606,7 +609,7 @@ public class ArmorStand extends LivingEntity {
private org.bukkit.event.entity.EntityDeathEvent brokenByPlayer(DamageSource damageSource) { // Paper
ItemStack itemstack = new ItemStack(Items.ARMOR_STAND);
@@ -10987,7 +11037,7 @@ index 523f14916073fb137578da777a23ba8265fd8af6..2b9b0acd20d2bf16d08ed89ba625dfb1
itemstack.setHoverName(this.getCustomName());
}
-@@ -690,6 +693,7 @@ public class ArmorStand extends LivingEntity {
+@@ -677,6 +680,7 @@ public class ArmorStand extends LivingEntity {
@Override
public void tick() {
@@ -10995,16 +11045,16 @@ index 523f14916073fb137578da777a23ba8265fd8af6..2b9b0acd20d2bf16d08ed89ba625dfb1
// Paper start
if (!this.canTick) {
if (this.noTickPoseDirty) {
-@@ -1024,4 +1028,18 @@ public class ArmorStand extends LivingEntity {
+@@ -1004,4 +1008,18 @@ public class ArmorStand extends LivingEntity {
+ }
}
// Paper end
- // Paper end
+
+ // Purpur start
+ @Override
+ public void updateInWaterStateAndDoWaterCurrentPushing() {
+ if (this.level().purpurConfig.armorstandWaterMovement &&
-+ (this.level().purpurConfig.armorstandWaterFence || !(level().getBlockState(blockPosition().below()).getBlock() instanceof net.minecraft.world.level.block.FenceBlock)))
++ (this.level().purpurConfig.armorstandWaterFence || !(level().getBlockState(blockPosition().below()).getBlock() instanceof net.minecraft.world.level.block.FenceBlock)))
+ super.updateInWaterStateAndDoWaterCurrentPushing();
+ }
+
@@ -11015,10 +11065,10 @@ index 523f14916073fb137578da777a23ba8265fd8af6..2b9b0acd20d2bf16d08ed89ba625dfb1
+ // 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 759ecd79534a7706f7d4a63eb9dacbefcfe54674..182faba889dc15a3500c5919cad8a5483a53033a 100644
+index c5ec729470aa2b17c6963605cd10b8f53bae5e59..fa94ffe6edf023dc16507d886e9d54ea58af0eec 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
-@@ -273,7 +273,13 @@ public class ItemFrame extends HangingEntity {
+@@ -268,7 +268,13 @@ public class ItemFrame extends HangingEntity {
}
if (alwaysDrop) {
@@ -11062,7 +11112,7 @@ index d9016807bc21c38a5c38170e1335c79b39355bcb..62cdc36a21c0203ed98d2946a1efdf54
}
diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
-index e6f75a9cac46c8e3ddba664a9d5b27b665a94cb4..958e7684440fcc209fe33e882bf259d92a6814b1 100644
+index 45c07733f03b5c11f6d8e820f65dc950c70d9a67..8e9ab1335626493b8d74f71f643565c0e65af94c 100644
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -133,7 +133,7 @@ public class FallingBlockEntity extends Entity {
@@ -11084,13 +11134,13 @@ index e6f75a9cac46c8e3ddba664a9d5b27b665a94cb4..958e7684440fcc209fe33e882bf259d9
}
// Paper end - fix sand duping
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
-index eb0351aa12eebcefab1d1d14641fc3c60cbbcab8..4f01fede54a3150798812d6e5116631bf897a29b 100644
+index c34c698d389da29c9cfaa56cb8023e30416a14ba..7844ee584b917485ce5e490ad040c2c1d732eb1d 100644
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
-@@ -56,6 +56,12 @@ public class ItemEntity extends Entity implements TraceableEntity {
+@@ -58,6 +58,12 @@ public class ItemEntity extends Entity implements TraceableEntity {
public boolean canMobPickup = true; // Paper
private int despawnRate = -1; // Paper
- public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper
+ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
+ // Purpur start
+ public boolean immuneToCactus = false;
+ public boolean immuneToExplosion = false;
@@ -11100,7 +11150,7 @@ index eb0351aa12eebcefab1d1d14641fc3c60cbbcab8..4f01fede54a3150798812d6e5116631b
public ItemEntity(EntityType extends ItemEntity> type, Level world) {
super(type, world);
-@@ -346,7 +352,16 @@ public class ItemEntity extends Entity implements TraceableEntity {
+@@ -364,7 +370,16 @@ public class ItemEntity extends Entity implements TraceableEntity {
@Override
public boolean hurt(DamageSource source, float amount) {
@@ -11118,7 +11168,7 @@ index eb0351aa12eebcefab1d1d14641fc3c60cbbcab8..4f01fede54a3150798812d6e5116631b
return false;
} else if (!this.getItem().isEmpty() && this.getItem().is(Items.NETHER_STAR) && source.is(DamageTypeTags.IS_EXPLOSION)) {
return false;
-@@ -548,6 +563,12 @@ public class ItemEntity extends Entity implements TraceableEntity {
+@@ -567,6 +582,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
@@ -11132,10 +11182,10 @@ index eb0351aa12eebcefab1d1d14641fc3c60cbbcab8..4f01fede54a3150798812d6e5116631b
@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 4ce3e69970dd9eb251d0538a2d233ca30e9e5e47..afc65b8bb7e7f7f70a25f2d869412ed325b658da 100644
+index c3e47426382296d650fa00ce0bc1a82bf23c7877..dfc3e9d2611ce418ac6f6cc5a23bb74415007713 100644
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
-@@ -175,4 +175,29 @@ public class PrimedTnt extends Entity implements TraceableEntity {
+@@ -207,4 +207,29 @@ public class PrimedTnt extends Entity implements TraceableEntity {
return !level().paperConfig().fixes.preventTntFromMovingInWater && super.isPushedByFluid();
}
// Paper end
@@ -11166,7 +11216,7 @@ index 4ce3e69970dd9eb251d0538a2d233ca30e9e5e47..afc65b8bb7e7f7f70a25f2d869412ed3
+ // 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 b319021b22c5dceba6199ed27814b2dcf47b8d50..28eb98d383d6846a25c29f8cd8ff211c360a56dc 100644
+index a383c0c8b5c89ef1eef7d18edc3a09f749fdd310..68f45498405f5fd9a6f5525b9a59518a8b506aa8 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
@@ -11420,7 +11470,7 @@ index 70d25bb45ad603095a1f5812cc396dfc5f16a1e1..c9bd400473166999479f5eef1edad529
public boolean doHurtTarget(Entity target) {
if (super.doHurtTarget(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 fd1b5a1beea7594fa65decfdcccfa15781fc005b..304ea7fdcd410a7c88ec61143364e14de8db0b0c 100644
+index 52eb3f6a73fa99d12d5fc75bab03e47a605c653a..64f6b5f44db4fd90e789032e3833da60cfcfbef1 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
@@ -59,21 +59,99 @@ public class Creeper extends Monster implements PowerableMob {
@@ -11599,7 +11649,7 @@ index fd1b5a1beea7594fa65decfdcccfa15781fc005b..304ea7fdcd410a7c88ec61143364e14d
}
// Paper end
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 991d728db2a3b64316fc2102cf3aee470327a62e..63a1cf5604c14025171d7be7434e2d6b64c98107 100644
+index 485d14d71fb26e6e0d00a43da040bf63d696b66a..034bb2d1292dde6276885c3ea71d886c3894311c 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java
@@ -29,6 +29,7 @@ import net.minecraft.world.entity.ai.goal.MoveToBlockGoal;
@@ -11779,7 +11829,7 @@ index efc1d49c5bfea7d1674b8a9de2c8b617657eda0f..df8d1b34078031001c50325b8cf5bfa9
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 0d51f435f18f3f9d59a3241a0b7fa1c4af841b72..4c9ffa8e1ab97d8156ead0ed189c769ffd9b4aae 100644
+index ebbd0031da656c4b12debbf76a347da2865d50d1..a5fcc85334474b29c3575bccbaeceaadc06eea5c 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
@@ -95,12 +95,40 @@ public class EnderMan extends Monster implements NeutralMob {
@@ -12006,10 +12056,10 @@ index 66b6c55f72aec7e4e9dfa5417a46ba68dbb16a83..20ca96baf8f73fd5835422c6551f515a
@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 7f0fbca7638bf89465bafed9d106813b86f0149b..4095f03ccd1712335baffe858603618100aed99c 100644
+index e67cb165a0d706d38e4970fb3d63f59a29808a76..daee6c4c0c2d43b65cdfd691bbbdc72465702dfe 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Evoker.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Evoker.java
-@@ -50,10 +50,43 @@ public class Evoker extends SpellcasterIllager {
+@@ -51,10 +51,43 @@ public class Evoker extends SpellcasterIllager {
this.xpReward = 10;
}
@@ -12053,7 +12103,7 @@ index 7f0fbca7638bf89465bafed9d106813b86f0149b..4095f03ccd1712335baffe8586036181
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());
-@@ -62,6 +95,7 @@ public class Evoker extends SpellcasterIllager {
+@@ -63,6 +96,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));
@@ -12061,7 +12111,7 @@ index 7f0fbca7638bf89465bafed9d106813b86f0149b..4095f03ccd1712335baffe8586036181
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));
-@@ -321,7 +355,7 @@ public class Evoker extends SpellcasterIllager {
+@@ -327,7 +361,7 @@ public class Evoker extends SpellcasterIllager {
return false;
} else if (Evoker.this.tickCount < this.nextAttackTickCount) {
return false;
@@ -12308,7 +12358,7 @@ index 793c72bb7b86e404926085629121d6cad19a2740..d13eed85d5399cd6991b3ad90f05a580
}
}
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 45300f79cba6133d2a2eca706eae03ee3cd973c3..54113957c9cfab2ad3be25dbc05b8c29d1a064d5 100644
+index fd41ef66e2e12ec3a888bb376ef4363343914fcd..01c558673f0bb5034bca9df0e473375e7b7e724e 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Guardian.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Guardian.java
@@ -70,15 +70,51 @@ public class Guardian extends Monster {
@@ -12371,7 +12421,7 @@ index 45300f79cba6133d2a2eca706eae03ee3cd973c3..54113957c9cfab2ad3be25dbc05b8c29
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 10, true, false, new Guardian.GuardianAttackSelector(this)));
}
-@@ -352,7 +389,7 @@ public class Guardian extends Monster {
+@@ -347,7 +384,7 @@ public class Guardian extends Monster {
@Override
public void travel(Vec3 movementInput) {
if (this.isControlledByLocalInstance() && this.isInWater()) {
@@ -12380,7 +12430,7 @@ index 45300f79cba6133d2a2eca706eae03ee3cd973c3..54113957c9cfab2ad3be25dbc05b8c29
this.move(MoverType.SELF, this.getDeltaMovement());
this.setDeltaMovement(this.getDeltaMovement().scale(0.9D));
if (!this.isMoving() && this.getTarget() == null) {
-@@ -369,7 +406,7 @@ public class Guardian extends Monster {
+@@ -364,7 +401,7 @@ public class Guardian extends Monster {
return new Vector3f(0.0F, dimensions.height + 0.125F * scaleFactor, 0.0F);
}
@@ -12389,7 +12439,7 @@ index 45300f79cba6133d2a2eca706eae03ee3cd973c3..54113957c9cfab2ad3be25dbc05b8c29
private final Guardian guardian;
-@@ -378,8 +415,17 @@ public class Guardian extends Monster {
+@@ -373,8 +410,17 @@ public class Guardian extends Monster {
this.guardian = guardian;
}
@@ -12408,7 +12458,7 @@ index 45300f79cba6133d2a2eca706eae03ee3cd973c3..54113957c9cfab2ad3be25dbc05b8c29
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();
-@@ -390,7 +436,7 @@ public class Guardian extends Monster {
+@@ -385,7 +431,7 @@ public class Guardian extends Monster {
this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), f, 90.0F));
this.guardian.yBodyRot = this.guardian.getYRot();
@@ -12418,7 +12468,7 @@ index 45300f79cba6133d2a2eca706eae03ee3cd973c3..54113957c9cfab2ad3be25dbc05b8c29
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 8ef1e325d722ca36fc0fc36f1e5287d7002b9fb2..473f28e86a0e5157264b83d9c3c4a18c72216da3 100644
+index 72b8290bebe8ed9bc3c464b30cfe5d2d664310f5..06a5106a94a44c1d21537410d801cdd945503d69 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Husk.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Husk.java
@@ -22,6 +22,59 @@ public class Husk extends Zombie {
@@ -12626,7 +12676,7 @@ index 2858ea5562d06c11e5c7337a2b123f9be7a3f62e..1ad97267394d3717b1871336193cdc91
@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 e4218acaaf7d3aef0fb31f5597fb1af32aa2c8b5..01977550309451cda795583ba4122143b140b9b7 100644
+index 127a344f35e194fc7b1a0783c75291fab929fe19..d90d8539815d92143c994108efdfcc18bcb3b158 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Monster.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Monster.java
@@ -89,6 +89,14 @@ public abstract class Monster extends PathfinderMob implements Enemy {
@@ -13203,7 +13253,7 @@ index 0c11d9bef8f0129c541e30ad057612e881703b24..c9c21c87e3bd1c404fbef6768761bcb5
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 8cb6f2d32c4b7a62ec1bdfeb8b661a1387cafe4b..81caa18fca658f70846ba437ac02906f5e9653b9 100644
+index b73dac8f68041f8a2e0752d70cc9d08b5cfd1cde..8a52c1ad5e2872e4b484eebc834fa42fd1930481 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Shulker.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Shulker.java
@@ -22,6 +22,8 @@ import net.minecraft.tags.DamageTypeTags;
@@ -13311,7 +13361,7 @@ index 8cb6f2d32c4b7a62ec1bdfeb8b661a1387cafe4b..81caa18fca658f70846ba437ac02906f
if (entityshulker != null) {
entityshulker.setVariant(this.getVariant());
-@@ -591,7 +651,7 @@ public class Shulker extends AbstractGolem implements VariantHolder getVariant() {
@@ -13320,7 +13370,7 @@ index 8cb6f2d32c4b7a62ec1bdfeb8b661a1387cafe4b..81caa18fca658f70846ba437ac02906f
}
@Nullable
-@@ -601,7 +661,7 @@ public class Shulker extends AbstractGolem implements VariantHolder(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 118b636a44e4b062e812e433f603b039276337da..a95e983032b3d3d125a39a46700b7db9dc69f307 100644
+index 8185cef34b9300561a00f9e62b98f1aa818a3f5a..e01c91385935b71bb9aa7259b95cb963140e8c94 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Stray.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Stray.java
@@ -21,6 +21,38 @@ public class Stray extends AbstractSkeleton {
@@ -13904,7 +13954,7 @@ index 61162ecd43dc5e6f7898daecdec49f444e6d869b..2f49b528601a1feb7246fe7a9b83ce82
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 90e577b1a89b02c38daff2845a63dafe5ed929e1..be1c9a7e2bafb33dcb954ba9fd427c033bb7542f 100644
+index 30ea3f64234fd1fda8dada3c7fb12be0730322a8..44fe951f0297c0efa5169c8972c05eaf90d49edf 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Vex.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java
@@ -63,6 +63,65 @@ public class Vex extends Monster implements TraceableEntity {
@@ -14003,7 +14053,7 @@ index 90e577b1a89b02c38daff2845a63dafe5ed929e1..be1c9a7e2bafb33dcb954ba9fd427c03
}
@Override
-@@ -240,14 +301,14 @@ public class Vex extends Monster implements TraceableEntity {
+@@ -251,14 +312,14 @@ public class Vex extends Monster implements TraceableEntity {
return new Vector3f(0.0F, dimensions.height - 0.0625F * scaleFactor, 0.0F);
}
@@ -14020,7 +14070,7 @@ index 90e577b1a89b02c38daff2845a63dafe5ed929e1..be1c9a7e2bafb33dcb954ba9fd427c03
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();
-@@ -256,7 +317,7 @@ public class Vex extends Monster implements TraceableEntity {
+@@ -267,7 +328,7 @@ public class Vex extends Monster implements TraceableEntity {
this.operation = MoveControl.Operation.WAIT;
Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5D));
} else {
@@ -14260,7 +14310,7 @@ index b79c86272f12c4b1173ea494cbe09e1ecdc23533..1d36459ee10da702d65b4a6d139a05fd
}
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 5fdad1600cc7a7c22d1d9a58b6b2dda605521b97..1be1bfb831198b68d8e20bf5ff922edff8832114 100644
+index 753defa8f8b48d004a2a53b2fc322fd9c083d95e..f6dd5fd56926215830ccebbd46098d4bc08e17e4 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -96,22 +96,69 @@ public class Zombie extends Monster {
@@ -14471,7 +14521,7 @@ index 5fdad1600cc7a7c22d1d9a58b6b2dda605521b97..1be1bfb831198b68d8e20bf5ff922edf
@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 94396ad1a3c280787d36c6c18256d10340ace488..4d744e00bbaf25d1bad3782a6415e9bf5958e536 100644
+index 7de9d012e7416eaa0189b513a0972c846e93c4b6..712f77d4ddad04c7cd89d51c6d0c79c2f3ab9347 100644
--- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
@@ -82,6 +82,58 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
@@ -14634,6 +14684,33 @@ index 1afe8a8694c1fd0bf43ce3c0c36a83fda9aec141..df8c7a45eb49a8c667030eb67d6d49dc
}
@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 0b8992a9aea781470ab3b1880cf041972a20089d..94431d5c789a9f558c16c0d1fc8f1f7463421ec6 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
+@@ -59,7 +59,7 @@ public class Breeze extends Monster {
+
+ @Override
+ public Brain getBrain() {
+- return super.getBrain();
++ return (Brain) super.getBrain(); // Purpur - decompile error
+ }
+
+ @Override
+@@ -200,10 +200,10 @@ 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().pop();
++ // this.level().getProfiler().popPush("breezeActivityUpdate"); // Purpur
++ // this.level().getProfiler().pop(); // Purpur
+ super.customServerAiStep();
+ }
+
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 e703320717ff620a19ff76d1c10066117c9895d5..9d6c4f13c4a444c6c815c6c4f2114142f166b9bb 100644
--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
@@ -14868,10 +14945,10 @@ index d02ee11066fc4f07ccb110b09b86d895ff90d4f2..856e6e02c9424a6c06e310262cb4f5bd
PiglinBruteAi.maybePlayActivitySound(this);
super.customServerAiStep();
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 5e43912708f9074dee1bb351efa737a7e6796fc3..5e66c2bd3807619cadee5b7081d93d21886e2806 100644
+index 58a7e61e02b7d72326ed4d57ee514adb63b3873c..22263f219ce9e9f014abb76c43297c528acb36eb 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
-@@ -122,8 +122,32 @@ public class Warden extends Monster implements VibrationSystem {
+@@ -123,8 +123,32 @@ public class Warden extends Monster implements VibrationSystem {
this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F);
this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, 0.0F);
this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, 0.0F);
@@ -14904,7 +14981,7 @@ index 5e43912708f9074dee1bb351efa737a7e6796fc3..5e66c2bd3807619cadee5b7081d93d21
@Override
public Packet getAddEntityPacket() {
return new ClientboundAddEntityPacket(this, this.hasPose(Pose.EMERGING) ? 1 : 0);
-@@ -277,10 +301,10 @@ public class Warden extends Monster implements VibrationSystem {
+@@ -278,10 +302,10 @@ public class Warden extends Monster implements VibrationSystem {
protected void customServerAiStep() {
ServerLevel worldserver = (ServerLevel) this.level();
@@ -14917,7 +14994,7 @@ index 5e43912708f9074dee1bb351efa737a7e6796fc3..5e66c2bd3807619cadee5b7081d93d21
super.customServerAiStep();
if ((this.tickCount + this.getId()) % 120 == 0) {
Warden.applyDarknessAround(worldserver, this.position(), this, 20);
-@@ -397,19 +421,16 @@ public class Warden extends Monster implements VibrationSystem {
+@@ -398,19 +422,16 @@ public class Warden extends Monster implements VibrationSystem {
@Contract("null->false")
public boolean canTargetEntity(@Nullable Entity entity) {
@@ -14999,7 +15076,7 @@ index 5f407535298a31a34cfe114dd863fd6a9b977707..29c7e33fe961020e5a0007287fe9b663
}
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 2460768aaa7b8e6d183c03c1f0f2ccd6cb61a16f..02df0bf09f2ef91e4dafbdcea590b4634b2abf08 100644
+index 1e6d61673b0e3252129c04edcfa1d7d436e8ecbe..27ebfda79d9c4463f157b99c2c56e256839b3a31 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -141,6 +141,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -15111,7 +15188,7 @@ index 2460768aaa7b8e6d183c03c1f0f2ccd6cb61a16f..02df0bf09f2ef91e4dafbdcea590b463
}
brain.addActivity(Activity.CORE, VillagerGoalPackages.getCorePackage(villagerprofession, 0.5F));
-@@ -254,15 +340,22 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -254,15 +340,21 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
// Paper start
this.customServerAiStep(false);
}
@@ -15128,20 +15205,19 @@ index 2460768aaa7b8e6d183c03c1f0f2ccd6cb61a16f..02df0bf09f2ef91e4dafbdcea590b463
+ // treat as inactive if lobotomized
+ inactive = inactive || checkLobotomized();
+ } else {
-+ // clean up state for API
+ this.isLobotomized = false;
}
- // Pufferfish end
- this.level().getProfiler().pop();
-+ if (!inactive && (getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Purpur - only use brain if no rider
++ 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();
++ } else if (this.isLobotomized && shouldRestock()) restock();
+ // Purpur end
+ //this.level().getProfiler().pop(); // Purpur
if (this.assignProfessionWhenSpawned) {
this.assignProfessionWhenSpawned = false;
}
-@@ -318,7 +411,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -318,7 +410,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();
@@ -15150,7 +15226,7 @@ index 2460768aaa7b8e6d183c03c1f0f2ccd6cb61a16f..02df0bf09f2ef91e4dafbdcea590b463
} else {
boolean flag = this.getOffers().isEmpty();
-@@ -331,9 +424,10 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -331,9 +423,10 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
}
if (flag) {
@@ -15163,7 +15239,7 @@ index 2460768aaa7b8e6d183c03c1f0f2ccd6cb61a16f..02df0bf09f2ef91e4dafbdcea590b463
this.startTrading(player);
}
-@@ -502,7 +596,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -502,7 +595,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
while (iterator.hasNext()) {
MerchantOffer merchantrecipe = (MerchantOffer) iterator.next();
@@ -15172,7 +15248,7 @@ index 2460768aaa7b8e6d183c03c1f0f2ccd6cb61a16f..02df0bf09f2ef91e4dafbdcea590b463
}
}
-@@ -752,7 +846,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -752,7 +845,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@Override
public boolean canBreed() {
@@ -15181,7 +15257,7 @@ index 2460768aaa7b8e6d183c03c1f0f2ccd6cb61a16f..02df0bf09f2ef91e4dafbdcea590b463
}
private boolean hungry() {
-@@ -945,6 +1039,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -945,6 +1038,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
public boolean hasFarmSeeds() {
return this.getInventory().hasAnyMatching((itemstack) -> {
@@ -15193,7 +15269,7 @@ index 2460768aaa7b8e6d183c03c1f0f2ccd6cb61a16f..02df0bf09f2ef91e4dafbdcea590b463
return itemstack.is(ItemTags.VILLAGER_PLANTABLE_SEEDS);
});
}
-@@ -1002,6 +1101,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -1002,6 +1100,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
}
public void spawnGolemIfNeeded(ServerLevel world, long time, int requiredCount) {
@@ -15201,7 +15277,7 @@ index 2460768aaa7b8e6d183c03c1f0f2ccd6cb61a16f..02df0bf09f2ef91e4dafbdcea590b463
if (this.wantsToSpawnGolem(time)) {
AABB axisalignedbb = this.getBoundingBox().inflate(10.0D, 10.0D, 10.0D);
List list = world.getEntitiesOfClass(Villager.class, axisalignedbb);
-@@ -1066,6 +1166,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -1066,6 +1165,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@Override
public void startSleeping(BlockPos pos) {
@@ -15329,12 +15405,12 @@ index 8385eb1d60f377da94e3178ab506feefb43563fd..a5443f92786427c42092aec8350e7ab3
if (NaturalSpawner.isSpawnPositionOk(SpawnPlacements.Type.ON_GROUND, 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 481c3e321cfc0f20bb1c4c6942b8bdbd23c06339..724329ded5d72eb230db392972d30e7ba4e69ceb 100644
+index 2668c3b6f752d5d8bc45f4e6e52c20cc6a36a957..9ef9d005036ecbe271b08fa5e4465f328da19815 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
-@@ -188,17 +188,40 @@ public abstract class Player extends LivingEntity {
+@@ -183,17 +183,40 @@ public abstract class Player extends LivingEntity {
public boolean affectsSpawning = true;
- public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET;
+ public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage
// Paper end
+ public int sixRowEnderchestSlotCount = -1; // Purpur
+ public int burpDelay = 0; // Purpur
@@ -15373,7 +15449,7 @@ index 481c3e321cfc0f20bb1c4c6942b8bdbd23c06339..724329ded5d72eb230db392972d30e7b
public Player(Level world, BlockPos pos, float yaw, GameProfile gameProfile) {
super(EntityType.PLAYER, world);
this.lastItemInMainHand = ItemStack.EMPTY;
-@@ -243,6 +266,12 @@ public abstract class Player extends LivingEntity {
+@@ -238,6 +261,12 @@ public abstract class Player extends LivingEntity {
@Override
public void tick() {
@@ -15407,12 +15483,12 @@ index 481c3e321cfc0f20bb1c4c6942b8bdbd23c06339..724329ded5d72eb230db392972d30e7b
@Override
public int getPortalWaitTime() {
-- return this.abilities.invulnerable ? 1 : 80;
-+ return canPortalInstant ? 1 : this.abilities.invulnerable ? this.level().purpurConfig.playerCreativePortalWaitTime : this.level().purpurConfig.playerPortalWaitTime; // Purpur
+- return Math.max(1, this.level().getGameRules().getInt(this.abilities.invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY));
++ return Math.max(1, canPortalInstant ? 1 : this.level().getGameRules().getInt(this.abilities.invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY));
}
@Override
-@@ -597,7 +636,7 @@ public abstract class Player extends LivingEntity {
+@@ -592,7 +631,7 @@ public abstract class Player extends LivingEntity {
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
@@ -15421,7 +15497,7 @@ index 481c3e321cfc0f20bb1c4c6942b8bdbd23c06339..724329ded5d72eb230db392972d30e7b
list1.add(entity);
} else if (!entity.isRemoved()) {
this.touch(entity);
-@@ -1288,7 +1327,7 @@ public abstract class Player extends LivingEntity {
+@@ -1283,7 +1322,7 @@ public abstract class Player extends LivingEntity {
flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper
flag2 = flag2 && !this.isSprinting();
if (flag2) {
@@ -15430,7 +15506,7 @@ index 481c3e321cfc0f20bb1c4c6942b8bdbd23c06339..724329ded5d72eb230db392972d30e7b
}
f += f1;
-@@ -1983,9 +2022,19 @@ public abstract class Player extends LivingEntity {
+@@ -1914,9 +1953,19 @@ public abstract class Player extends LivingEntity {
@Override
public int getExperienceReward() {
if (!this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && !this.isSpectator()) {
@@ -15453,7 +15529,7 @@ index 481c3e321cfc0f20bb1c4c6942b8bdbd23c06339..724329ded5d72eb230db392972d30e7b
} else {
return 0;
}
-@@ -2061,6 +2110,11 @@ public abstract class Player extends LivingEntity {
+@@ -1992,6 +2041,11 @@ public abstract class Player extends LivingEntity {
return this.inventory.armor;
}
@@ -15465,7 +15541,7 @@ index 481c3e321cfc0f20bb1c4c6942b8bdbd23c06339..724329ded5d72eb230db392972d30e7b
public boolean setEntityOnShoulder(CompoundTag entityNbt) {
if (!this.isPassenger() && this.onGround() && !this.isInWater() && !this.isInPowderSnow) {
if (this.getShoulderEntityLeft().isEmpty()) {
-@@ -2341,7 +2395,7 @@ public abstract class Player extends LivingEntity {
+@@ -2272,7 +2326,7 @@ public abstract class Player extends LivingEntity {
public ItemStack eat(Level world, ItemStack stack) {
this.getFoodData().eat(stack.getItem(), stack);
this.awardStat(Stats.ITEM_USED.get(stack.getItem()));
@@ -15474,19 +15550,27 @@ index 481c3e321cfc0f20bb1c4c6942b8bdbd23c06339..724329ded5d72eb230db392972d30e7b
if (this instanceof ServerPlayer) {
CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) this, stack);
}
+@@ -2366,6 +2420,7 @@ public abstract class Player extends LivingEntity {
+ }
+
+ public static boolean isValidUsername(String name) {
++ if (true) return org.purpurmc.purpur.PurpurConfig.usernameValidCharactersPattern.matcher(name).matches(); // Purpur
+ // Paper start
+ if (name == null || name.isEmpty() || name.length() > 16) {
+ return false;
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 6c176933967f6ee98da3026f16a10efe4c3842fe..aa5e17e497bbc1d45b361de73cc7a181773dbd8b 100644
+index 505fe5496044f090ce6f7d541b8c3e13c567b16d..1c51ad780cae3c0c2a917f229ac370b75fe62c24 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
-@@ -72,6 +72,7 @@ public abstract class AbstractArrow extends Projectile {
- private IntOpenHashSet piercingIgnoreEntityIds;
+@@ -74,6 +74,7 @@ public abstract class AbstractArrow extends Projectile {
@Nullable
private List piercedAndKilledEntities;
+ public ItemStack pickupItemStack;
+ public int lootingLevel; // Purpur
// Spigot Start
@Override
-@@ -312,7 +313,7 @@ public abstract class AbstractArrow extends Projectile {
+@@ -319,7 +320,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)));
@@ -15495,7 +15579,7 @@ index 6c176933967f6ee98da3026f16a10efe4c3842fe..aa5e17e497bbc1d45b361de73cc7a181
}
@Override
-@@ -612,6 +613,12 @@ public abstract class AbstractArrow extends Projectile {
+@@ -641,6 +642,12 @@ public abstract class AbstractArrow extends Projectile {
this.knockback = punch;
}
@@ -15554,30 +15638,18 @@ index 0bbe853f7df93f9dcd2b21d762939f8b6be069aa..7db9844083703944f59e112c6dc5e1a5
public void tick() {
super.tick();
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 cd0629581bae5f805842157af36c2d838e01bee3..b0a559dfefac693bda8692a30fbaa5ac8062ef27 100644
+index f0a6251cc8f612b898231e505c47fd5b2bbb4973..8e13b5d3e89e49994ad9763be7e4f35dd58a9c5e 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
-@@ -326,6 +326,6 @@ public abstract class Projectile extends Entity implements TraceableEntity {
+@@ -334,7 +334,7 @@ public abstract class Projectile extends Entity implements TraceableEntity {
public boolean mayInteract(Level 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);
}
- }
-diff --git a/src/main/java/net/minecraft/world/entity/projectile/ProjectileUtil.java b/src/main/java/net/minecraft/world/entity/projectile/ProjectileUtil.java
-index cc0a3d9794d05b6bc6ab05f4f2ab8d83134b181d..e1f918d0bd2a70db1aba8bda8717149f58766825 100644
---- a/src/main/java/net/minecraft/world/entity/projectile/ProjectileUtil.java
-+++ b/src/main/java/net/minecraft/world/entity/projectile/ProjectileUtil.java
-@@ -33,7 +33,7 @@ public final class ProjectileUtil {
- return getHitResult(vec32, entity, predicate, vec3, level);
- }
-- private static HitResult getHitResult(Vec3 pos, Entity entity, Predicate predicate, Vec3 velocity, Level world) {
-+ public static HitResult getHitResult(Vec3 pos, Entity entity, Predicate predicate, Vec3 velocity, Level world) { // Purpur - private -> public
- Vec3 vec3 = pos.add(velocity);
- HitResult hitResult = world.clip(new ClipContext(pos, vec3, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, entity));
- if (hitResult.getType() != HitResult.Type.MISS) {
+ public boolean mayBreak(Level 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 9d43c8520953d6fe0d0948f9dbe14e0650ee01c2..deee9fffe6981d7e728621cc799a812d78000592 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java
@@ -15638,10 +15710,10 @@ index 718e120c9768cf716b32d3d652f53f1dda925168..440d3d72d8b2dac14f83a83caa5ae9db
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 f5db60cbecbe69941873e064315931089fe0e48a..2728eaaf0a9b761d932bd22639ef4e1ccc428482 100644
+index af4da25c9b13c114179fab3254aea5323210d7da..59cc9e9a56898c7bdc5474842c31d2fbe6a81897 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
-@@ -67,10 +67,11 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
+@@ -70,10 +70,11 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
Bukkit.getPluginManager().callEvent(teleEvent);
if (!teleEvent.isCancelled() && entityplayer.connection.isAcceptingMessages()) {
@@ -15654,7 +15726,7 @@ index f5db60cbecbe69941873e064315931089fe0e48a..2728eaaf0a9b761d932bd22639ef4e1c
entityendermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot());
this.level().addFreshEntity(entityendermite, CreatureSpawnEvent.SpawnReason.ENDER_PEARL);
}
-@@ -83,7 +84,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
+@@ -86,7 +87,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile {
entityplayer.connection.teleport(teleEvent.getTo());
entity.resetFallDistance();
CraftEventFactory.entityDamage = this;
@@ -15664,10 +15736,10 @@ index f5db60cbecbe69941873e064315931089fe0e48a..2728eaaf0a9b761d932bd22639ef4e1c
}
// CraftBukkit end
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 a6bc277b6589dd7104566542733327822d6299a4..dde841cc09ba4a3575a462b03537887551d47ba5 100644
+index 51931e5cecf4c9ed8442136b18a94c7da89cf77d..2e6817fc05fe92615842a29c3e0682306a6b3ec5 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java
-@@ -62,7 +62,7 @@ public class ThrownTrident extends AbstractArrow {
+@@ -60,7 +60,7 @@ public class ThrownTrident extends AbstractArrow {
Entity entity = this.getOwner();
byte b0 = (Byte) this.entityData.get(ThrownTrident.ID_LOYALTY);
@@ -15677,10 +15749,10 @@ index a6bc277b6589dd7104566542733327822d6299a4..dde841cc09ba4a3575a462b035378875
if (!this.level().isClientSide && this.pickup == AbstractArrow.Pickup.ALLOWED) {
this.spawnAtLocation(this.getPickupItem(), 0.1F);
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 06d1bdb9bd124b201c36d284c50d22bf50d3735a..b4687453256ead43cf5288994316c7bf946b86df 100644
+index 78dd3365dc4d1265fc2102f740d75a384f5df5c5..aa5ce9625bf23885a55521cbb4d994b684a5cf61 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/WitherSkull.java
-@@ -97,7 +97,7 @@ public class WitherSkull extends AbstractHurtingProjectile {
+@@ -98,7 +98,7 @@ public class WitherSkull extends AbstractHurtingProjectile {
if (!this.level().isClientSide) {
// CraftBukkit start
// this.level().explode(this, this.getX(), this.getY(), this.getZ(), 1.0F, false, World.a.MOB);
@@ -15689,7 +15761,7 @@ index 06d1bdb9bd124b201c36d284c50d22bf50d3735a..b4687453256ead43cf5288994316c7bf
this.level().getCraftServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
-@@ -109,6 +109,17 @@ public class WitherSkull extends AbstractHurtingProjectile {
+@@ -110,6 +110,17 @@ public class WitherSkull extends AbstractHurtingProjectile {
}
@@ -15765,12 +15837,12 @@ index 31831811ce16265e9828fa34d9e67d8ac195d723..a1f74718240da3dfb0fc53f337ec3bf1
if (!this.raidMap.containsKey(raid.getId())) {
this.raidMap.put(raid.getId(), raid);
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 44a6118d3bd67a95180f750c17967561946e2e87..faf449dfb4f95a300796db46833f3b6a51cb961b 100644
+index dc421a0a6430583f1f0154e1dd689b80253f6e3d..9984ac31e911473a94d90aae1cdd46e16ac0182b 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
-@@ -112,12 +112,14 @@ public abstract class AbstractMinecart extends Entity {
- private double flyingY = 0.949999988079071D; // Paper - restore vanilla precision
- private double flyingZ = 0.949999988079071D; // Paper - restore vanilla precision
+@@ -105,12 +105,14 @@ public abstract class AbstractMinecart extends VehicleEntity {
+ private double flyingY = 0.95;
+ private double flyingZ = 0.95;
public double maxSpeed = 0.4D;
+ public double storedMaxSpeed; // Purpur
// CraftBukkit end
@@ -15783,7 +15855,7 @@ index 44a6118d3bd67a95180f750c17967561946e2e87..faf449dfb4f95a300796db46833f3b6a
}
protected AbstractMinecart(EntityType> type, Level world, double x, double y, double z) {
-@@ -342,6 +344,12 @@ public abstract class AbstractMinecart extends Entity {
+@@ -294,6 +296,12 @@ public abstract class AbstractMinecart extends VehicleEntity {
@Override
public void tick() {
@@ -15796,7 +15868,7 @@ index 44a6118d3bd67a95180f750c17967561946e2e87..faf449dfb4f95a300796db46833f3b6a
// CraftBukkit start
double prevX = this.getX();
double prevY = this.getY();
-@@ -499,16 +507,62 @@ public abstract class AbstractMinecart extends Entity {
+@@ -451,16 +459,62 @@ public abstract class AbstractMinecart extends VehicleEntity {
public void activateMinecart(int x, int y, int z, boolean powered) {}
@@ -15859,7 +15931,7 @@ index 44a6118d3bd67a95180f750c17967561946e2e87..faf449dfb4f95a300796db46833f3b6a
this.move(MoverType.SELF, this.getDeltaMovement());
if (!this.onGround()) {
-@@ -670,7 +724,7 @@ public abstract class AbstractMinecart extends Entity {
+@@ -622,7 +676,7 @@ public abstract class AbstractMinecart extends VehicleEntity {
if (d18 > 0.01D) {
double d20 = 0.06D;
@@ -15869,25 +15941,10 @@ index 44a6118d3bd67a95180f750c17967561946e2e87..faf449dfb4f95a300796db46833f3b6a
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 5c07da62c82bc70138f6cb5007629d6974be69ac..c314febb75a85ef12051bde392c5b57e9c5d85ac 100644
+index c041c0b81be41cfd128c2f5ba56a5329d50b2efc..7e9c88efd2a1edea673d1ef81635c2891a04d30e 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java
-@@ -242,7 +242,13 @@ public class Boat extends Entity implements VariantHolder {
- }
-
- protected void destroy(DamageSource source) {
-- this.spawnAtLocation((ItemLike) this.getDropItem());
-+ // Purpur start
-+ final ItemStack boat = new ItemStack(this.getDropItem());
-+ if (this.level().purpurConfig.persistentDroppableEntityDisplayNames && this.hasCustomName()) {
-+ boat.setHoverName(this.getCustomName());
-+ }
-+ this.spawnAtLocation(boat);
-+ // Purpur end
- }
-
- @Override
-@@ -578,6 +584,7 @@ public class Boat extends Entity implements VariantHolder {
+@@ -521,6 +521,7 @@ public class Boat extends VehicleEntity implements VariantHolder {
if (f > 0.0F) {
this.landFriction = f;
@@ -15895,6 +15952,21 @@ index 5c07da62c82bc70138f6cb5007629d6974be69ac..c314febb75a85ef12051bde392c5b57e
return Boat.Status.ON_LAND;
} else {
return Boat.Status.IN_AIR;
+@@ -967,7 +968,13 @@ public class Boat extends VehicleEntity implements VariantHolder {
+
+ @Override
+ public ItemStack getPickResult() {
+- return new ItemStack(this.getDropItem());
++ // Purpur start
++ final ItemStack boat = new ItemStack(this.getDropItem());
++ if (this.level().purpurConfig.persistentDroppableEntityDisplayNames && this.hasCustomName()) {
++ boat.setHoverName(this.getCustomName());
++ }
++ return boat;
++ // Purpur end
+ }
+
+ public static enum Type implements StringRepresentable {
diff --git a/src/main/java/net/minecraft/world/food/FoodData.java b/src/main/java/net/minecraft/world/food/FoodData.java
index c3448707fd8a632b457cc97b35d08a9c6933d5ee..e8079d126e6c0cf0b15c01afb6498922ee05964c 100644
--- a/src/main/java/net/minecraft/world/food/FoodData.java
@@ -15966,7 +16038,7 @@ index b16d9e2eaa589f19c563ee70b1a56d67dbcdecb0..71beab673f04cd051c46ea37f8c84731
public static final FoodProperties BAKED_POTATO = (new FoodProperties.Builder()).nutrition(5).saturationMod(0.6F).build();
public static final FoodProperties BEEF = (new FoodProperties.Builder()).nutrition(3).saturationMod(0.3F).meat().build();
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
-index 82f18790b9dc55b039ae03600a80a46d56a87521..6a754ecd4e9d6c3ebc7bd91b1de797fdbf3c4290 100644
+index 47a3c18401e2df4c89908691348f2411d3ef6fda..5ca5b5e5925d330f2962a9a1024b5dd675f0003a 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 {
@@ -16211,7 +16283,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 c5c509fbb915c60dfa95aac8510684d0b9f8b0ff..d604b7ec46f08993647979ed220a84842e3fe325 100644
+index 343f44db579839eb61376f876b5eff2e615dc2e5..849b6a30d412d10f1e2e6e88f2d8d990e4a720e4 100644
--- a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
@@ -40,6 +40,12 @@ import org.bukkit.event.enchantment.PrepareItemEnchantEvent;
@@ -16277,7 +16349,7 @@ index c5c509fbb915c60dfa95aac8510684d0b9f8b0ff..d604b7ec46f08993647979ed220a8484
});
}
diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
-index 076c2b2938c9b88b7e71dbc2aa9d8c7e90d4fe75..b1eacb9691b320a10de3420fae3632bb9d5b7ae3 100644
+index 4acad717bfec91e4abcdd59900e6872838d0712c..46c4468b846085d92f773142ecbee0fe258ff319 100644
--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
@@ -95,9 +95,11 @@ public class GrindstoneMenu extends AbstractContainerMenu {
@@ -16352,28 +16424,20 @@ index 076c2b2938c9b88b7e71dbc2aa9d8c7e90d4fe75..b1eacb9691b320a10de3420fae3632bb
return itemstack;
diff --git a/src/main/java/net/minecraft/world/inventory/InventoryMenu.java b/src/main/java/net/minecraft/world/inventory/InventoryMenu.java
-index 9af1da3858d6cf79b8bfaf99dde1370ccc50d023..45eec732ff0e4e78b4d3f2112b6a79d7ae668d2f 100644
+index 9af1da3858d6cf79b8bfaf99dde1370ccc50d023..1acb41fab25bdbc4109913b111dbe3b0e106af3f 100644
--- a/src/main/java/net/minecraft/world/inventory/InventoryMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/InventoryMenu.java
-@@ -4,6 +4,7 @@ import com.mojang.datafixers.util.Pair;
- import net.minecraft.network.chat.Component;
- import net.minecraft.resources.ResourceLocation;
- import net.minecraft.world.Container;
-+import net.minecraft.world.effect.MobEffects;
- import net.minecraft.world.entity.EquipmentSlot;
- import net.minecraft.world.entity.Mob;
- import net.minecraft.world.entity.player.Inventory;
-@@ -95,7 +96,7 @@ public class InventoryMenu extends RecipeBookMenu {
+@@ -95,7 +95,7 @@ public class InventoryMenu extends RecipeBookMenu {
public boolean mayPickup(Player playerEntity) {
ItemStack itemstack = this.getItem();
- return !itemstack.isEmpty() && !playerEntity.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.mayPickup(playerEntity);
-+ return !itemstack.isEmpty() && !playerEntity.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? playerEntity.level().purpurConfig.playerRemoveBindingWithWeakness && playerEntity.hasEffect(MobEffects.WEAKNESS) : super.mayPickup(playerEntity); // Purpur
++ return !itemstack.isEmpty() && !playerEntity.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? playerEntity.level().purpurConfig.playerRemoveBindingWithWeakness && playerEntity.hasEffect(net.minecraft.world.effect.MobEffects.WEAKNESS) : super.mayPickup(playerEntity); // Purpur
}
@Override
diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
-index c2cf5a8e788637c6264cf43d712a5be223ff1cc5..a578882b64c581ef4f47fa483a9f2988cfa4c8cf 100644
+index e5a7f36843d621e6c714ef2e1cb8e2e3551924ef..2071c21783cc5e3f542018de3b0a7a1c579147da 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 {
@@ -16443,58 +16507,33 @@ index 7cffc64573008502bdd14ae4906fe51166b12fb3..1feafdbb48cf760cb6ebf95d5be2c32b
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 18898e16ec42f6b694b06e09d9174b60d62450d7..20f33b77b4a9494be227456bc742a029eb0af59b 100644
+index 2e75fd06e9e379eb95ebfe55086ffc327706ab2f..2918b1aca8fae6a319881a631dc727b6d375a33c 100644
--- a/src/main/java/net/minecraft/world/item/AxeItem.java
+++ b/src/main/java/net/minecraft/world/item/AxeItem.java
-@@ -33,29 +33,32 @@ public class AxeItem extends DiggerItem {
+@@ -33,13 +33,15 @@ public class AxeItem extends DiggerItem {
+ Level level = context.getLevel();
BlockPos blockPos = context.getClickedPos();
Player player = context.getPlayer();
- BlockState blockState = level.getBlockState(blockPos);
-- Optional optional = this.getStripped(blockState);
-- Optional optional2 = WeatheringCopper.getPrevious(blockState);
-- Optional optional3 = Optional.ofNullable(HoneycombItem.WAX_OFF_BY_BLOCK.get().get(blockState.getBlock())).map((block) -> {
-- return block.withPropertiesOf(blockState);
-- });
-+ // Purpur start
-+ Block clickedBlock = level.getBlockState(blockPos).getBlock();
-+ Optional optional = Optional.ofNullable(level.purpurConfig.axeStrippables.get(blockState.getBlock()));
-+ Optional optional2 = Optional.ofNullable(level.purpurConfig.axeWeatherables.get(blockState.getBlock()));
-+ Optional optional3 = Optional.ofNullable(level.purpurConfig.axeWaxables.get(blockState.getBlock()));
-+ // Purpur end
- ItemStack itemStack = context.getItemInHand();
-- Optional optional4 = Optional.empty();
-+ Optional optional4 = Optional.empty(); // Purpur
- if (optional.isPresent()) {
-- level.playSound(player, blockPos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F);
-+ if (!STRIPPABLES.containsKey(clickedBlock)) level.playSound(null, blockPos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F); // Purpur - force sound
- optional4 = optional;
- } else if (optional2.isPresent()) {
-- level.playSound(player, blockPos, SoundEvents.AXE_SCRAPE, SoundSource.BLOCKS, 1.0F, 1.0F);
-+ if (!HoneycombItem.WAXABLES.get().containsKey(clickedBlock)) level.playSound(null, blockPos, SoundEvents.AXE_SCRAPE, SoundSource.BLOCKS, 1.0F, 1.0F); // Purpur - force sound
- level.levelEvent(player, 3005, blockPos, 0);
- optional4 = optional2;
- } else if (optional3.isPresent()) {
-- level.playSound(player, blockPos, SoundEvents.AXE_WAX_OFF, SoundSource.BLOCKS, 1.0F, 1.0F);
-+ if (!HoneycombItem.WAX_OFF_BY_BLOCK.get().containsKey(clickedBlock)) level.playSound(null, blockPos, SoundEvents.AXE_WAX_OFF, SoundSource.BLOCKS, 1.0F, 1.0F); // Purpur - force sound
- level.levelEvent(player, 3004, blockPos, 0);
- optional4 = optional3;
- }
-
- if (optional4.isPresent()) {
-+ org.purpurmc.purpur.tool.Actionable actionable = optional4.get(); // Purpur
-+ BlockState state = actionable.into().withPropertiesOf(blockState); // Purpur
+- Optional optional = this.evaluateNewBlockState(level, blockPos, player, level.getBlockState(blockPos));
++ Optional optional = this.evaluateActionable(level, blockPos, player, level.getBlockState(blockPos)); // Purpur
+ if (optional.isEmpty()) {
+ return InteractionResult.PASS;
+ } else {
++ org.purpurmc.purpur.tool.Actionable actionable = optional.get(); // Purpur
++ BlockState state = actionable.into().withPropertiesOf(level.getBlockState(blockPos)); // Purpur
+ ItemStack itemStack = context.getItemInHand();
// Paper start - EntityChangeBlockEvent
-- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, blockPos, optional4.get())) {
+- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, blockPos, optional.get())) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, blockPos, state)) { // Purpur
return InteractionResult.PASS;
}
// Paper end
-@@ -63,15 +66,22 @@ public class AxeItem extends DiggerItem {
+@@ -47,35 +49,40 @@ public class AxeItem extends DiggerItem {
CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger((ServerPlayer)player, blockPos, itemStack);
}
-- level.setBlock(blockPos, optional4.get(), 11);
-- level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(player, optional4.get()));
+- level.setBlock(blockPos, optional.get(), 11);
+- level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(player, optional.get()));
+ // Purpur start
+ level.setBlock(blockPos, state, 11);
+ actionable.drops().forEach((drop, chance) -> {
@@ -16512,11 +16551,38 @@ index 18898e16ec42f6b694b06e09d9174b60d62450d7..20f33b77b4a9494be227456bc742a029
- return InteractionResult.sidedSuccess(level.isClientSide);
+ return InteractionResult.SUCCESS; // Purpur - force arm swing
- } else {
- return InteractionResult.PASS;
}
+ }
+
+- private Optional evaluateNewBlockState(Level world, BlockPos pos, @Nullable Player player, BlockState state) {
+- Optional optional = this.getStripped(state);
++ private Optional evaluateActionable(Level world, BlockPos pos, @Nullable Player player, BlockState state) { // Purpur
++ Optional optional = Optional.ofNullable(world.purpurConfig.axeStrippables.get(state.getBlock())); // Purpur
+ if (optional.isPresent()) {
+- world.playSound(player, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F);
++ world.playSound(STRIPPABLES.containsKey(state.getBlock()) ? player : null, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F); // Purpur - force sound
+ return optional;
+ } else {
+- Optional optional2 = WeatheringCopper.getPrevious(state);
++ Optional optional2 = Optional.ofNullable(world.purpurConfig.axeWeatherables.get(state.getBlock())); // Purpur
+ if (optional2.isPresent()) {
+- world.playSound(player, pos, SoundEvents.AXE_SCRAPE, SoundSource.BLOCKS, 1.0F, 1.0F);
++ world.playSound(WeatheringCopper.getPrevious(state).isPresent() ? player : null, pos, SoundEvents.AXE_SCRAPE, SoundSource.BLOCKS, 1.0F, 1.0F); // Purpur - force sound
+ world.levelEvent(player, 3005, pos, 0);
+ return optional2;
+ } else {
+- Optional optional3 = Optional.ofNullable(HoneycombItem.WAX_OFF_BY_BLOCK.get().get(state.getBlock())).map((block) -> {
+- return block.withPropertiesOf(state);
+- });
++ Optional optional3 = Optional.ofNullable(world.purpurConfig.axeWaxables.get(state.getBlock())); // Purpur
+ if (optional3.isPresent()) {
+- world.playSound(player, pos, SoundEvents.AXE_WAX_OFF, SoundSource.BLOCKS, 1.0F, 1.0F);
++ world.playSound(HoneycombItem.WAX_OFF_BY_BLOCK.get().containsKey(state.getBlock()) ? player : null, pos, SoundEvents.AXE_WAX_OFF, SoundSource.BLOCKS, 1.0F, 1.0F); // Purpur - force sound
+ world.levelEvent(player, 3004, pos, 0);
+ 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 efdf56044396b4ce486948d2c993971f99174a5e..42bfde8e36b6395f50973300313d6959e2735327 100644
+index 6404323f01833569e46c4ae45ceb21eb297c0c7f..891cc06311fd135d2ac4a46d9cb3368ea2c041dd 100644
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
@@ -152,7 +152,24 @@ public class BlockItem extends Item {
@@ -16555,10 +16621,10 @@ index efdf56044396b4ce486948d2c993971f99174a5e..42bfde8e36b6395f50973300313d6959
CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack);
diff --git a/src/main/java/net/minecraft/world/item/BoatItem.java b/src/main/java/net/minecraft/world/item/BoatItem.java
-index aec7ac31a35b1cc81f40b3fbeb5cf95c0f2c8a6c..cbcd35e60a2c344c83978abf0b94c2120ff53dee 100644
+index 67a5a201d0b26ca7b27e6d0c3ffb9f8b6e16bce0..ec3d60b561de45349b705b7f14592be930af4b91 100644
--- a/src/main/java/net/minecraft/world/item/BoatItem.java
+++ b/src/main/java/net/minecraft/world/item/BoatItem.java
-@@ -69,6 +69,11 @@ public class BoatItem extends Item {
+@@ -71,6 +71,11 @@ public class BoatItem extends Item {
entityboat.setVariant(this.type);
entityboat.setYRot(user.getYRot());
@@ -16710,7 +16776,7 @@ index 58cb992c5defec2f092755cbde661ff10f38bf9d..52f48681407d23f0925f4c9c072d5f0a
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)) {
diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
-index 3688e9f8c6c6d1239095e3a87060ccca90386d0c..34254eec36d34ae343733fa1abbaaba60be41a3b 100644
+index faa3f62d22266a3c32d6c95c3ffebd4aa3880739..0cf62b1f64afa56c319392eafe0d444b7c5662c7 100644
--- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java
+++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
@@ -26,7 +26,7 @@ public class EndCrystalItem extends Item {
@@ -16841,10 +16907,10 @@ index 180aec596110309aade13d2080f8824d152b07cb..552c31c0f3746dd35388395036e70a92
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 d0f7baa80cb7d0883304abe2ed990c258a0d92b6..2776b124dd15e4c84edcfbf98ba44d53ef149e43 100644
+index 5caf48c84b8dd46903dbdacaa3a5e13272374e0e..cbfd535d62acdde7789fa88332f4a607c381d450 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
-@@ -432,6 +432,7 @@ public final class ItemStack {
+@@ -453,6 +453,7 @@ public final class ItemStack {
world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710
for (BlockState blockstate : blocks) {
blockstate.update(true, false);
@@ -16852,7 +16918,7 @@ index d0f7baa80cb7d0883304abe2ed990c258a0d92b6..2776b124dd15e4c84edcfbf98ba44d53
}
world.preventPoiUpdated = false;
-@@ -463,6 +464,7 @@ public final class ItemStack {
+@@ -484,6 +485,7 @@ public final class ItemStack {
if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically
block.getBlock().onPlace(block, world, newblockposition, oldBlock, true, context); // Paper - pass context
}
@@ -16860,7 +16926,7 @@ index d0f7baa80cb7d0883304abe2ed990c258a0d92b6..2776b124dd15e4c84edcfbf98ba44d53
world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point
}
-@@ -591,6 +593,16 @@ public final class ItemStack {
+@@ -612,6 +614,16 @@ public final class ItemStack {
return this.isDamageableItem() && this.getDamageValue() > 0;
}
@@ -16877,7 +16943,7 @@ index d0f7baa80cb7d0883304abe2ed990c258a0d92b6..2776b124dd15e4c84edcfbf98ba44d53
public int getDamageValue() {
return this.tag == null ? 0 : this.tag.getInt("Damage");
}
-@@ -610,7 +622,7 @@ public final class ItemStack {
+@@ -631,7 +643,7 @@ public final class ItemStack {
int j;
if (amount > 0) {
@@ -16886,7 +16952,7 @@ index d0f7baa80cb7d0883304abe2ed990c258a0d92b6..2776b124dd15e4c84edcfbf98ba44d53
int k = 0;
for (int l = 0; j > 0 && l < amount; ++l) {
-@@ -665,6 +677,12 @@ public final class ItemStack {
+@@ -686,6 +698,12 @@ public final class ItemStack {
if (this.hurt(amount, entity.getRandom(), entity /*instanceof ServerPlayer ? (ServerPlayer) entity : null*/)) { // Paper - pass LivingEntity for EntityItemDamageEvent
breakCallback.accept(entity);
Item item = this.getItem();
@@ -16899,7 +16965,7 @@ index d0f7baa80cb7d0883304abe2ed990c258a0d92b6..2776b124dd15e4c84edcfbf98ba44d53
// CraftBukkit start - Check for item breaking
if (this.count == 1 && entity instanceof net.minecraft.world.entity.player.Player) {
org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent((net.minecraft.world.entity.player.Player) entity, this);
-@@ -1191,7 +1209,7 @@ public final class ItemStack {
+@@ -1216,7 +1234,7 @@ public final class ItemStack {
ListTag nbttaglist = this.tag.getList("Enchantments", 10);
@@ -16908,7 +16974,7 @@ index d0f7baa80cb7d0883304abe2ed990c258a0d92b6..2776b124dd15e4c84edcfbf98ba44d53
processEnchantOrder(this.tag); // Paper
}
-@@ -1199,6 +1217,12 @@ public final class ItemStack {
+@@ -1224,6 +1242,12 @@ public final class ItemStack {
return this.tag != null && this.tag.contains("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false;
}
@@ -16922,10 +16988,10 @@ index d0f7baa80cb7d0883304abe2ed990c258a0d92b6..2776b124dd15e4c84edcfbf98ba44d53
this.getOrCreateTag().put(key, element);
}
diff --git a/src/main/java/net/minecraft/world/item/Items.java b/src/main/java/net/minecraft/world/item/Items.java
-index 5f20e075c532f0f1d413242949d1738c0c152bf7..5fbb13ebef0ca66419f3e5006d19e4a5918a038a 100644
+index f692149d91b525bda6dc79d489d7496ea24037e8..cf68dca4096556b0c2594c76fcf113419e56dae0 100644
--- a/src/main/java/net/minecraft/world/item/Items.java
+++ b/src/main/java/net/minecraft/world/item/Items.java
-@@ -294,7 +294,7 @@ public class Items {
+@@ -316,7 +316,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);
@@ -16934,7 +17000,7 @@ index 5f20e075c532f0f1d413242949d1738c0c152bf7..5fbb13ebef0ca66419f3e5006d19e4a5
public static final Item CHEST = registerBlock(Blocks.CHEST);
public static final Item CRAFTING_TABLE = registerBlock(Blocks.CRAFTING_TABLE);
public static final Item FARMLAND = registerBlock(Blocks.FARMLAND);
-@@ -1184,7 +1184,7 @@ public class Items {
+@@ -1224,7 +1224,7 @@ public class Items {
public static final Item LANTERN = registerBlock(Blocks.LANTERN);
public static final Item SOUL_LANTERN = registerBlock(Blocks.SOUL_LANTERN);
public static final Item SWEET_BERRIES = registerItem("sweet_berries", new ItemNameBlockItem(Blocks.SWEET_BERRY_BUSH, (new Item.Properties()).food(Foods.SWEET_BERRIES)));
@@ -16943,7 +17009,7 @@ index 5f20e075c532f0f1d413242949d1738c0c152bf7..5fbb13ebef0ca66419f3e5006d19e4a5
public static final Item CAMPFIRE = registerBlock(Blocks.CAMPFIRE);
public static final Item SOUL_CAMPFIRE = registerBlock(Blocks.SOUL_CAMPFIRE);
public static final Item SHROOMLIGHT = registerBlock(Blocks.SHROOMLIGHT);
-@@ -1309,6 +1309,13 @@ public class Items {
+@@ -1367,6 +1367,13 @@ public class Items {
((BlockItem)item).registerBlocks(Item.BY_BLOCK, item);
}
@@ -16958,10 +17024,10 @@ index 5f20e075c532f0f1d413242949d1738c0c152bf7..5fbb13ebef0ca66419f3e5006d19e4a5
}
}
diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java
-index c368b437597edf7e165326727ae778a69c3fcc83..fed5bfb02ab7d6c1d1d9bf993fda5b3f411b9352 100644
+index 797415866a7f182d804f6b8e57ceb07a6ac2a20a..6cfd169c2c32b644d70907358c2d4a2087c00a68 100644
--- a/src/main/java/net/minecraft/world/item/MapItem.java
+++ b/src/main/java/net/minecraft/world/item/MapItem.java
-@@ -243,6 +243,7 @@ public class MapItem extends ComplexItem {
+@@ -235,6 +235,7 @@ public class MapItem extends ComplexItem {
MapItemSavedData worldmap = MapItem.getSavedData(map, world);
if (worldmap != null) {
@@ -16993,10 +17059,10 @@ index f33977d95b6db473be4f95075ba99caf90ad0220..56dc04d8875971ee9a5d077a695509af
return stack.isEmpty() ? new ItemStack(Items.BUCKET) : stack;
diff --git a/src/main/java/net/minecraft/world/item/MinecartItem.java b/src/main/java/net/minecraft/world/item/MinecartItem.java
-index a33395dc5a94d89b5ab273c7832813b6ff9ea3b7..2b2218e2de535ebc8f529f5b5bf98fa1ef819a5e 100644
+index 3aa73cd44aa8c86b78c35bc1788e4f83018c49ed..66a8b28275619079e3bcbcc460146976d533d54e 100644
--- a/src/main/java/net/minecraft/world/item/MinecartItem.java
+++ b/src/main/java/net/minecraft/world/item/MinecartItem.java
-@@ -122,8 +122,9 @@ public class MinecartItem extends Item {
+@@ -119,8 +119,9 @@ public class MinecartItem extends Item {
BlockState iblockdata = world.getBlockState(blockposition);
if (!iblockdata.is(BlockTags.RAILS)) {
@@ -17007,8 +17073,8 @@ index a33395dc5a94d89b5ab273c7832813b6ff9ea3b7..2b2218e2de535ebc8f529f5b5bf98fa1
+ } // else { // Purpur - place minecarts anywhere
ItemStack itemstack = context.getItemInHand();
- if (!world.isClientSide) {
-@@ -151,6 +152,6 @@ public class MinecartItem extends Item {
+ if (world instanceof ServerLevel) {
+@@ -145,6 +146,6 @@ public class MinecartItem extends Item {
itemstack.shrink(1);
return InteractionResult.sidedSuccess(world.isClientSide);
@@ -17071,25 +17137,26 @@ index ef3f90a5bcdd7b9815a4053cff166f9d2552f55d..e7e5e1cc92f56e3daba8fa09c59188fe
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)) {
diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.java
-index 741719301e6fc91a598e74342810c4185e6fde26..6fbff9c02fbabf03c9c649a9ea6128021081f9cd 100644
+index 4f10f801dc126e9135432939b6663770c0e7a0bc..8f89a1c7e6214f549490ecf75afbdd72b897b120 100644
--- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java
+++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java
-@@ -68,6 +68,15 @@ public class SpawnEggItem extends Item {
- SpawnerBlockEntity tileentitymobspawner = (SpawnerBlockEntity) tileentity;
- EntityType> entitytypes = this.getType(itemstack.getTag());
+@@ -68,6 +68,16 @@ public class SpawnEggItem extends Item {
+ Spawner spawner = (Spawner) tileentity;
-+ // Purpur start
-+ org.bukkit.block.Block bukkitBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
-+ org.purpurmc.purpur.event.PlayerSetSpawnerTypeWithEggEvent event = new org.purpurmc.purpur.event.PlayerSetSpawnerTypeWithEggEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), bukkitBlock, (org.bukkit.block.CreatureSpawner) bukkitBlock.getState(), org.bukkit.entity.EntityType.fromName(entitytypes.getName()));
-+ if (!event.callEvent()) {
-+ return InteractionResult.FAIL;
-+ }
-+ entitytypes = EntityType.getFromBukkitType(event.getEntityType());
-+ // Purpur end
+ entitytypes = this.getType(itemstack.getTag());
+
- tileentitymobspawner.setEntityId(entitytypes, world.getRandom());
- tileentity.setChanged();
- world.sendBlockUpdated(blockposition, iblockdata, iblockdata, 3);
++ // Purpur start
++ org.bukkit.block.Block bukkitBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
++ org.purpurmc.purpur.event.PlayerSetSpawnerTypeWithEggEvent event = new org.purpurmc.purpur.event.PlayerSetSpawnerTypeWithEggEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), bukkitBlock, (org.bukkit.block.CreatureSpawner) bukkitBlock.getState(), org.bukkit.entity.EntityType.fromName(entitytypes.getName()));
++ if (!event.callEvent()) {
++ return InteractionResult.FAIL;
++ }
++ entitytypes = EntityType.getFromBukkitType(event.getEntityType());
++ // Purpur end
++
+ spawner.setEntityId(entitytypes, world.getRandom());
+ world.sendBlockUpdated(blockposition, iblockdata, iblockdata, 3);
+ world.gameEvent((Entity) context.getPlayer(), 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 de5bdceb4c8578fb972a2fd5ee0dfdae509e46dc..bcf63ccb6e679cb97d658780b2663aafa3568bcb 100644
--- a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java
@@ -17104,7 +17171,7 @@ index de5bdceb4c8578fb972a2fd5ee0dfdae509e46dc..bcf63ccb6e679cb97d658780b2663aaf
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)) {
diff --git a/src/main/java/net/minecraft/world/item/TridentItem.java b/src/main/java/net/minecraft/world/item/TridentItem.java
-index 8078f127ff4b6e0aafb5804b9c02e237f79445b5..c32cbe6065ecb6810f352b8a3598c21e42e60e1d 100644
+index 5fab851b319847035fb1eefd0ab999de3ccc2cd8..ec5daeef857fdad6c7659130fb42f52cf6eb491f 100644
--- a/src/main/java/net/minecraft/world/item/TridentItem.java
+++ b/src/main/java/net/minecraft/world/item/TridentItem.java
@@ -77,11 +77,19 @@ public class TridentItem extends Item implements Vanishable {
@@ -17128,7 +17195,7 @@ index 8078f127ff4b6e0aafb5804b9c02e237f79445b5..c32cbe6065ecb6810f352b8a3598c21e
// CraftBukkit start
// Paper start
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());
-@@ -130,6 +138,14 @@ public class TridentItem extends Item implements Vanishable {
+@@ -131,6 +139,14 @@ public class TridentItem extends Item implements Vanishable {
f2 *= f6 / f5;
f3 *= f6 / f5;
f4 *= f6 / f5;
@@ -17144,10 +17211,10 @@ index 8078f127ff4b6e0aafb5804b9c02e237f79445b5..c32cbe6065ecb6810f352b8a3598c21e
entityhuman.startAutoSpinAttack(20);
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 06fe5b056d78d42cdf78437eeabe1786d596b7f8..3532db21cee82c18f95c540d24b2071585d71c4e 100644
+index 7c29750e534eae4266bf7a63c50e3827401d6569..e8e9a3370ba07dc0ca47c8352f6f04a449f2268f 100644
--- a/src/main/java/net/minecraft/world/item/crafting/Ingredient.java
+++ b/src/main/java/net/minecraft/world/item/crafting/Ingredient.java
-@@ -39,6 +39,7 @@ public final class Ingredient implements Predicate {
+@@ -36,6 +36,7 @@ public final class Ingredient implements Predicate {
@Nullable
private IntList stackingIds;
public boolean exact; // CraftBukkit
@@ -17155,7 +17222,7 @@ index 06fe5b056d78d42cdf78437eeabe1786d596b7f8..3532db21cee82c18f95c540d24b20715
public static final Codec CODEC = Ingredient.codec(true);
public static final Codec CODEC_NONEMPTY = Ingredient.codec(false);
-@@ -70,6 +71,12 @@ public final class Ingredient implements Predicate {
+@@ -67,6 +68,12 @@ public final class Ingredient implements Predicate {
} else if (this.isEmpty()) {
return itemstack.isEmpty();
} else {
@@ -17301,10 +17368,10 @@ index 4f7457578ab3118d10e0d5dfc23d79c9b20c2f44..e03ce53b93d1b9366f2a7f14f341750a
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 6eca4a9b3cf462a4d18f32619bbcdfda0fa2ebc5..914564a528c360f352927e7681ab2e31ed365b21 100644
+index 3aa4cb526f04a171ace0b95d18ecebc9a002470a..ac6bdf21d5ff8ba563f8c9187f6a8dcc823587aa 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
-@@ -71,6 +71,7 @@ public abstract class BaseSpawner {
+@@ -57,6 +57,7 @@ public abstract class BaseSpawner {
}
public boolean isNearPlayer(Level world, BlockPos pos) {
@@ -17313,7 +17380,7 @@ index 6eca4a9b3cf462a4d18f32619bbcdfda0fa2ebc5..914564a528c360f352927e7681ab2e31
}
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
-index aaa07fcd4b32fe0de88142ab30378327a01f1729..bc8555d21d418f9da37cc089904f7cb038b1cdbe 100644
+index ff0b7b9e4ae3aa0c170d05bc51fd7ff26e7531ee..53d4000593d4c79de8e8ab04bfd614b7ee0ad7a5 100644
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
@@ -191,7 +191,7 @@ public interface EntityGetter {
@@ -17326,10 +17393,10 @@ index aaa07fcd4b32fe0de88142ab30378327a01f1729..bc8555d21d418f9da37cc089904f7cb0
if (range < 0.0D || 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 45243249a561440512ef2a620c60b02e159c80e2..ef9b1687dd2dfda5398523140aecc678b4690642 100644
+index 210b6d71207b99e66ba014b176b2c1445053b1d1..1223e678395e84859449a11e9e403454ddae0b15 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
-@@ -87,7 +87,7 @@ public class Explosion {
+@@ -97,7 +97,7 @@ public class Explosion {
this.hitPlayers = Maps.newHashMap();
this.level = world;
this.source = entity;
@@ -17338,7 +17405,7 @@ index 45243249a561440512ef2a620c60b02e159c80e2..ef9b1687dd2dfda5398523140aecc678
this.x = x;
this.y = y;
this.z = z;
-@@ -403,10 +403,27 @@ public class Explosion {
+@@ -425,10 +425,27 @@ public class Explosion {
public void explode() {
// CraftBukkit start
@@ -17367,37 +17434,37 @@ index 45243249a561440512ef2a620c60b02e159c80e2..ef9b1687dd2dfda5398523140aecc678
this.level.gameEvent(this.source, GameEvent.EXPLODE, new Vec3(this.x, this.y, this.z));
Set set = Sets.newHashSet();
boolean flag = true;
-@@ -706,7 +723,7 @@ public class Explosion {
- if (!iblockdata.isAir() && iblockdata.isDestroyable()) { // Paper
- BlockPos blockposition1 = blockposition.immutable();
+@@ -659,7 +676,7 @@ public class Explosion {
+ }
-- this.level.getProfiler().push("explosion_blocks");
-+ //this.level.getProfiler().push("explosion_blocks"); // Purpur
- if (block.dropFromExplosion(this)) {
- Level world = this.level;
+ if (flag1) {
+- this.level.getProfiler().push("explosion_blocks");
++ // this.level.getProfiler().push("explosion_blocks"); // Purpur
+ List> list = new ArrayList();
-@@ -728,7 +745,7 @@ public class Explosion {
-
- this.level.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 3);
- block.wasExploded(this.level, blockposition, this);
-- this.level.getProfiler().pop();
-+ //this.level.getProfiler().pop(); // Purpur
- }
+ Util.shuffle(this.toBlow, this.level.random);
+@@ -735,7 +752,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 99e1c645871be28d130319b65700a1b8db093de4..25540a7f5631acd856726cdb44bace9be7dab401 100644
+index 2902c29cd7f0b99b84cff3664fc4ec15a383e41b..b58402221840a9e72b30a31d884b0fb2d86883fd 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -176,6 +176,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
- // Paper end
+@@ -179,6 +179,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ // 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;
-@@ -193,6 +194,49 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -196,6 +197,49 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
// Paper end - fix and optimise world upgrading
@@ -17447,22 +17514,24 @@ index 99e1c645871be28d130319b65700a1b8db093de4..25540a7f5631acd856726cdb44bace9b
public CraftWorld getWorld() {
return this.world;
}
-@@ -210,11 +254,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -212,12 +256,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ // Paper end
public abstract ResourceKey getTypeKey();
-
+-
- protected final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(java.util.concurrent.ThreadLocalRandom.current().nextLong()); public net.minecraft.util.RandomSource getThreadUnsafeRandom() { return this.randomTickRandom; } // Pufferfish - move thread unsafe random initialization // Pufferfish - getter
++
+ //protected final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(java.util.concurrent.ThreadLocalRandom.current().nextLong()); public net.minecraft.util.RandomSource getThreadUnsafeRandom() { return this.randomTickRandom; } // Pufferfish - move thread unsafe random initialization // Pufferfish - getter // Purpur - dont break ABI
- 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 - Async-Anti-Xray - Pass executor
+ 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; Async-Anti-Xray: Pass executor
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
- this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper
+ 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
+ this.playerBreedingCooldowns = this.getNewBreedingCooldownCache(); // Purpur
this.generator = gen;
this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env);
-@@ -1255,18 +1301,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1269,18 +1315,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
protected void tickBlockEntities() {
@@ -17484,9 +17553,9 @@ index 99e1c645871be28d130319b65700a1b8db093de4..25540a7f5631acd856726cdb44bace9b
- this.timings.tileEntityTick.startTiming(); // Spigot
+ //this.timings.tileEntityTick.startTiming(); // Spigot // Purpur
// Spigot start
- // Iterator iterator = this.blockEntityTickers.iterator();
- int tilesThisCycle = 0;
-@@ -1299,10 +1345,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ // Iterator iterator = this.blockEntityTickers.iterator();
+ boolean flag = this.tickRateManager().runsNormally();
+@@ -1309,10 +1355,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
this.blockEntityTickers.removeAll(toRemove);
@@ -17499,7 +17568,7 @@ index 99e1c645871be28d130319b65700a1b8db093de4..25540a7f5631acd856726cdb44bace9b
this.spigotConfig.currentPrimedTnt = 0; // Spigot
}
-@@ -1505,7 +1551,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1522,7 +1568,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@Override
public List getEntities(@Nullable Entity except, AABB box, Predicate super Entity> predicate) {
@@ -17508,7 +17577,7 @@ index 99e1c645871be28d130319b65700a1b8db093de4..25540a7f5631acd856726cdb44bace9b
List list = Lists.newArrayList();
((ServerLevel)this).getEntityLookup().getEntities(except, box, list, predicate); // Paper - optimise this call
return list;
-@@ -1524,7 +1570,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1541,7 +1587,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
public void getEntities(EntityTypeTest filter, AABB box, Predicate super T> predicate, List super T> result, int limit) {
@@ -17517,7 +17586,7 @@ index 99e1c645871be28d130319b65700a1b8db093de4..25540a7f5631acd856726cdb44bace9b
// Paper start - optimise this call
//TODO use limit
if (filter instanceof net.minecraft.world.entity.EntityType entityTypeTest) {
-@@ -1781,7 +1827,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1800,7 +1846,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
public ProfilerFiller getProfiler() {
@@ -17526,7 +17595,7 @@ index 99e1c645871be28d130319b65700a1b8db093de4..25540a7f5631acd856726cdb44bace9b
return (ProfilerFiller) this.profiler.get();
}
-@@ -1881,4 +1927,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1912,4 +1958,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
}
// Paper end - notify observers even if grow failed
@@ -17542,7 +17611,7 @@ index 99e1c645871be28d130319b65700a1b8db093de4..25540a7f5631acd856726cdb44bace9b
+ // 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 9c2d62feff1816f5729060c6192269a5b2d34153..a2a59dd2e515bf4dca84a442703c122fd36f05e0 100644
+index 3fb96de68b93e8d33bd5ab9137e5d4facc94d788..22e12f0028187cf6c92aa0bf1f67764daae6f151 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
@@ -132,8 +132,8 @@ public final class NaturalSpawner {
@@ -17577,10 +17646,10 @@ index 9c2d62feff1816f5729060c6192269a5b2d34153..a2a59dd2e515bf4dca84a442703c122f
if (entityhuman != null) {
double d2 = entityhuman.distanceToSqr(d0, (double) i, d1);
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 5c5a3b169795bf8a527b316c666cbc2105c66622..020afeca950d2c7fb6c7b179d424548fd90f8b0d 100644
+index 9fca247f51e8b4d445f61ab5c16faf3928626deb..583bb1282fedcab75dbe4359a9f53b76a538d903 100644
--- a/src/main/java/net/minecraft/world/level/block/AnvilBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/AnvilBlock.java
-@@ -55,6 +55,54 @@ public class AnvilBlock extends FallingBlock {
+@@ -62,6 +62,54 @@ public class AnvilBlock extends FallingBlock {
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
@@ -17636,10 +17705,10 @@ index 5c5a3b169795bf8a527b316c666cbc2105c66622..020afeca950d2c7fb6c7b179d424548f
return InteractionResult.SUCCESS;
} else {
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 087f3b3cc180e16195efdc0b402701fd9f5d78b4..aa4e13f1c77f10221128569483497668cd2eb7d3 100644
+index 3ecc92439fc85d224ff52f41c5e34079e042a5e6..2336fea8c65d64a77a1afa4b8b976fb0d7da00eb 100644
--- a/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java
-@@ -43,6 +43,20 @@ public class AzaleaBlock extends BushBlock implements BonemealableBlock {
+@@ -49,6 +49,20 @@ public class AzaleaBlock extends BushBlock implements BonemealableBlock {
@Override
public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
@@ -17657,14 +17726,14 @@ index 087f3b3cc180e16195efdc0b402701fd9f5d78b4..aa4e13f1c77f10221128569483497668
+
+ private void growTree(ServerLevel world, RandomSource random, BlockPos pos, net.minecraft.world.level.block.state.BlockState state) {
+ // Purpur end
- TREE_GROWER.growTree(world, world.getChunkSource().getGenerator(), pos, state, random);
+ TreeGrower.AZALEA.growTree(world, world.getChunkSource().getGenerator(), pos, state, random);
}
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 3d2b34c5a7c9b00c1164b4f89c2cbff81fc460eb..b5505e926e5cdb447de68e8eb8e46c97eb988e27 100644
+index 2a65c7b859b1126dbac9819a01ca2652e20498a9..3192edee23b899107b17e354ddfb3159ac2ef429 100644
--- a/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BaseCoralPlantTypeBlock.java
-@@ -35,6 +35,7 @@ public class BaseCoralPlantTypeBlock extends Block implements SimpleWaterloggedB
+@@ -39,6 +39,7 @@ public abstract class BaseCoralPlantTypeBlock extends Block implements SimpleWat
}
protected static boolean scanForWater(BlockState state, BlockGetter world, BlockPos pos) {
@@ -17673,28 +17742,28 @@ index 3d2b34c5a7c9b00c1164b4f89c2cbff81fc460eb..b5505e926e5cdb447de68e8eb8e46c97
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 d40500f9a807cab0b2fb6fa9032f33f4fb74c895..2b66ddafaaca17f64d1e7502dfa4d7576e3e032f 100644
+index 2c1d03237d5b24b93807c7e97d969ace13d6a917..59fb467c3338edc7caf5103ad7c6becfc6311aa6 100644
--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java
-@@ -96,7 +96,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, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK);
-+ if (world.purpurConfig.bedExplode) world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, (float) world.purpurConfig.bedExplosionPower, world.purpurConfig.bedExplosionFire, world.purpurConfig.bedExplosionEffect); // Purpur
+- world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state
++ if (world.purpurConfig.bedExplode) world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, (float) world.purpurConfig.bedExplosionPower, world.purpurConfig.bedExplosionFire, world.purpurConfig.bedExplosionEffect); // Paper - add exploded state // Purpur
return InteractionResult.SUCCESS;
} else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) {
if (!BedBlock.canSetSpawn(world)) return this.explodeBed(state, world, pos); // Paper - check explode first
-@@ -149,7 +149,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
+@@ -159,7 +159,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
Vec3 vec3d = blockposition.getCenter();
-- world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK);
-+ if (world.purpurConfig.bedExplode) world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, (float) world.purpurConfig.bedExplosionPower, world.purpurConfig.bedExplosionFire, world.purpurConfig.bedExplosionEffect); // Purpur
+- world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state
++ if (world.purpurConfig.bedExplode) world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, (float) world.purpurConfig.bedExplosionPower, world.purpurConfig.bedExplosionFire, world.purpurConfig.bedExplosionEffect); // Paper - add exploded state // Purpur
return InteractionResult.SUCCESS;
}
}
-@@ -173,7 +173,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) {
@@ -17704,10 +17773,10 @@ index d40500f9a807cab0b2fb6fa9032f33f4fb74c895..2b66ddafaaca17f64d1e7502dfa4d757
@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 54cf35b0c48d96ecfb27ff13cd685c16a1cd616b..1822ea0c72cc1685aab86a44f75c791bc5c595fa 100644
+index 8e4a6a1188b2ce2825dc5750505212c72efb5c7b..c7f78ccb228d261984ac360f2ca6ae9478786184 100644
--- a/src/main/java/net/minecraft/world/level/block/BigDripleafBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BigDripleafBlock.java
-@@ -236,7 +236,7 @@ public class BigDripleafBlock extends HorizontalDirectionalBlock implements Bone
+@@ -243,7 +243,7 @@ public class BigDripleafBlock extends HorizontalDirectionalBlock implements Bone
BigDripleafBlock.playTiltSound(world, blockposition, soundeffect);
}
@@ -17717,10 +17786,10 @@ index 54cf35b0c48d96ecfb27ff13cd685c16a1cd616b..1822ea0c72cc1685aab86a44f75c791b
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 d4cbff18adb62073a1dceb189043789620af6877..65504432a13df45e895cf6ca885627014444563a 100644
+index 3f2fdf73e2e520838c7b59fe994e67ab2d1a4d6b..4543aa29d73bcff5d2e1e4b4f8bfaf53444d6322 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
-@@ -62,6 +62,13 @@ import net.minecraft.world.phys.shapes.Shapes;
+@@ -63,6 +63,13 @@ import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.slf4j.Logger;
@@ -17733,8 +17802,8 @@ index d4cbff18adb62073a1dceb189043789620af6877..65504432a13df45e895cf6ca88562701
+
public class Block extends BlockBehaviour implements ItemLike {
- private static final Logger LOGGER = LogUtils.getLogger();
-@@ -87,6 +94,10 @@ public class Block extends BlockBehaviour implements ItemLike {
+ public static final MapCodec CODEC = simpleCodec(Block::new);
+@@ -89,6 +96,10 @@ public class Block extends BlockBehaviour implements ItemLike {
public static final int UPDATE_LIMIT = 512;
protected final StateDefinition stateDefinition;
private BlockState defaultBlockState;
@@ -17745,7 +17814,7 @@ index d4cbff18adb62073a1dceb189043789620af6877..65504432a13df45e895cf6ca88562701
// Paper start
public final boolean isDestroyable() {
return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits ||
-@@ -313,7 +324,7 @@ public class Block extends BlockBehaviour implements ItemLike {
+@@ -320,7 +331,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) -> {
@@ -17754,23 +17823,23 @@ index d4cbff18adb62073a1dceb189043789620af6877..65504432a13df45e895cf6ca88562701
});
state.spawnAfterBreak((ServerLevel) world, pos, ItemStack.EMPTY, true);
}
-@@ -329,7 +340,7 @@ public class Block extends BlockBehaviour implements ItemLike {
- io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.block.CraftBlock.at(world, source), items);
+@@ -338,7 +349,7 @@ public class Block extends BlockBehaviour implements ItemLike {
+ event.setExpToDrop(block.getExpDrop(state, (ServerLevel) world, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping
event.callEvent();
for (var drop : event.getDrops()) {
- popResource(world.getMinecraftWorld(), pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
+ popResource(world.getMinecraftWorld(), pos, applyDisplayNameAndLoreFromTile(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop), blockEntity)); // Purpur
}
- state.spawnAfterBreak(world.getMinecraftWorld(), pos, ItemStack.EMPTY, true);
- }
-@@ -340,13 +351,53 @@ public class Block extends BlockBehaviour implements ItemLike {
- public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
+ state.spawnAfterBreak(world.getMinecraftWorld(), pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
+ block.popExperience((ServerLevel) world, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping
+@@ -355,13 +366,53 @@ 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) -> {
- Block.popResource(world, pos, itemstack1);
+ Block.popResource(world, pos, applyDisplayNameAndLoreFromTile(itemstack1, blockEntity)); // Purpur
});
- state.spawnAfterBreak((ServerLevel) world, pos, tool, true);
+ state.spawnAfterBreak((ServerLevel) world, pos, tool, dropExperience); // Paper - Properly handle xp dropping
}
}
@@ -17818,8 +17887,8 @@ index d4cbff18adb62073a1dceb189043789620af6877..65504432a13df45e895cf6ca88562701
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);
-@@ -430,7 +481,17 @@ public class Block extends BlockBehaviour implements ItemLike {
- } // Paper
+@@ -445,7 +496,17 @@ public class Block extends BlockBehaviour implements ItemLike {
+ } // Paper - fix drops not preventing stats/food exhaustion
}
- public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {}
@@ -17837,7 +17906,7 @@ index d4cbff18adb62073a1dceb189043789620af6877..65504432a13df45e895cf6ca88562701
public boolean isPossibleToRespawnInThis(BlockState state) {
return !state.isSolid() && !state.liquid();
-@@ -449,7 +510,7 @@ public class Block extends BlockBehaviour implements ItemLike {
+@@ -464,7 +525,7 @@ public class Block extends BlockBehaviour implements ItemLike {
}
public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
@@ -17847,10 +17916,10 @@ index d4cbff18adb62073a1dceb189043789620af6877..65504432a13df45e895cf6ca88562701
public void updateEntityAfterFallOn(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 d5654cfe37bd82f1290b280990a8502432491ae1..6425bc42bb8024aa7936b841d6c2ee2c892eb329 100644
+index 9a2de546dc2af2ad4bf5d32ca6583f0e1f3f70d8..3d48293c34fa37ba5091c6058dadb32a8f74a009 100644
--- a/src/main/java/net/minecraft/world/level/block/Blocks.java
+++ b/src/main/java/net/minecraft/world/level/block/Blocks.java
-@@ -1094,8 +1094,8 @@ public class Blocks {
+@@ -1145,8 +1145,8 @@ public class Blocks {
public static final Block CAVE_VINES = register("cave_vines", new CaveVinesBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).randomTicks().noCollission().lightLevel(CaveVines.emission(14)).instabreak().sound(SoundType.CAVE_VINES).pushReaction(PushReaction.DESTROY)));
public static final Block CAVE_VINES_PLANT = register("cave_vines_plant", new CaveVinesPlantBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).noCollission().lightLevel(CaveVines.emission(14)).instabreak().sound(SoundType.CAVE_VINES).pushReaction(PushReaction.DESTROY)));
public static final Block SPORE_BLOSSOM = register("spore_blossom", new SporeBlossomBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).instabreak().noCollission().sound(SoundType.SPORE_BLOSSOM).pushReaction(PushReaction.DESTROY)));
@@ -17861,7 +17930,7 @@ index d5654cfe37bd82f1290b280990a8502432491ae1..6425bc42bb8024aa7936b841d6c2ee2c
public static final Block MOSS_CARPET = register("moss_carpet", new CarpetBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_GREEN).strength(0.1F).sound(SoundType.MOSS_CARPET).pushReaction(PushReaction.DESTROY)));
public static final Block PINK_PETALS = register("pink_petals", new PinkPetalsBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).noCollission().sound(SoundType.PINK_PETALS).pushReaction(PushReaction.DESTROY)));
public static final Block MOSS_BLOCK = register("moss_block", new MossBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_GREEN).strength(0.1F).sound(SoundType.MOSS).pushReaction(PushReaction.DESTROY)));
-@@ -1160,7 +1160,7 @@ public class Blocks {
+@@ -1215,7 +1215,7 @@ public class Blocks {
}
private static Boolean ocelotOrParrot(BlockState state, BlockGetter world, BlockPos pos, EntityType> type) {
@@ -17869,12 +17938,12 @@ index d5654cfe37bd82f1290b280990a8502432491ae1..6425bc42bb8024aa7936b841d6c2ee2c
+ return type == EntityType.OCELOT || type == EntityType.PARROT; // Purpur - decompile error
}
- private static BedBlock bed(DyeColor color) {
+ private static Block bed(DyeColor color) {
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 03fde6e47c4a347c62fe9b4a3351769aedf874f6..ca906b0250e5332f7ececf1419ca6d2c1d385adc 100644
+index bed3d9c781c7d3ca260027b4737970889a54689c..db1941ed32d141327a8b11e54b3ff9900072ad36 100644
--- a/src/main/java/net/minecraft/world/level/block/BushBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java
-@@ -48,4 +48,24 @@ public class BushBlock extends Block {
+@@ -52,4 +52,24 @@ public abstract class BushBlock extends Block {
public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) {
return type == PathComputationType.AIR && !this.hasCollision ? true : super.isPathfindable(state, world, pos, type);
}
@@ -17900,19 +17969,19 @@ index 03fde6e47c4a347c62fe9b4a3351769aedf874f6..ca906b0250e5332f7ececf1419ca6d2c
+ // 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 0003fb51ae3a6575575e10b4c86719f3061e2577..fa6a2fbb8065b1f120750491b7e4b89542a6a891 100644
+index a9629a102c4fa4e5720e63fcf4590e9231426c62..a476f9a1eaa99b557962947149b6ee6ea3288d6e 100644
--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
-@@ -22,7 +22,7 @@ import net.minecraft.world.phys.shapes.CollisionContext;
+@@ -23,7 +23,7 @@ import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
-public class CactusBlock extends Block {
+public class CactusBlock extends Block implements BonemealableBlock { // Purpur
+ public static final MapCodec CODEC = simpleCodec(CactusBlock::new);
public static final IntegerProperty AGE = BlockStateProperties.AGE_15;
- public static final int MAX_AGE = 15;
-@@ -107,7 +107,7 @@ public class CactusBlock extends Block {
+@@ -114,7 +114,7 @@ public class CactusBlock extends Block {
enumdirection = (Direction) iterator.next();
iblockdata1 = world.getBlockState(pos.relative(enumdirection));
@@ -17921,7 +17990,7 @@ index 0003fb51ae3a6575575e10b4c86719f3061e2577..fa6a2fbb8065b1f120750491b7e4b895
return false;
}
-@@ -129,4 +129,34 @@ public class CactusBlock extends Block {
+@@ -136,4 +136,34 @@ public class CactusBlock extends Block {
public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) {
return false;
}
@@ -17957,10 +18026,10 @@ index 0003fb51ae3a6575575e10b4c86719f3061e2577..fa6a2fbb8065b1f120750491b7e4b895
+ // Purpur end
}
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 7700461b8cd0bde1bf6c0d5e4b73184bed1adc4e..cfa02b274286374c7555919d0e8d66a2c8fb8b88 100644
+index 7302d07c6ff69608e75ac52fdb19f2ec1d105129..35e2f279d358201384ff74fd767df18f6fda432b 100644
--- a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java
-@@ -123,7 +123,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB
+@@ -138,7 +138,7 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB
BlockPos blockposition = ctx.getClickedPos();
boolean flag = world.getFluidState(blockposition).getType() == Fluids.WATER;
@@ -17970,10 +18039,10 @@ index 7700461b8cd0bde1bf6c0d5e4b73184bed1adc4e..cfa02b274286374c7555919d0e8d66a2
@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 23c487e295b3b736d8800f0c884324c9b18a5373..ebeb7caf7fd4f45714bab0856a48b847a544cce7 100644
+index cdd7ab3fe589d089c0c03508721f46f6c136fc8a..6f148028c0fe503e9f6b327596d0954ce9e53269 100644
--- a/src/main/java/net/minecraft/world/level/block/CarvedPumpkinBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CarvedPumpkinBlock.java
-@@ -64,7 +64,7 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock {
+@@ -71,7 +71,7 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock {
SnowGolem entitysnowman = (SnowGolem) EntityType.SNOW_GOLEM.create(world);
if (entitysnowman != null) {
@@ -17982,7 +18051,7 @@ index 23c487e295b3b736d8800f0c884324c9b18a5373..ebeb7caf7fd4f45714bab0856a48b847
}
} else {
BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection1 = this.getOrCreateIronGolemFull().find(world, pos);
-@@ -74,7 +74,7 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock {
+@@ -81,7 +81,7 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock {
if (entityirongolem != null) {
entityirongolem.setPlayerCreated(true);
@@ -17991,7 +18060,7 @@ index 23c487e295b3b736d8800f0c884324c9b18a5373..ebeb7caf7fd4f45714bab0856a48b847
}
}
}
-@@ -82,6 +82,16 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock {
+@@ -89,6 +89,16 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock {
}
private static void spawnGolemInWorld(Level world, BlockPattern.BlockPatternMatch patternResult, Entity entity, BlockPos pos) {
@@ -18009,10 +18078,10 @@ index 23c487e295b3b736d8800f0c884324c9b18a5373..ebeb7caf7fd4f45714bab0856a48b847
entity.moveTo((double) pos.getX() + 0.5D, (double) pos.getY() + 0.05D, (double) pos.getZ() + 0.5D, 0.0F, 0.0F);
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java
-index 2f85b893dd0abc39fcedec65acc89e1567faf6f0..3ee012a9ef8cada0b2203e53b2f731f60f697cb1 100644
+index a821a981adbebdcf22997731b9bbea3d033cd2b1..028419d45c098baf5eab5d6e7a73189cb3e86622 100644
--- a/src/main/java/net/minecraft/world/level/block/CauldronBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CauldronBlock.java
-@@ -29,7 +29,7 @@ public class CauldronBlock extends AbstractCauldronBlock {
+@@ -36,7 +36,7 @@ public class CauldronBlock extends AbstractCauldronBlock {
}
protected static boolean shouldHandlePrecipitation(Level world, Biome.Precipitation precipitation) {
@@ -18022,10 +18091,10 @@ index 2f85b893dd0abc39fcedec65acc89e1567faf6f0..3ee012a9ef8cada0b2203e53b2f731f6
@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 ead7b37122c76d43af2cdd17af7f0da8014efb26..1acc2dcda68ec8e462d51927f2ea985e7952a830 100644
+index 54916c80720f219bf747250a2ff9a875f180c7a2..cae6d33728a39de9db908e1e24fdc3ad987d0542 100644
--- a/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java
-@@ -88,4 +88,11 @@ public class CaveVinesBlock extends GrowingPlantHeadBlock implements Bonemealabl
+@@ -94,4 +94,11 @@ public class CaveVinesBlock extends GrowingPlantHeadBlock implements Bonemealabl
public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
world.setBlock(pos, state.setValue(BERRIES, Boolean.valueOf(true)), 2);
}
@@ -18038,23 +18107,23 @@ index ead7b37122c76d43af2cdd17af7f0da8014efb26..1acc2dcda68ec8e462d51927f2ea985e
+ // Purpur end
}
diff --git a/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java b/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java
-index 8512b977b44a0a4d3a2521e27a60d65f7ac967be..dd270f67388c8663e0418875c88cb1e2a55d0635 100644
+index daae7fd6e0148cfba8e359d990748a0c83a3376e..0e06b1bcd906e92c083dc74d56d6d0a2a36f62a7 100644
--- a/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java
-@@ -65,7 +65,7 @@ public interface ChangeOverTimeBlock> {
+@@ -67,7 +67,7 @@ public interface ChangeOverTimeBlock> {
}
float f = (float) (k + 1) / (float) (k + j + 1);
- float f1 = f * f * this.getChanceModifier();
+ float f1 = world.purpurConfig.disableOxidationProximityPenalty ? this.getChanceModifier() : f * f * this.getChanceModifier(); // Purpur
- if (random.nextFloat() < f1) {
- this.getNext(state).ifPresent((iblockdata2) -> {
+ 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 af6e245b02d5fb78764d2db0ac200056277b212a..4ee31c5a6053237b15ddb8e3208cdb9a35a0d08d 100644
+index 9804ee2020e5cef23d3f5174d153fc149e611503..3a5e5cf88c5592e1bc3e6dc9eced2d1dd47bd145 100644
--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java
-@@ -355,6 +355,7 @@ public class ChestBlock extends AbstractChestBlock implements
+@@ -358,6 +358,7 @@ public class ChestBlock extends AbstractChestBlock