From af3b1442a9fa63b51f9b33adf7ac8e464811962e Mon Sep 17 00:00:00 2001 From: MrPowerGamerBR Date: Sun, 25 May 2025 20:23:19 -0300 Subject: [PATCH] Update to Paper 1.21.5 Not all patches are migrated yet, I'm commiting right now to avoid losing my progress This time I've moved the patches to file patches instead of feature patches, this DOES NOT include the parallel world ticking patch yet --- build.gradle.kts | 2 +- gradle.properties | 6 +- gradle/wrapper/gradle-wrapper.properties | 2 +- sparklypaper-api/build.gradle.kts.patch | 20 +- .../0001-SPARKLYPOWER-Add-custom-blocks.patch | 61 -- .../paper/MaterialTags.java.patch | 18 + .../advancement/AdvancementDisplay.java.patch | 11 - .../main/java/org/bukkit/Material.java.patch | 19 + sparklypaper-server/build.gradle.kts.patch | 41 +- .../0001-SparklyPaper-config-files.patch | 46 - ...ate-if-the-map-does-not-have-the-Cra.patch | 23 - ...ts-copy-when-requesting-player-stats.patch | 40 - .../0006-Blazingly-Simple-Farm-Checks.patch | 180 ---- .../0007-Spooky-month-optimizations.patch | 109 -- .../0008-Optimize-canSee-checks.patch | 19 - ...09-Fix-MC-117075-TE-Unload-Lag-Spike.patch | 39 - ...-Track-how-much-MSPT-each-world-used.patch | 44 - ...flag-when-loading-maps-from-the-disk.patch | 21 - .../0012-Helpful-NMS-packet-changes.patch | 144 --- .../0013-Add-CraftItemRecipeEvent.patch | 51 - ...d-PlayerMoveControllableVehicleEvent.patch | 42 - .../0016-Add-PlayerPreMoveEvent.patch | 86 -- .../0018-Parallel-world-ticking.patch | 967 ------------------ ...ap-SparklyPower-hacky-legacy-NBT-tag.patch | 19 - .../0020-SPARKLYPOWER-Add-custom-blocks.patch | 63 -- ...dd-EntityGetProjectileForWeaponEvent.patch | 40 - .../server/MinecraftServer.java.patch} | 41 +- .../dedicated/DedicatedServer.java.patch | 18 + .../server/level/ServerEntity.java.patch} | 16 +- .../server/level/ServerLevel.java.patch | 15 + .../ServerGamePacketListenerImpl.java.patch | 131 +++ .../world/entity/monster/Monster.java.patch | 15 + .../world/entity/player/Player.java.patch | 15 + .../minecraft/world/item/BowItem.java.patch} | 10 +- .../minecraft/world/level/Level.java.patch | 51 + .../world/level/block/Blocks.java.patch | 55 + .../world/level/block/CrafterBlock.java.patch | 15 + .../entity/HopperBlockEntity.java.patch} | 11 +- .../0002-SparklyPaper-config-files.patch | 61 -- ...rency-issues-when-using-imageToBytes.patch | 19 - .../0005-Optimize-canSee-checks.patch | 37 - .../0009-Parallel-world-ticking.patch | 628 ------------ .../paper/command/MSPTCommand.java.patch} | 10 +- .../EntityScheduler.java.patch} | 45 +- .../bukkit/craftbukkit/CraftServer.java.patch | 26 + .../org/bukkit/craftbukkit/Main.java.patch | 17 + .../craftbukkit/entity/CraftEntity.java.patch | 19 + .../event/CraftEventFactory.java.patch} | 16 +- .../util/CraftMagicNumbers.java.patch} | 21 +- .../craftbukkit/util/Versioning.java.patch | 11 + .../org/spigotmc/WatchdogThread.java.patch} | 30 +- .../craftbukkit/legacy/LegacyTest.java.patch} | 14 +- .../sparklypaper/LegacyNBTRemapper.kt | 95 -- .../ServerLevelTickExecutorThreadFactory.kt | 20 - 54 files changed, 516 insertions(+), 3059 deletions(-) delete mode 100644 sparklypaper-api/paper-patches/features/0001-SPARKLYPOWER-Add-custom-blocks.patch create mode 100644 sparklypaper-api/paper-patches/files/src/main/java/com/destroystokyo/paper/MaterialTags.java.patch delete mode 100644 sparklypaper-api/paper-patches/files/src/main/java/io/papermc/paper/advancement/AdvancementDisplay.java.patch create mode 100644 sparklypaper-api/paper-patches/files/src/main/java/org/bukkit/Material.java.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0001-SparklyPaper-config-files.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0003-Skip-MapItem-update-if-the-map-does-not-have-the-Cra.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0004-Skip-dirty-stats-copy-when-requesting-player-stats.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0006-Blazingly-Simple-Farm-Checks.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0007-Spooky-month-optimizations.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0008-Optimize-canSee-checks.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0009-Fix-MC-117075-TE-Unload-Lag-Spike.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0010-Track-how-much-MSPT-each-world-used.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0011-Reset-dirty-flag-when-loading-maps-from-the-disk.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0012-Helpful-NMS-packet-changes.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0013-Add-CraftItemRecipeEvent.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0015-Add-PlayerMoveControllableVehicleEvent.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0016-Add-PlayerPreMoveEvent.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0018-Parallel-world-ticking.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0019-SPARKLYPOWER-Remap-SparklyPower-hacky-legacy-NBT-tag.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0020-SPARKLYPOWER-Add-custom-blocks.patch delete mode 100644 sparklypaper-server/minecraft-patches/features/0021-Add-EntityGetProjectileForWeaponEvent.patch rename sparklypaper-server/minecraft-patches/{features/0005-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch => sources/net/minecraft/server/MinecraftServer.java.patch} (56%) create mode 100644 sparklypaper-server/minecraft-patches/sources/net/minecraft/server/dedicated/DedicatedServer.java.patch rename sparklypaper-server/minecraft-patches/{features/0002-Skip-distanceToSqr-call-in-ServerEntity-sendChanges-.patch => sources/net/minecraft/server/level/ServerEntity.java.patch} (53%) create mode 100644 sparklypaper-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch create mode 100644 sparklypaper-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch create mode 100644 sparklypaper-server/minecraft-patches/sources/net/minecraft/world/entity/monster/Monster.java.patch create mode 100644 sparklypaper-server/minecraft-patches/sources/net/minecraft/world/entity/player/Player.java.patch rename sparklypaper-server/minecraft-patches/{features/0017-Add-PreEntityShootBowEvent.patch => sources/net/minecraft/world/item/BowItem.java.patch} (67%) create mode 100644 sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch create mode 100644 sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/Blocks.java.patch create mode 100644 sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/CrafterBlock.java.patch rename sparklypaper-server/minecraft-patches/{features/0014-Allow-throttling-hopper-checks-if-the-target-contain.patch => sources/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch} (54%) delete mode 100644 sparklypaper-server/paper-patches/features/0002-SparklyPaper-config-files.patch delete mode 100644 sparklypaper-server/paper-patches/features/0003-Fix-concurrency-issues-when-using-imageToBytes.patch delete mode 100644 sparklypaper-server/paper-patches/features/0005-Optimize-canSee-checks.patch delete mode 100644 sparklypaper-server/paper-patches/features/0009-Parallel-world-ticking.patch rename sparklypaper-server/paper-patches/{features/0006-Track-how-much-MSPT-each-world-used.patch => files/src/main/java/io/papermc/paper/command/MSPTCommand.java.patch} (79%) rename sparklypaper-server/paper-patches/{features/0004-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch => files/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java.patch} (50%) create mode 100644 sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/CraftServer.java.patch create mode 100644 sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/Main.java.patch create mode 100644 sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java.patch rename sparklypaper-server/paper-patches/{features/0007-Add-CraftItemRecipeEvent.patch => files/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java.patch} (59%) rename sparklypaper-server/paper-patches/{features/0008-Allow-item-version-downgrades.patch => files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch} (60%) create mode 100644 sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/Versioning.java.patch rename sparklypaper-server/paper-patches/{features/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch => files/src/main/java/org/spigotmc/WatchdogThread.java.patch} (64%) rename sparklypaper-server/paper-patches/{features/0010-SPARKLYPOWER-Add-custom-blocks.patch => files/src/test/java/org/bukkit/craftbukkit/legacy/LegacyTest.java.patch} (53%) delete mode 100644 sparklypaper-server/src/main/kotlin/net/sparklypower/sparklypaper/LegacyNBTRemapper.kt delete mode 100644 sparklypaper-server/src/main/kotlin/net/sparklypower/sparklypaper/ServerLevelTickExecutorThreadFactory.kt diff --git a/build.gradle.kts b/build.gradle.kts index 28c5434..a0cf669 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,7 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent plugins { java // TODO java launcher tasks - id("io.papermc.paperweight.patcher") version "2.0.0-beta.14" + id("io.papermc.paperweight.patcher") version "2.0.0-beta.17" } paperweight { diff --git a/gradle.properties b/gradle.properties index 04bdca0..40020b2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ group=net.sparklypower.sparklypaper -version=1.21.4-R0.1-SNAPSHOT -mcVersion=1.21.4 -paperRef=09e9afd2952b44a922697bdfe795481b89334aba +version=1.21.5-R0.1-SNAPSHOT +mcVersion=1.21.5 +paperRef=a033e3b9ef78cfe85be807ac3fd1dd956274d4db org.gradle.configuration-cache=true org.gradle.caching=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cea7a79..002b867 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/sparklypaper-api/build.gradle.kts.patch b/sparklypaper-api/build.gradle.kts.patch index 0313e40..472465e 100644 --- a/sparklypaper-api/build.gradle.kts.patch +++ b/sparklypaper-api/build.gradle.kts.patch @@ -1,18 +1,18 @@ --- a/paper-api/build.gradle.kts +++ b/paper-api/build.gradle.kts -@@ -93,7 +_,7 @@ +@@ -90,7 +_,7 @@ testRuntimeOnly("org.junit.platform:junit-platform-launcher") } --val generatedApiPath: java.nio.file.Path = layout.projectDirectory.dir("src/generated/java").asFile.toPath() -+val generatedApiPath: java.nio.file.Path = rootProject.layout.projectDirectory.dir("paper-api/src/generated/java").asFile.toPath() +-val generatedDir: java.nio.file.Path = layout.projectDirectory.dir("src/generated/java").asFile.toPath() ++val generatedDir: java.nio.file.Path = rootProject.layout.projectDirectory.dir("paper-api/src/generated/java").asFile.toPath() idea { module { - generatedSourceDirs.add(generatedApiPath.toFile()) -@@ -103,6 +_,18 @@ + generatedSourceDirs.add(generatedDir.toFile()) +@@ -100,10 +_,21 @@ main { java { - srcDir(generatedApiPath) + srcDir(generatedDir) + srcDir(file("../paper-api/src/main/java")) + } + resources { @@ -28,7 +28,11 @@ } } } -@@ -169,7 +_,7 @@ +- + val outgoingVariants = arrayOf("runtimeElements", "apiElements", "sourcesElements", "javadocElements") + val mainCapability = "${project.group}:${project.name}:${project.version}" + configurations { +@@ -166,7 +_,7 @@ tasks.withType { val options = options as StandardJavadocDocletOptions @@ -37,7 +41,7 @@ options.use() options.isDocFilesSubDirs = true options.links( -@@ -202,11 +_,11 @@ +@@ -199,11 +_,11 @@ } // workaround for https://github.com/gradle/gradle/issues/4046 diff --git a/sparklypaper-api/paper-patches/features/0001-SPARKLYPOWER-Add-custom-blocks.patch b/sparklypaper-api/paper-patches/features/0001-SPARKLYPOWER-Add-custom-blocks.patch deleted file mode 100644 index 81212d3..0000000 --- a/sparklypaper-api/paper-patches/features/0001-SPARKLYPOWER-Add-custom-blocks.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Wed, 12 Jun 2024 11:53:27 -0300 -Subject: [PATCH] SPARKLYPOWER Add custom blocks - - -diff --git a/src/main/java/com/destroystokyo/paper/MaterialTags.java b/src/main/java/com/destroystokyo/paper/MaterialTags.java -index 679f78e07a3a2de745fa237165d0a8db5e086f29..a083aac89cbe397545f34f0e9312fc8fb66dec85 100644 ---- a/src/main/java/com/destroystokyo/paper/MaterialTags.java -+++ b/src/main/java/com/destroystokyo/paper/MaterialTags.java -@@ -83,6 +83,7 @@ public class MaterialTags { - */ - public static final MaterialSetTag CONCRETES = new MaterialSetTag(keyFor("concretes")) - .endsWith("_CONCRETE") -+ .notStartsWith("SPARKLYPOWER_") // SparklyPaper - custom blocks - .ensureSize("CONCRETES", 16).lock(); - - /** -@@ -161,6 +162,7 @@ public class MaterialTags { - .endsWith("TERRACOTTA") - .not(Material.TERRACOTTA) - .notEndsWith("GLAZED_TERRACOTTA") -+ .notStartsWith("SPARKLYPOWER_") // SparklyPaper - custom blocks - .ensureSize("STAINED_TERRACOTTA", 16).lock(); - - /** -@@ -168,6 +170,7 @@ public class MaterialTags { - */ - public static final MaterialSetTag TERRACOTTA = new MaterialSetTag(keyFor("terracotta")) - .endsWith("TERRACOTTA") -+ .notStartsWith("SPARKLYPOWER_") // SparklyPaper - custom blocks - .ensureSize("TERRACOTTA", 33).lock(); - - /** -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 9afafc00e457c721a1b20b05c6a5d330caa40dfb..34049b57f5e481e3e8a3eb22cc73dcfda39c6116 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -3814,6 +3814,22 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla - POTTED_FLOWERING_AZALEA_BUSH(10609), - POTTED_OPEN_EYEBLOSSOM(24999), - POTTED_CLOSED_EYEBLOSSOM(16694), -+ // SparklyPaper start - SparklyPower Survival custom blocks -+ // The IDs themselves doesn't have any correlation with anything, Spigot invented that for backwards compatibility -+ SPARKLYPOWER_RAINBOW_WOOL(13003), -+ SPARKLYPOWER_RAINBOW_CONCRETE(13004), -+ SPARKLYPOWER_RAINBOW_TERRACOTTA(13005), -+ SPARKLYPOWER_ASPHALT_SERVER(13006), -+ /** -+ * BlockData: {@link Slab} -+ */ -+ SPARKLYPOWER_ASPHALT_SERVER_SLAB(13007, Slab.class), -+ SPARKLYPOWER_ASPHALT_PLAYER(13008), -+ /** -+ * BlockData: {@link Slab} -+ */ -+ SPARKLYPOWER_ASPHALT_PLAYER_SLAB(13009, Slab.class), -+ // SparklyPaper end - // ----- Legacy Separator ----- - @Deprecated(since = "1.13") - LEGACY_AIR(0, 0), diff --git a/sparklypaper-api/paper-patches/files/src/main/java/com/destroystokyo/paper/MaterialTags.java.patch b/sparklypaper-api/paper-patches/files/src/main/java/com/destroystokyo/paper/MaterialTags.java.patch new file mode 100644 index 0000000..80cdb0b --- /dev/null +++ b/sparklypaper-api/paper-patches/files/src/main/java/com/destroystokyo/paper/MaterialTags.java.patch @@ -0,0 +1,18 @@ +--- a/src/main/java/com/destroystokyo/paper/MaterialTags.java ++++ b/src/main/java/com/destroystokyo/paper/MaterialTags.java +@@ -83,6 +_,7 @@ + */ + public static final MaterialSetTag CONCRETES = new MaterialSetTag(keyFor("concretes")) + .endsWith("_CONCRETE") ++ .notStartsWith("SPARKLYPOWER_") // SparklyPaper - custom blocks + .ensureSize("CONCRETES", 16).lock(); + + /** +@@ -152,6 +_,7 @@ + */ + public static final MaterialSetTag GLAZED_TERRACOTTA = new MaterialSetTag(keyFor("glazed_terracotta")) + .endsWith("GLAZED_TERRACOTTA") ++ .notStartsWith("SPARKLYPOWER_") // SparklyPaper - custom blocks + .ensureSize("GLAZED_TERRACOTTA", 16).lock(); + + /** diff --git a/sparklypaper-api/paper-patches/files/src/main/java/io/papermc/paper/advancement/AdvancementDisplay.java.patch b/sparklypaper-api/paper-patches/files/src/main/java/io/papermc/paper/advancement/AdvancementDisplay.java.patch deleted file mode 100644 index 2bf7c4b..0000000 --- a/sparklypaper-api/paper-patches/files/src/main/java/io/papermc/paper/advancement/AdvancementDisplay.java.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/src/main/java/io/papermc/paper/advancement/AdvancementDisplay.java -+++ b/src/main/java/io/papermc/paper/advancement/AdvancementDisplay.java -@@ -27,7 +_,7 @@ - * - * @return the frame type - */ -- Frame frame(); -+ Frame frame(); // patch - - /** - * Gets the advancement title. diff --git a/sparklypaper-api/paper-patches/files/src/main/java/org/bukkit/Material.java.patch b/sparklypaper-api/paper-patches/files/src/main/java/org/bukkit/Material.java.patch new file mode 100644 index 0000000..a863ad6 --- /dev/null +++ b/sparklypaper-api/paper-patches/files/src/main/java/org/bukkit/Material.java.patch @@ -0,0 +1,19 @@ +--- a/src/main/java/org/bukkit/Material.java ++++ b/src/main/java/org/bukkit/Material.java +@@ -1697,6 +_,16 @@ + ZOMBIE_HEAD(-1, Skull.class), + ZOMBIE_WALL_HEAD(-1, WallSkull.class), + // End generate - Blocks ++ // SparklyPaper start - SparklyPower Survival custom blocks ++ // The IDs themselves doesn't have any correlation with anything, Spigot invented that for backwards compatibility ++ SPARKLYPOWER_RAINBOW_WOOL(-1), ++ SPARKLYPOWER_RAINBOW_CONCRETE(-1), ++ SPARKLYPOWER_RAINBOW_TERRACOTTA(-1), ++ SPARKLYPOWER_ASPHALT_SERVER(-1), ++ SPARKLYPOWER_ASPHALT_SERVER_SLAB(-1, Slab.class), ++ SPARKLYPOWER_ASPHALT_PLAYER(-1), ++ SPARKLYPOWER_ASPHALT_PLAYER_SLAB(-1, Slab.class), ++ // SparklyPaper end + // ----- Legacy Separator ----- + @Deprecated(since = "1.13", forRemoval = true) + LEGACY_AIR(0, 0), diff --git a/sparklypaper-server/build.gradle.kts.patch b/sparklypaper-server/build.gradle.kts.patch index ee2f975..7bc31ef 100644 --- a/sparklypaper-server/build.gradle.kts.patch +++ b/sparklypaper-server/build.gradle.kts.patch @@ -1,17 +1,17 @@ --- a/paper-server/build.gradle.kts +++ b/paper-server/build.gradle.kts -@@ -4,6 +_,8 @@ +@@ -7,6 +_,8 @@ plugins { `java-library` -+ kotlin("jvm") version "2.0.0" -+ kotlin("plugin.serialization") version "2.0.0" ++ kotlin("jvm") version "2.1.21" ++ kotlin("plugin.serialization") version "2.1.21" `maven-publish` + idea id("io.papermc.paperweight.core") - } -@@ -21,6 +_,17 @@ - // macheOldPath = file("F:\\Projects\\PaperTooling\\mache\\versions\\1.21.4\\src\\main\\java") - // gitFilePatches = true +@@ -24,6 +_,17 @@ + minecraftVersion = providers.gradleProperty("mcVersion") + gitFilePatches = false + val fork = forks.register("sparklypaper") { + upstream.patchDir("paperServer") { @@ -24,10 +24,10 @@ + + activeFork = fork + - spigot { - buildDataRef = "3edaf46ec1eed4115ce1b18d2846cded42577e42" - packageVersion = "v1_21_R3" // also needs to be updated in MappingEnvironment -@@ -101,7 +_,20 @@ + //updatingMinecraft { + // oldPaperCommit = "f4f275519f7c1fbe9db173b7144a4fe81440e365" + //} +@@ -108,7 +_,20 @@ } } @@ -49,7 +49,7 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { extendsFrom(configurations.compileClasspath.get()) } -@@ -119,7 +_,12 @@ +@@ -130,7 +_,12 @@ } dependencies { @@ -57,13 +57,13 @@ + // SparklyPaper start + implementation(project(":sparklypaper-api")) + implementation(kotlin("reflect")) -+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") -+ implementation("com.charleskorn.kaml:kaml:0.55.0") ++ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1") ++ implementation("com.charleskorn.kaml:kaml:0.78.0") + // SparklyPaper end implementation("ca.spottedleaf:concurrentutil:0.0.3") implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+ implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21 -@@ -184,9 +_,14 @@ +@@ -201,9 +_,14 @@ val build = System.getenv("BUILD_NUMBER") ?: null val buildTime = if (build != null) Instant.now() else Instant.EPOCH val gitHash = git.exec(providers, "rev-parse", "--short=7", "HEAD").get().trim() @@ -79,7 +79,7 @@ attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", "Implementation-Title" to "Paper", -@@ -195,8 +_,8 @@ +@@ -212,8 +_,8 @@ "Specification-Title" to "Paper", "Specification-Version" to project.version, "Specification-Vendor" to "Paper Team", @@ -90,3 +90,12 @@ "Build-Number" to (build ?: ""), "Build-Time" to buildTime.toString(), "Git-Branch" to gitBranch, +@@ -267,7 +_,7 @@ + jvmArgumentProviders.add(provider) + } + +-val generatedDir: java.nio.file.Path = layout.projectDirectory.dir("src/generated/java").asFile.toPath() ++val generatedDir: java.nio.file.Path = rootProject.layout.projectDirectory.dir("paper-server/src/generated/java").asFile.toPath() + idea { + module { + generatedSourceDirs.add(generatedDir.toFile()) diff --git a/sparklypaper-server/minecraft-patches/features/0001-SparklyPaper-config-files.patch b/sparklypaper-server/minecraft-patches/features/0001-SparklyPaper-config-files.patch deleted file mode 100644 index eda3f80..0000000 --- a/sparklypaper-server/minecraft-patches/features/0001-SparklyPaper-config-files.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 13 Jan 2025 13:20:31 -0300 -Subject: [PATCH] SparklyPaper config files - - -diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 97a294d2f5c1ddf0af7ffec3e1425eb329c5751b..4c420e17d936132bb4569776911757fd959e93d6 100644 ---- a/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -224,6 +224,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command - this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark - com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics -+ // SparklyPaper start -+ try { -+ net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.init((java.io.File) options.valueOf("sparklypaper-settings")); -+ } catch (Exception e) { -+ DedicatedServer.LOGGER.error("Unable to load server configuration", e); -+ return false; -+ } -+ net.sparklypower.sparklypaper.SparklyPaperCommands.INSTANCE.registerCommands(this); -+ // SparklyPaper end - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now - - this.setPvpAllowed(properties.pvp); -diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 2bbebb4335d927f240abcac67a5b423e38dc33d7..27c2ea4a387ee5f7d078a42cb57f146cb748501d 100644 ---- a/net/minecraft/world/level/Level.java -+++ b/net/minecraft/world/level/Level.java -@@ -170,6 +170,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - // Paper end - add paper world config - - public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray -+ public net.sparklypower.sparklypaper.configs.SparklyPaperConfig.SparklyPaperWorldConfig sparklyPaperConfig; // SparklyPaper - public static BlockPos lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; -@@ -853,6 +854,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - // Paper end - getblock optimisations - cache world height/sections - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot - this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config -+ this.sparklyPaperConfig = net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.getWorldSettings(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // SparklyPaper - this.generator = gen; - this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); - diff --git a/sparklypaper-server/minecraft-patches/features/0003-Skip-MapItem-update-if-the-map-does-not-have-the-Cra.patch b/sparklypaper-server/minecraft-patches/features/0003-Skip-MapItem-update-if-the-map-does-not-have-the-Cra.patch deleted file mode 100644 index f109c18..0000000 --- a/sparklypaper-server/minecraft-patches/features/0003-Skip-MapItem-update-if-the-map-does-not-have-the-Cra.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Fri, 17 Nov 2023 14:22:41 -0300 -Subject: [PATCH] Skip "MapItem#update()" if the map does not have the - CraftMapRenderer present - -Optimizes "image in map" maps, without requiring the map to be locked, which some old map plugins may not do - -This has the disadvantage that the vanilla map data will never be updated while the CraftMapRenderer is not present, but that's not a huuuge problem for us - -diff --git a/net/minecraft/world/item/MapItem.java b/net/minecraft/world/item/MapItem.java -index 8795d54cff569c911e0a535f38a0ec4130f7b4d5..31960e54bf5ed4aa31cd12b60ab0fa263902ce2c 100644 ---- a/net/minecraft/world/item/MapItem.java -+++ b/net/minecraft/world/item/MapItem.java -@@ -277,7 +277,7 @@ public class MapItem extends Item { - savedData.tickCarriedBy(player, stack); - } - -- if (!savedData.locked && (isSelected || entity instanceof Player && ((Player)entity).getOffhandItem() == stack)) { -+ if (!savedData.locked && (!level.sparklyPaperConfig.getSkipMapItemDataUpdatesIfMapDoesNotHaveCraftMapRenderer() || savedData.mapView.getRenderers().stream().anyMatch(mapRenderer -> mapRenderer.getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class)) && (isSelected || entity instanceof Player && ((Player)entity).getOffhandItem() == stack)) { // SparklyPaper - don't update maps if they don't have the CraftMapRenderer in the render list - this.update(level, entity, savedData); - } - } diff --git a/sparklypaper-server/minecraft-patches/features/0004-Skip-dirty-stats-copy-when-requesting-player-stats.patch b/sparklypaper-server/minecraft-patches/features/0004-Skip-dirty-stats-copy-when-requesting-player-stats.patch deleted file mode 100644 index aab45ae..0000000 --- a/sparklypaper-server/minecraft-patches/features/0004-Skip-dirty-stats-copy-when-requesting-player-stats.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 13 Jan 2025 14:32:08 -0300 -Subject: [PATCH] Skip dirty stats copy when requesting player stats - - -diff --git a/net/minecraft/stats/ServerStatsCounter.java b/net/minecraft/stats/ServerStatsCounter.java -index 6c5205fe1dc6387a77b1edbdcab748d39e775d7f..c6e4a7668ed923d93bd7f67d19af82d5d84a0dc0 100644 ---- a/net/minecraft/stats/ServerStatsCounter.java -+++ b/net/minecraft/stats/ServerStatsCounter.java -@@ -81,11 +81,15 @@ public class ServerStatsCounter extends StatsCounter { - this.dirty.add(stat); - } - -+ // SparklyPaper start - Skip dirty stats copy when requesting player stats -+ /* - private Set> getDirty() { - Set> set = Sets.newHashSet(this.dirty); - this.dirty.clear(); - return set; - } -+ */ -+ // SparklyPaper end - - public void parseLocal(DataFixer fixerUpper, String json) { - try { -@@ -190,10 +194,12 @@ public class ServerStatsCounter extends StatsCounter { - public void sendStats(ServerPlayer player) { - Object2IntMap> map = new Object2IntOpenHashMap<>(); - -- for (Stat stat : this.getDirty()) { -+ for (Stat stat : this.dirty) { // SparklyPaper - Skip dirty stats copy when requesting player stats - map.put(stat, this.getValue(stat)); - } - -+ this.dirty.clear(); // SparklyPaper - Skip dirty stats copy when requesting player stats -+ - player.connection.send(new ClientboundAwardStatsPacket(map)); - } - } diff --git a/sparklypaper-server/minecraft-patches/features/0006-Blazingly-Simple-Farm-Checks.patch b/sparklypaper-server/minecraft-patches/features/0006-Blazingly-Simple-Farm-Checks.patch deleted file mode 100644 index 372b6cf..0000000 --- a/sparklypaper-server/minecraft-patches/features/0006-Blazingly-Simple-Farm-Checks.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 13 Jan 2025 14:50:47 -0300 -Subject: [PATCH] Blazingly Simple Farm Checks - - -diff --git a/net/minecraft/world/level/block/CropBlock.java b/net/minecraft/world/level/block/CropBlock.java -index bc0969f40814094e42a860a72314fccd1a66fabe..c14de811ae7cead820a00a87b9d2ce8cfb241d92 100644 ---- a/net/minecraft/world/level/block/CropBlock.java -+++ b/net/minecraft/world/level/block/CropBlock.java -@@ -87,6 +87,57 @@ public class CropBlock extends BushBlock implements BonemealableBlock { - if (level.getRawBrightness(pos, 0) >= 9) { - int age = this.getAge(state); - if (age < this.getMaxAge()) { -+ // SparklyPaper start - Blazingly simple farm checks -+ if (level.sparklyPaperConfig.getBlazinglySimpleFarmChecks().getEnabled()) { -+ // These checks are similar to getGrowthSpeed, but we have "inlined" them because we want to access stuff like the farm block data later on -+ // Is the block below us moisturised? -+ BlockPos farmlandBelowTheCurrentBlock = pos.below(); -+ BlockState farmlandBelowTheCurrentBlockData = level.getBlockState(farmlandBelowTheCurrentBlock); -+ float f = level.sparklyPaperConfig.getBlazinglySimpleFarmChecks().getDefaultGrowthSpeed(); -+ boolean isCurrentFarmlandStateMoist = false; -+ if (farmlandBelowTheCurrentBlockData.is(Blocks.FARMLAND)) { -+ if ((Integer) farmlandBelowTheCurrentBlockData.getValue(FarmBlock.MOISTURE) > 0) { -+ // If we are currently moist, increase the speed! -+ f = level.sparklyPaperConfig.getBlazinglySimpleFarmChecks().getMoistGrowthSpeed(); -+ isCurrentFarmlandStateMoist = true; -+ } -+ } -+ // If we are skipping the middle aging stages, we need to change the growth speed and the next stage accordingly -+ if (level.sparklyPaperConfig.getBlazinglySimpleFarmChecks().getSkipMiddleAgingStagesForCrops()) { -+ f = f / getMaxAge(); -+ age = getMaxAge() - 1; -+ } -+ -+ // Spigot start -+ int modifier; -+ if (this == Blocks.BEETROOTS) { -+ modifier = level.spigotConfig.beetrootModifier; -+ } else if (this == Blocks.CARROTS) { -+ modifier = level.spigotConfig.carrotModifier; -+ } else if (this == Blocks.POTATOES) { -+ modifier = level.spigotConfig.potatoModifier; -+ // Paper start -+ } else if (this == Blocks.TORCHFLOWER_CROP) { -+ modifier = level.spigotConfig.torchFlowerModifier; -+ // Paper end -+ } else { -+ modifier = level.spigotConfig.wheatModifier; -+ } -+ -+ if (random.nextFloat() < (modifier / (100.0f * (Math.floor((25.0F / f) + 1))))) { // Spigot - SPIGOT-7159: Better modifier resolution -+ // Spigot end -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(age + 1), 2)) { -+ return; -+ } -+ -+ // Now that we know that the crop will grow... is the next stage the crop's max age? If yes, we are going to check if the farm land is moist! -+ if (age + 1 == getMaxAge() && isCurrentFarmlandStateMoist && !FarmBlock.isNearWater(level, farmlandBelowTheCurrentBlock)) { -+ // Whoops, farm land ain't moist! -+ // From FarmBlock, set the moisture to 0 -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, farmlandBelowTheCurrentBlock, (BlockState) farmlandBelowTheCurrentBlockData.setValue(FarmBlock.MOISTURE, 0), 2); // CraftBukkit -+ } -+ } -+ } else { - float growthSpeed = getGrowthSpeed(this, level, pos); - // Spigot start - int modifier = 100; -@@ -108,6 +159,8 @@ public class CropBlock extends BushBlock implements BonemealableBlock { - // Spigot end - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, this.getStateForAge(age + 1), 2); // CraftBukkit - } -+ } -+ // SparklyPaper end - } - } - } -diff --git a/net/minecraft/world/level/block/FarmBlock.java b/net/minecraft/world/level/block/FarmBlock.java -index 1fdede769b67cb5d2f9159c779f19e3639bb6ff5..1de42b2be50a5704a80c6cacc9e2cd82d0959bd6 100644 ---- a/net/minecraft/world/level/block/FarmBlock.java -+++ b/net/minecraft/world/level/block/FarmBlock.java -@@ -95,6 +95,19 @@ public class FarmBlock extends Block { - @Override - protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { - int moistureValue = state.getValue(MOISTURE); -+ // SparklyPaper start - Blazingly simple farm checks -+ if (level.sparklyPaperConfig.getBlazinglySimpleFarmChecks().getEnabled()) { -+ if (moistureValue == 0) { // We only care about non-moisturised farm blocks -+ if (FarmBlock.isNearWater(level, pos)) { -+ // Make it MOIST! -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, pos, (BlockState) state.setValue(FarmBlock.MOISTURE, 7), 2); // CraftBukkit -+ } else if (!FarmBlock.shouldMaintainFarmland(level, pos)) { -+ FarmBlock.turnToDirt((Entity) null, state, level, pos); -+ } -+ } -+ return; -+ } -+ // SparklyPaper end - if (moistureValue > 0 && level.paperConfig().tickRates.wetFarmland != 1 && (level.paperConfig().tickRates.wetFarmland < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % level.paperConfig().tickRates.wetFarmland != 0)) { return; } // Paper - Configurable random tick rates for blocks - if (moistureValue == 0 && level.paperConfig().tickRates.dryFarmland != 1 && (level.paperConfig().tickRates.dryFarmland < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % level.paperConfig().tickRates.dryFarmland != 0)) { return; } // Paper - Configurable random tick rates for blocks - if (!isNearWater(level, pos) && !level.isRainingAt(pos.above())) { -@@ -157,7 +170,7 @@ public class FarmBlock extends Block { - return level.getBlockState(pos.above()).is(BlockTags.MAINTAINS_FARMLAND); - } - -- private static boolean isNearWater(LevelReader level, BlockPos pos) { -+ public static boolean isNearWater(LevelReader level, BlockPos pos) { // SparklyPaper - make public for the Blazingly simple farm checks - // Paper start - Perf: remove abstract block iteration - int xOff = pos.getX(); - int yOff = pos.getY(); -diff --git a/net/minecraft/world/level/block/StemBlock.java b/net/minecraft/world/level/block/StemBlock.java -index 3dca57dd0c00dc64724cbc7f5a71963da9d12fd5..9839821365484bac93023b1aa542619dae4c88cf 100644 ---- a/net/minecraft/world/level/block/StemBlock.java -+++ b/net/minecraft/world/level/block/StemBlock.java -@@ -79,6 +79,56 @@ public class StemBlock extends BushBlock implements BonemealableBlock { - @Override - protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { - if (level.getRawBrightness(pos, 0) >= 9) { -+ // SparklyPaper start - Blazingly simple farm checks -+ if (level.sparklyPaperConfig.getBlazinglySimpleFarmChecks().getEnabled()) { -+ // These checks are similar to getGrowthSpeed, but we have "inlined" them because we want to access stuff like the farm block data later on -+ // Is the block below us moisturised? -+ BlockPos farmlandBelowTheCurrentBlock = pos.below(); -+ BlockState farmlandBelowTheCurrentBlockData = level.getBlockState(farmlandBelowTheCurrentBlock); -+ float f = level.sparklyPaperConfig.getBlazinglySimpleFarmChecks().getDefaultGrowthSpeed(); -+ boolean isCurrentFarmlandStateMoist = false; -+ if (farmlandBelowTheCurrentBlockData.is(Blocks.FARMLAND)) { -+ if ((Integer) farmlandBelowTheCurrentBlockData.getValue(FarmBlock.MOISTURE) > 0) { -+ // If we are currently moist, increase the speed! -+ f = level.sparklyPaperConfig.getBlazinglySimpleFarmChecks().getMoistGrowthSpeed(); -+ isCurrentFarmlandStateMoist = true; -+ } -+ } -+ -+ if (random.nextFloat() < ((this == Blocks.PUMPKIN_STEM ? level.spigotConfig.pumpkinModifier : level.spigotConfig.melonModifier) / (100.0f * (Math.floor((25.0F / f) + 1))))) { // Spigot - SPIGOT-7159: Better modifier resolution -+ int i = (Integer) state.getValue(StemBlock.AGE); -+ -+ if (i < 7) { -+ state = (BlockState) state.setValue(StemBlock.AGE, i + 1); -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit -+ } else { -+ Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random); -+ BlockPos blockposition1 = pos.relative(enumdirection); -+ BlockState iblockdata1 = level.getBlockState(blockposition1.below()); -+ -+ if (level.getBlockState(blockposition1).isAir() && (iblockdata1.is(Blocks.FARMLAND) || iblockdata1.is(BlockTags.DIRT))) { -+ Registry iregistry = net.minecraft.core.registries.BuiltInRegistries.BLOCK; -+ Optional optional = iregistry.getOptional(this.fruit); -+ Optional optional1 = iregistry.getOptional(this.attachedStem); -+ -+ if (optional.isPresent() && optional1.isPresent()) { -+ // CraftBukkit start -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, blockposition1, ((Block) optional.get()).defaultBlockState())) { -+ return; -+ } -+ // CraftBukkit end -+ // Now that we know that the crop will grow... is the next stage the crop's max age? If yes, we are going to check if the farm land is moist! -+ if (isCurrentFarmlandStateMoist && !FarmBlock.isNearWater(level, farmlandBelowTheCurrentBlock)) { -+ // Whoops, farm land ain't moist! -+ // From FarmBlock, set the moisture to 0 -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(level, farmlandBelowTheCurrentBlock, (BlockState) farmlandBelowTheCurrentBlockData.setValue(FarmBlock.MOISTURE, 0), 2); // CraftBukkit -+ } -+ level.setBlockAndUpdate(pos, (BlockState) ((Block) optional1.get()).defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, enumdirection)); -+ } -+ } -+ } -+ } -+ } else { - float growthSpeed = CropBlock.getGrowthSpeed(this, level, pos); - if (random.nextFloat() < ((this == Blocks.PUMPKIN_STEM ? level.spigotConfig.pumpkinModifier : level.spigotConfig.melonModifier) / (100.0f * (Math.floor((25.0F / growthSpeed) + 1))))) { // Spigot - SPIGOT-7159: Better modifier resolution - int ageValue = state.getValue(AGE); -@@ -105,6 +155,8 @@ public class StemBlock extends BushBlock implements BonemealableBlock { - } - } - } -+ } -+ // SparklyPaper end - } - - @Override diff --git a/sparklypaper-server/minecraft-patches/features/0007-Spooky-month-optimizations.patch b/sparklypaper-server/minecraft-patches/features/0007-Spooky-month-optimizations.patch deleted file mode 100644 index 5826479..0000000 --- a/sparklypaper-server/minecraft-patches/features/0007-Spooky-month-optimizations.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Tue, 21 Nov 2023 16:50:04 -0300 -Subject: [PATCH] Spooky month optimizations - -The quintessential patch that other performance forks also have for... some reason??? I thought that this optimization was too funny to not do it in SparklyPaper. - -Caches when Bat's spooky season starts and ends, and when Skeleton and Zombies halloween starts and ends. The epoch is updated every 90 days. If your server is running for 90+ days straight without restarts, congratulations! - -Avoids unnecessary date checks, even tho that this shouldn't really improve performance that much... unless you have a lot of bats/zombies/skeletons spawning. - -diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 6ad6bfe60026be304aa2178d5f04a79531cc66a6..4dbf2d9aa52029122f4816ca3504fa330b28a29b 100644 ---- a/net/minecraft/server/MinecraftServer.java -+++ b/net/minecraft/server/MinecraftServer.java -@@ -304,6 +304,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping - public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation - public final Set entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (concurrent because plugins may schedule tasks async) -+ public net.sparklypower.sparklypaper.HalloweenManager halloweenManager = new net.sparklypower.sparklypaper.HalloweenManager(); // SparklyPaper - Spooky month optimizations - - public static S spin(Function threadFunction) { - ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system -diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 4c420e17d936132bb4569776911757fd959e93d6..6ac73610f6039290c4ef3dde2206b6863d2b5067 100644 ---- a/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -233,6 +233,10 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - } - net.sparklypower.sparklypaper.SparklyPaperCommands.INSTANCE.registerCommands(this); - // SparklyPaper end -+ // SparklyPaper start - Spooky month optimizations -+ halloweenManager.startHalloweenEpochTask(); -+ halloweenManager.waitUntilEpochHasBeenUpdated(); -+ // SparklyPaper end - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now - - this.setPvpAllowed(properties.pvp); -diff --git a/net/minecraft/world/entity/ambient/Bat.java b/net/minecraft/world/entity/ambient/Bat.java -index 5ebe7b1dce367d5c5e1136b97b2b9f6737595201..b003fa86fab9a6106c9875205d73e49e46904498 100644 ---- a/net/minecraft/world/entity/ambient/Bat.java -+++ b/net/minecraft/world/entity/ambient/Bat.java -@@ -231,7 +231,7 @@ public class Bat extends AmbientCreature { - } else { - int maxLocalRawBrightness = level.getMaxLocalRawBrightness(pos); - int i = 4; -- if (isHalloween()) { -+ if (level.getServer().halloweenManager.isSpookySeason()) { - i = 7; - } else if (randomSource.nextBoolean()) { - return false; -@@ -243,12 +243,15 @@ public class Bat extends AmbientCreature { - } - } - -+ // SparklyPaper - Spooky month optimizations -+ /* - private static boolean isHalloween() { - LocalDate localDate = LocalDate.now(); - int i = localDate.get(ChronoField.DAY_OF_MONTH); - int i1 = localDate.get(ChronoField.MONTH_OF_YEAR); - return i1 == 10 && i >= 20 || i1 == 11 && i <= 3; - } -+ */ - - private void setupAnimationStates() { - if (this.isResting()) { -diff --git a/net/minecraft/world/entity/monster/AbstractSkeleton.java b/net/minecraft/world/entity/monster/AbstractSkeleton.java -index 37abc7769573e3cdda380166dd086551d5e7bd88..be623fd09ca573922297d3af3cd114160ec05061 100644 ---- a/net/minecraft/world/entity/monster/AbstractSkeleton.java -+++ b/net/minecraft/world/entity/monster/AbstractSkeleton.java -@@ -158,10 +158,12 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo - this.reassessWeaponGoal(); - this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper - Add world settings for mobs picking up loot - if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { -- LocalDate localDate = LocalDate.now(); -- int i = localDate.get(ChronoField.DAY_OF_MONTH); -- int i1 = localDate.get(ChronoField.MONTH_OF_YEAR); -- if (i1 == 10 && i == 31 && random.nextFloat() < 0.25F) { -+ // SparklyPaper start - Spooky month optimizations -+ // LocalDate localDate = LocalDate.now(); -+ // int i = localDate.get(ChronoField.DAY_OF_MONTH); -+ // int i1 = localDate.get(ChronoField.MONTH_OF_YEAR); -+ if (this.getServer().halloweenManager.isHalloween() /* i1 == 10 && i == 31 */&& random.nextFloat() < 0.25F) { -+ // SparklyPaper end - this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); - this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; - } -diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java -index 637790ff833abaa0c52fdee204abba7077d12ccc..600b96d4b2645e26fd690ac70d3901d567b7bc24 100644 ---- a/net/minecraft/world/entity/monster/Zombie.java -+++ b/net/minecraft/world/entity/monster/Zombie.java -@@ -550,10 +550,12 @@ public class Zombie extends Monster { - } - - if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { -- LocalDate localDate = LocalDate.now(); -- int i = localDate.get(ChronoField.DAY_OF_MONTH); -- int i1 = localDate.get(ChronoField.MONTH_OF_YEAR); -- if (i1 == 10 && i == 31 && random.nextFloat() < 0.25F) { -+ // SparklyPaper start - Spooky month optimizations -+ // LocalDate localDate = LocalDate.now(); -+ // int i = localDate.get(ChronoField.DAY_OF_MONTH); -+ // int i1 = localDate.get(ChronoField.MONTH_OF_YEAR); -+ if (this.getServer().halloweenManager.isHalloween() /* i1 == 10 && i == 31 */&& random.nextFloat() < 0.25F) { -+ // SparklyPaper end - this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); - this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; - } diff --git a/sparklypaper-server/minecraft-patches/features/0008-Optimize-canSee-checks.patch b/sparklypaper-server/minecraft-patches/features/0008-Optimize-canSee-checks.patch deleted file mode 100644 index 2b31d7a..0000000 --- a/sparklypaper-server/minecraft-patches/features/0008-Optimize-canSee-checks.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 13 Jan 2025 15:03:52 -0300 -Subject: [PATCH] Optimize canSee checks - - -diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index b3f498558614243cf633dcd71e3c49c2c55e6e0f..ad9ab7fe6df3880c730388a50741b7938b037ff2 100644 ---- a/net/minecraft/server/level/ChunkMap.java -+++ b/net/minecraft/server/level/ChunkMap.java -@@ -1232,7 +1232,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - flag = flag && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z); - // Paper end - Configurable entity tracking range by Y - // CraftBukkit start - respect vanish API -- if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits -+ if (flag && !player.getBukkitEntity().canSeeChunkMapUpdatePlayer(this.entity.getBukkitEntity())) { // Paper - only consider hits // SparklyPaper - optimize canSee checks - flag = false; - } - // CraftBukkit end diff --git a/sparklypaper-server/minecraft-patches/features/0009-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/sparklypaper-server/minecraft-patches/features/0009-Fix-MC-117075-TE-Unload-Lag-Spike.patch deleted file mode 100644 index 98118b2..0000000 --- a/sparklypaper-server/minecraft-patches/features/0009-Fix-MC-117075-TE-Unload-Lag-Spike.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 13 Jan 2025 16:41:37 -0300 -Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike - -We replaced the `blockEntityTickers` list with a custom list based on fastutil's `ObjectArrayList` with a small yet huge change for us: A method that allows us to remove a list of indexes from the list. - -This is WAY FASTER than using `removeAll` with a list of entries to be removed, because we don't need to calculate the identity of each block entity to be removed, and we can jump directly to where the search should begin, giving a performance boost for small removals (because we don't need to loop thru the entire list to find what element should be removed) and a performance boost for big removals (no need to calculate the identity of each block entity). - -diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 27c2ea4a387ee5f7d078a42cb57f146cb748501d..644ab8b2c797f0675530a3efe23a878899689d66 100644 ---- a/net/minecraft/world/level/Level.java -+++ b/net/minecraft/world/level/Level.java -@@ -115,7 +115,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - public static final int TICKS_PER_DAY = 24000; - public static final int MAX_ENTITY_SPAWN_Y = 20000000; - public static final int MIN_ENTITY_SPAWN_Y = -20000000; -- public final List blockEntityTickers = Lists.newArrayList(); // Paper - public -+ public final net.sparklypower.sparklypaper.BlockEntityTickersList blockEntityTickers = new net.sparklypower.sparklypaper.BlockEntityTickersList(); // Paper - public // SparklyPaper - optimize block entity removals - protected final NeighborUpdater neighborUpdater; - private final List pendingBlockEntityTickers = Lists.newArrayList(); - private boolean tickingBlockEntities; -@@ -1479,7 +1479,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - TickingBlockEntity tickingBlockEntity = this.blockEntityTickers.get(this.tileTickPosition); - // Spigot end - if (tickingBlockEntity.isRemoved()) { -- toRemove.add(tickingBlockEntity); // Paper - Fix MC-117075; use removeAll -+ this.blockEntityTickers.markAsRemoved(this.tileTickPosition); // toRemove.add(tickingBlockEntity); // SparklyPaper - optimize block entity removals // Paper - Fix MC-117075; use removeAll - } else if (runsNormally && this.shouldTickBlocksAt(tickingBlockEntity.getPos())) { - tickingBlockEntity.tick(); - // Paper start - rewrite chunk system -@@ -1491,6 +1491,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - } - this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 - -+ this.blockEntityTickers.removeMarkedEntries(); // SparklyPaper - optimize block entity removals - this.tickingBlockEntities = false; - profilerFiller.pop(); - this.spigotConfig.currentPrimedTnt = 0; // Spigot diff --git a/sparklypaper-server/minecraft-patches/features/0010-Track-how-much-MSPT-each-world-used.patch b/sparklypaper-server/minecraft-patches/features/0010-Track-how-much-MSPT-each-world-used.patch deleted file mode 100644 index 957df01..0000000 --- a/sparklypaper-server/minecraft-patches/features/0010-Track-how-much-MSPT-each-world-used.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 6 Nov 2023 21:54:33 -0300 -Subject: [PATCH] Track how much MSPT each world used - - -diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 4dbf2d9aa52029122f4816ca3504fa330b28a29b..c15c11ab3feaca918ac0185383cd1653200cd186 100644 ---- a/net/minecraft/server/MinecraftServer.java -+++ b/net/minecraft/server/MinecraftServer.java -@@ -1737,7 +1737,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Wed, 5 Jun 2024 15:20:00 -0300 -Subject: [PATCH] Reset dirty flag when loading maps from the disk - -By default, the server will start rewriting all map datas to the disk after loading it, even if the map didn't have any changes - -This also slows down world saving a lot if you have a lot of maps - -diff --git a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index f5a131e870a4f1ad06ebfb1f360720cf19656fb5..2aed9d55ea1a93b323865141a69c9947759eae29 100644 ---- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -+++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -@@ -197,6 +197,7 @@ public class MapItemSavedData extends SavedData { - } - } - -+ mapItemSavedData.setDirty(false); // SparklyPaper - reset dirty flag when loading maps from the disk (context for updates: this modification is at the end of the map "load" function) - return mapItemSavedData; - } - diff --git a/sparklypaper-server/minecraft-patches/features/0012-Helpful-NMS-packet-changes.patch b/sparklypaper-server/minecraft-patches/features/0012-Helpful-NMS-packet-changes.patch deleted file mode 100644 index b1aae48..0000000 --- a/sparklypaper-server/minecraft-patches/features/0012-Helpful-NMS-packet-changes.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 10 Jun 2024 13:06:30 -0300 -Subject: [PATCH] Helpful NMS packet changes - -Some nice changes to the packet internals to make packet sending and manipulation easier for us to avoid Reflection and JVM internals (ooo theUnsafe spooky) usage - -diff --git a/net/minecraft/network/protocol/game/ClientboundAddEntityPacket.java b/net/minecraft/network/protocol/game/ClientboundAddEntityPacket.java -index 1373977b339405ef59bb3ea03d195285c96dd3fe..20a782d1bb7355bbdc0822a02204e1e05dc44145 100644 ---- a/net/minecraft/network/protocol/game/ClientboundAddEntityPacket.java -+++ b/net/minecraft/network/protocol/game/ClientboundAddEntityPacket.java -@@ -22,7 +22,7 @@ public class ClientboundAddEntityPacket implements Packet type; -+ public EntityType type; // SparklyPaper - Helpful NMS packet changes: remove final and make public - private final double x; - private final double y; - private final double z; -@@ -180,6 +180,32 @@ public class ClientboundAddEntityPacket implements Packet blockEntitiesData; - // Paper start - Handle oversized block entities in chunks - private final java.util.List> extraPackets = new java.util.ArrayList<>(); -diff --git a/net/minecraft/network/protocol/game/ClientboundRotateHeadPacket.java b/net/minecraft/network/protocol/game/ClientboundRotateHeadPacket.java -index 4bcbf4bff67d4d4958d56764a273cf4a66b9dd0c..fd621a5d02170f6aa297dbd6a08ba1fef60e54c9 100644 ---- a/net/minecraft/network/protocol/game/ClientboundRotateHeadPacket.java -+++ b/net/minecraft/network/protocol/game/ClientboundRotateHeadPacket.java -@@ -20,6 +20,13 @@ public class ClientboundRotateHeadPacket implements Packet DATA_TEXT_ID = SynchedEntityData.defineId(Display.TextDisplay.class, EntityDataSerializers.COMPONENT); -+ public static final EntityDataAccessor DATA_TEXT_ID = SynchedEntityData.defineId(Display.TextDisplay.class, EntityDataSerializers.COMPONENT); // SparklyPaper - Helpful NMS packet changes: make public - public static final EntityDataAccessor DATA_LINE_WIDTH_ID = SynchedEntityData.defineId(Display.TextDisplay.class, EntityDataSerializers.INT); - public static final EntityDataAccessor DATA_BACKGROUND_COLOR_ID = SynchedEntityData.defineId( - Display.TextDisplay.class, EntityDataSerializers.INT diff --git a/sparklypaper-server/minecraft-patches/features/0013-Add-CraftItemRecipeEvent.patch b/sparklypaper-server/minecraft-patches/features/0013-Add-CraftItemRecipeEvent.patch deleted file mode 100644 index bb4c924..0000000 --- a/sparklypaper-server/minecraft-patches/features/0013-Add-CraftItemRecipeEvent.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Tue, 25 Jun 2024 02:52:32 -0300 -Subject: [PATCH] Add CraftItemRecipeEvent - -Used when a player OR a crafter block crafts an item, as an alternative to PrepareItemCraftEvent and CraftItemEvent, because both events are not triggered when a item is crafted from a crafter - -diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 882dbb1276c548316938bbc50f5f7e01f8547ff8..01d526cef9c0aa2d5b6b1ea1c93f8a277bfac8c2 100644 ---- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -3163,6 +3163,21 @@ public class ServerGamePacketListenerImpl - } else { - event = new CraftItemEvent(recipe, inventory, type, slotNum, click, action); - } -+ // SparklyPaper start - add CraftItemRecipeEvent -+ // We will pigback a bit on the current implementation -+ net.sparklypower.sparklypaper.event.inventory.CraftItemRecipeEvent craftItemRecipeEvent = new net.sparklypower.sparklypaper.event.inventory.CraftItemRecipeEvent( -+ ((CraftingInventory) top).getMatrix(), // We cannot use the top inventory directly because (it seems) that the first slot is the "result" slot -+ recipe, -+ event.getCurrentItem() -+ ); -+ if (craftItemRecipeEvent.callEvent()) { -+ event.setCurrentItem(craftItemRecipeEvent.getResult()); -+ } else { -+ event.setCancelled(true); -+ cancelled = true; -+ event.setCurrentItem(craftItemRecipeEvent.getResult()); -+ } -+ // SparklyPaper end - } - } - -diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java -index 5f5966278faf86ed9b28955c80ba845c0cb75595..751969d28951f59f381aa6bf7ad42d55d3e84d57 100644 ---- a/net/minecraft/world/level/block/CrafterBlock.java -+++ b/net/minecraft/world/level/block/CrafterBlock.java -@@ -167,6 +167,13 @@ public class CrafterBlock extends BaseEntityBlock { - } - itemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getResult()); - // CraftBukkit end -+ // SparklyPaper - add CraftItemRecipeEvent -+ net.sparklypower.sparklypaper.event.inventory.CraftItemRecipeEvent sparklyEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callCraftItemRecipeEvent(crafterBlockEntity, recipeHolder.toBukkitRecipe(), itemStack); -+ if (sparklyEvent.isCancelled()) { -+ return; -+ } -+ itemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(sparklyEvent.getResult()); -+ // SparklyPaper end - if (itemStack.isEmpty()) { - level.levelEvent(1050, pos, 0); - } else { diff --git a/sparklypaper-server/minecraft-patches/features/0015-Add-PlayerMoveControllableVehicleEvent.patch b/sparklypaper-server/minecraft-patches/features/0015-Add-PlayerMoveControllableVehicleEvent.patch deleted file mode 100644 index 936b895..0000000 --- a/sparklypaper-server/minecraft-patches/features/0015-Add-PlayerMoveControllableVehicleEvent.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Sat, 4 Jan 2025 23:58:55 -0300 -Subject: [PATCH] Add PlayerMoveControllableVehicleEvent - - -diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 7f9ed94576c94161070fd1be1544aaed9aac0c6b..da190c2ab2080344dc11903aec51598af18d7556 100644 ---- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -587,6 +587,31 @@ public class ServerGamePacketListenerImpl - LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7)); - } - -+ // SparklyPaper start - Add PlayerMoveControllableVehicleEvent -+ org.bukkit.entity.Player craftPlayer = this.getCraftPlayer(); -+ org.bukkit.entity.Entity bukkitVehicle = rootVehicle.getBukkitEntity(); -+ if (bukkitVehicle instanceof org.bukkit.entity.Vehicle) { -+ net.sparklypower.sparklypaper.event.player.PlayerMoveControllableVehicleEvent playerMoveControllableVehicleEvent = new net.sparklypower.sparklypaper.event.player.PlayerMoveControllableVehicleEvent( -+ craftPlayer, -+ (org.bukkit.entity.Vehicle) bukkitVehicle, -+ new org.bukkit.Location(craftPlayer.getWorld(), x, y, z, f, f1), -+ new org.bukkit.Location(craftPlayer.getWorld(), d, d1, d2, f, f1) -+ ); -+ if (!playerMoveControllableVehicleEvent.callEvent()) { -+ // Cancelled, move back! -+ rootVehicle.absMoveTo(x, y, z, f, f1); -+ this.player.absMoveTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // CraftBukkit -+ this.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle)); -+ return; -+ } -+ d = playerMoveControllableVehicleEvent.getTo().x(); -+ d1 = playerMoveControllableVehicleEvent.getTo().y(); -+ d2 = playerMoveControllableVehicleEvent.getTo().z(); -+ f = playerMoveControllableVehicleEvent.getTo().getYaw(); -+ f1 = playerMoveControllableVehicleEvent.getTo().getPitch(); -+ } -+ // SparklyPaper end -+ - rootVehicle.absMoveTo(d, d1, d2, f, f1); - this.player.absMoveTo(d, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit - // Paper start - optimise out extra getCubes diff --git a/sparklypaper-server/minecraft-patches/features/0016-Add-PlayerPreMoveEvent.patch b/sparklypaper-server/minecraft-patches/features/0016-Add-PlayerPreMoveEvent.patch deleted file mode 100644 index 593bca9..0000000 --- a/sparklypaper-server/minecraft-patches/features/0016-Add-PlayerPreMoveEvent.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Wed, 8 Jan 2025 22:48:04 -0300 -Subject: [PATCH] Add PlayerPreMoveEvent - - -diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 4b8f847e6a7437152fe3409f9f6bc800ca0be93b..9b3dc8de35cf3ab55e9eb9dc5849d6205a52dde5 100644 ---- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1429,7 +1429,7 @@ public class ServerGamePacketListenerImpl - d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above - d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above - d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above -- boolean flag = d4 > 0.0; -+ boolean flag = d4 > 0.0; // SparklyPaper - diff on change, used to reset the fall distance, checks if d7 is > 0.0D (player is moving upwards) - if (this.player.onGround() && !packet.isOnGround() && flag) { - // Paper start - Add PlayerJumpEvent - org.bukkit.entity.Player player = this.getCraftPlayer(); -@@ -1463,7 +1463,37 @@ public class ServerGamePacketListenerImpl - - boolean flag1 = this.player.verticalCollisionBelow; - this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5)); -- this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move -+ // SparklyPaper start - Add PlayerPreMoveEvent event -+ boolean isOnGround = packet.isOnGround(); -+ boolean horizontalCollision = packet.horizontalCollision(); -+ if (net.sparklypower.sparklypaper.event.player.PlayerPreMoveEvent.getHandlerList().getRegisteredListeners().length != 0) { -+ org.bukkit.entity.Player player = this.getCraftPlayer(); -+ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. -+ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. -+ -+ // If the packet contains movement information then we update the To location with the correct XYZ. -+ if (packet.hasPos) { -+ to.setX(packet.x); -+ to.setY(packet.y); -+ to.setZ(packet.z); -+ } -+ -+ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. -+ if (packet.hasRot) { -+ to.setYaw(packet.yRot); -+ to.setPitch(packet.xRot); -+ } -+ -+ net.sparklypower.sparklypaper.event.player.PlayerPreMoveEvent event = new net.sparklypower.sparklypaper.event.player.PlayerPreMoveEvent(player, from, to, packet.isOnGround(), packet.horizontalCollision(), flag); -+ -+ if (event.callEvent()) { -+ isOnGround = event.isOnGround(); -+ horizontalCollision = event.isHorizontalCollision(); -+ flag = event.isResetFallDistance(); -+ } -+ } -+ // SparklyPaper end -+ this.player.onGround = isOnGround; // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move // SparklyPaper - Add PlayerPreMoveEvent - boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... - // Paper start - prevent position desync - if (this.awaitingPositionFromClient != null) { -@@ -1597,15 +1627,15 @@ public class ServerGamePacketListenerImpl - && this.noBlocksAround(this.player); - this.player.serverLevel().getChunkSource().move(this.player); - Vec3 vec3 = new Vec3(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z); -- this.player.setOnGroundWithMovement(packet.isOnGround(), packet.horizontalCollision(), vec3); -- this.player.doCheckFallDamage(vec3.x, vec3.y, vec3.z, packet.isOnGround()); -+ this.player.setOnGroundWithMovement(isOnGround, horizontalCollision, vec3); // SparklyPaper - Add PlayerPreMoveEvent -+ this.player.doCheckFallDamage(vec3.x, vec3.y, vec3.z, isOnGround); // SparklyPaper - Add PlayerPreMoveEvent - if (!this.player.isSpectator() && this.player.isAffectedByBlocks()) this.player.recordMovementThroughBlocks(new Vec3(x, y, z), this.player.position()); // Paper - Do not record movement for vehicles/players unaffected by blocks - this.handlePlayerKnownMovement(vec3); - if (flag) { - this.player.resetFallDistance(); - } - -- if (packet.isOnGround() -+ if (isOnGround // SparklyPaper - Add PlayerPreMoveEvent - || this.player.hasLandedInLiquid() - || this.player.onClimbable() - || this.player.isSpectator() -@@ -1620,7 +1650,7 @@ public class ServerGamePacketListenerImpl - this.lastGoodZ = this.player.getZ(); - } else { - this.internalTeleport(x, y, z, f, f1); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet. -- this.player.doCheckFallDamage(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z, packet.isOnGround()); -+ this.player.doCheckFallDamage(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z, isOnGround); // SparklyPaper - Add PlayerPreMoveEvent - } - } - } diff --git a/sparklypaper-server/minecraft-patches/features/0018-Parallel-world-ticking.patch b/sparklypaper-server/minecraft-patches/features/0018-Parallel-world-ticking.patch deleted file mode 100644 index db2cdf5..0000000 --- a/sparklypaper-server/minecraft-patches/features/0018-Parallel-world-ticking.patch +++ /dev/null @@ -1,967 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Tue, 7 Nov 2023 01:34:14 -0300 -Subject: [PATCH] Parallel world ticking - -"mom can we have folia?" "we already have folia at home" folia at home: - -diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -index b5817aa8f537593f6d9fc6b612c82ccccb250ac7..2dbbd33690265cbacd4c6516d24bc64890f50990 100644 ---- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -@@ -1031,7 +1031,7 @@ public final class ChunkHolderManager { - if (changedFullStatus.isEmpty()) { - return; - } -- if (!TickThread.isTickThread()) { -+ if (!TickThread.isTickThreadFor(world)) { // SparklyPaper - parallel world ticking - this.taskScheduler.scheduleChunkTask(() -> { - final ArrayDeque pendingFullLoadUpdate = ChunkHolderManager.this.pendingFullLoadUpdate; - for (int i = 0, len = changedFullStatus.size(); i < len; ++i) { -@@ -1057,7 +1057,7 @@ public final class ChunkHolderManager { - - // note: never call while inside the chunk system, this will absolutely break everything - public void processUnloads() { -- TickThread.ensureTickThread("Cannot unload chunks off-main"); -+ TickThread.ensureTickThread(world, "Cannot unload chunks off-main"); // SparklyPaper - parallel world ticking - - if (BLOCK_TICKET_UPDATES.get() == Boolean.TRUE) { - throw new IllegalStateException("Cannot unload chunks recursively"); -@@ -1339,7 +1339,7 @@ public final class ChunkHolderManager { - - List changedFullStatus = null; - -- final boolean isTickThread = TickThread.isTickThread(); -+ final boolean isTickThread = TickThread.isTickThreadFor(world); - - boolean ret = false; - final boolean canProcessFullUpdates = processFullUpdates & isTickThread; -diff --git a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java -index 4a881636ba21fae9e50950bbba2b4321b71d35ab..ef76ff3671d38b482ac9932560e574d0d8cd9318 100644 ---- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java -+++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java -@@ -46,7 +46,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack); - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - serverLevel.getCraftServer().getPluginManager().callEvent(event); - } - -diff --git a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -index bd5bbc7e55c6bea77991fe5a3c0c2580313d16c5..a231e08edba33bd55bed9a34129615f5e6dddb4d 100644 ---- a/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -+++ b/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -@@ -78,7 +78,7 @@ public class DefaultDispenseItemBehavior implements DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack); - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(itemEntity.getDeltaMovement())); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - level.getCraftServer().getPluginManager().callEvent(event); - } - -diff --git a/net/minecraft/core/dispenser/DispenseItemBehavior.java b/net/minecraft/core/dispenser/DispenseItemBehavior.java -index 717c84165d5e25cd384f56b7cb976abf6669b6f0..8771e808cdf90fa6590140654da4eab08e15e58f 100644 ---- a/net/minecraft/core/dispenser/DispenseItemBehavior.java -+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java -@@ -89,7 +89,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack); - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - serverLevel.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -147,7 +147,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack); - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - serverLevel.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -201,7 +201,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack); - - org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity()); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - world.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -251,7 +251,7 @@ public interface DispenseItemBehavior { - org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockSource.pos()); - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleCopy); - org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), abstractChestedHorse.getBukkitLivingEntity()); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - world.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -329,7 +329,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - level.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -389,7 +389,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - levelAccessor.getMinecraftWorld().getCraftServer().getPluginManager().callEvent(event); - } - -@@ -425,7 +425,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - serverLevel.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -482,7 +482,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - level.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -510,8 +510,8 @@ public interface DispenseItemBehavior { - // CraftBukkit start - level.captureTreeGeneration = false; - if (level.capturedBlockStates.size() > 0) { -- org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeType; -- net.minecraft.world.level.block.SaplingBlock.treeType = null; -+ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeTypeRT.get(); // SparklyPaper - parallel world ticking -+ net.minecraft.world.level.block.SaplingBlock.treeTypeRT.set(null); // SparklyPaper - parallel world ticking - org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(blockPos, level.getWorld()); - List blocks = new java.util.ArrayList<>(level.capturedBlockStates.values()); - level.capturedBlockStates.clear(); -@@ -548,7 +548,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(singleItemStack); - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockPos.getX() + 0.5D, (double) blockPos.getY(), (double) blockPos.getZ() + 0.5D)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - level.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -591,7 +591,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - level.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -644,7 +644,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - level.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -702,7 +702,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - only single item in event - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), org.bukkit.craftbukkit.util.CraftVector.toBukkit(blockPos)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - serverLevel.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -783,7 +783,7 @@ public interface DispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), entitiesOfClass.get(0).getBukkitLivingEntity()); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - serverLevel.getCraftServer().getPluginManager().callEvent(event); - } - -diff --git a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java -index 3595bbd05fb3e8fe57e38d4e2df5c6237046b726..2b02d7cbc7fbb916c240f2d16bab365dbc1b8e56 100644 ---- a/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java -+++ b/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java -@@ -39,7 +39,7 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack); - - org.bukkit.event.block.BlockDispenseArmorEvent event = new org.bukkit.event.block.BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) livingEntity.getBukkitEntity()); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - world.getCraftServer().getPluginManager().callEvent(event); - } - -diff --git a/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java b/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java -index 116395b6c00a0814922516707544a9ff26d68835..672ebd0cfc144d9b7315dcebf1e8007912ad7412 100644 ---- a/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java -+++ b/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java -@@ -62,7 +62,7 @@ public class MinecartDispenseItemBehavior extends DefaultDispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1); - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(vec31.x, vec31.y, vec31.z)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - serverLevel.getCraftServer().getPluginManager().callEvent(event); - } - -diff --git a/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java b/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java -index 449d9b72ff4650961daa9d1bd25940f3914a6b12..df07b55924c1edca11eebd9debc75d9f184ede9d 100644 ---- a/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java -+++ b/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java -@@ -32,7 +32,7 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack1); - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) direction.getStepX(), (double) direction.getStepY(), (double) direction.getStepZ())); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - serverLevel.getCraftServer().getPluginManager().callEvent(event); - } - -diff --git a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -index 626e9feb6a6e7a2cbc7c63e30ba4fb6b923e85c7..6ac9a0fc92eb9801bed3bc296988ee224afffa14 100644 ---- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -+++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -@@ -25,7 +25,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { - org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, blockSource.pos()); - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item); // Paper - ignore stack size on damageable items - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - serverLevel.getCraftServer().getPluginManager().callEvent(event); - } - -diff --git a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java -index 5ab2c8333178335515e619b87ae420f948c83bd1..c98e3748ff467f75f0a0e5a429563feaf06105f3 100644 ---- a/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java -+++ b/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java -@@ -27,7 +27,7 @@ public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { - org.bukkit.craftbukkit.inventory.CraftItemStack craftItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(item.copyWithCount(1)); // Paper - single item in event - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockPos.getX(), blockPos.getY(), blockPos.getZ())); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - blockSource.level().getCraftServer().getPluginManager().callEvent(event); - } - -diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index c15c11ab3feaca918ac0185383cd1653200cd186..1bc0e3397a1299bdbe37a69097ece7d7395421f7 100644 ---- a/net/minecraft/server/MinecraftServer.java -+++ b/net/minecraft/server/MinecraftServer.java -@@ -305,6 +305,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (concurrent because plugins may schedule tasks async) - public net.sparklypower.sparklypaper.HalloweenManager halloweenManager = new net.sparklypower.sparklypaper.HalloweenManager(); // SparklyPaper - Spooky month optimizations -+ public java.util.concurrent.Semaphore serverLevelTickingSemaphore = null; // SparklyPaper - parallel world ticking - - public static S spin(Function threadFunction) { - ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system -@@ -1720,6 +1721,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> tasks = new java.util.ArrayDeque<>(); -+ try { - for (ServerLevel serverLevel : this.getAllLevels()) { - serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent - serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent -@@ -1736,27 +1740,46 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -+ try { -+ ca.spottedleaf.moonrise.common.util.TickThread.ServerLevelTickThread currentThread = (ca.spottedleaf.moonrise.common.util.TickThread.ServerLevelTickThread) Thread.currentThread(); -+ currentThread.currentlyTickingServerLevel = serverLevel; -+ -+ long i = Util.getNanos(); // SparklyPaper - track world's MSPT -+ serverLevel.tick(hasTimeLeft); -+ // SparklyPaper start - track world's MSPT -+ long j = Util.getNanos() - i; -+ -+ // These are from the "tickServer" function -+ serverLevel.tickTimes5s.add(this.tickCount, j); -+ serverLevel.tickTimes10s.add(this.tickCount, j); -+ serverLevel.tickTimes60s.add(this.tickCount, j); -+ // SparklyPaper end -+ } catch (Throwable throwable) { -+ CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world"); -+ -+ serverLevel.fillReportDetails(crashreport); -+ throw new ReportedException(crashreport); -+ } finally { -+ serverLevelTickingSemaphore.release(); -+ } -+ }, serverLevel) -+ ); - - profilerFiller.pop(); - profilerFiller.pop(); - serverLevel.explosionDensityCache.clear(); // Paper - Optimize explosions - } -+ -+ while (!tasks.isEmpty()) { -+ tasks.pop().get(); -+ } -+ } catch (java.lang.InterruptedException | java.util.concurrent.ExecutionException e) { -+ throw new RuntimeException(e); // Propagate exception -+ } -+ // SparklyPaper end - this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked - - profilerFiller.popPush("connection"); -@@ -1847,6 +1870,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop, ServerLevel> oldLevels = this.levels; - Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); - newLevels.remove(level.dimension()); -+ level.tickExecutor.shutdown(); // SparklyPaper - parallel world ticking (We remove it in here instead of ServerLevel.close() because ServerLevel.close() is never called!) - this.levels = Collections.unmodifiableMap(newLevels); - } - // CraftBukkit end -diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 6ac73610f6039290c4ef3dde2206b6863d2b5067..0c5dbfe1d7e17796c1a60bcb1f97673ddff4d94e 100644 ---- a/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -233,6 +233,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - } - net.sparklypower.sparklypaper.SparklyPaperCommands.INSTANCE.registerCommands(this); - // SparklyPaper end -+ serverLevelTickingSemaphore = new java.util.concurrent.Semaphore(net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.getConfig().getParallelWorldTicking().getThreads()); // SparklyPaper - parallel world ticking -+ DedicatedServer.LOGGER.info("Using " + serverLevelTickingSemaphore.availablePermits() + " permits for parallel world ticking"); // SparklyPaper - parallel world ticking - // SparklyPaper start - Spooky month optimizations - halloweenManager.startHalloweenEpochTask(); - halloweenManager.waitUntilEpochHasBeenUpdated(); -diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 3bdd68f6fd3f6558276774064f021936fa00729e..0ee5bb3665ba097acd08386e1b0c4cdbdbd02bc2 100644 ---- a/net/minecraft/server/level/ServerLevel.java -+++ b/net/minecraft/server/level/ServerLevel.java -@@ -184,7 +184,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - private final MinecraftServer server; - public final net.minecraft.world.level.storage.PrimaryLevelData serverLevelData; // CraftBukkit - type - private int lastSpawnChunkRadius; -- final EntityTickList entityTickList = new EntityTickList(); -+ final EntityTickList entityTickList = new EntityTickList(this); // SparklyPaper - parallel world ticking - // Paper - rewrite chunk system - private final GameEventDispatcher gameEventDispatcher; - public boolean noSave; -@@ -208,6 +208,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - private final StructureCheck structureCheck; - private final boolean tickTime; - private final RandomSequences randomSequences; -+ public java.util.concurrent.ExecutorService tickExecutor; // SparklyPaper - parallel world ticking - - // CraftBukkit start - public final LevelStorageSource.LevelStorageAccess levelStorageAccess; -@@ -687,6 +688,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler); - // Paper end - rewrite chunk system - this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit -+ this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new net.sparklypower.sparklypaper.ServerLevelTickExecutorThreadFactory(getWorld().getName())); // SparklyPaper - parallel world ticking - } - - // Paper start -@@ -1226,7 +1228,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - } - // Paper start - rewrite chunk system - if ((++this.tickedBlocksOrFluids & 7L) != 0L) { -- ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); -+ // ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); // SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) - } - // Paper end - rewrite chunk system - -@@ -1239,7 +1241,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - } - // Paper start - rewrite chunk system - if ((++this.tickedBlocksOrFluids & 7L) != 0L) { -- ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); -+ // ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this.server).moonrise$executeMidTickTasks(); // SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) - } - // Paper end - rewrite chunk system - -@@ -1499,6 +1501,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - } - - private void addPlayer(ServerPlayer player) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add player off-main"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - Entity entity = this.getEntities().get(player.getUUID()); - if (entity != null) { - LOGGER.warn("Force-added player with duplicate UUID {}", player.getUUID()); -@@ -1511,7 +1514,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - - // CraftBukkit start - private boolean addEntity(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -- org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add entity off-main"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - entity.generation = false; // Paper - Don't fire sync event during generation; Reset flag if it was added during a ServerLevel generation process - // Paper start - extra debug info - if (entity.valid) { -diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 57d432dc9e8d8e9a3e088e7c40b35178c30fe786..8a6be70e40367a94ed7ba2947426cd4a40fe7d33 100644 ---- a/net/minecraft/server/level/ServerPlayer.java -+++ b/net/minecraft/server/level/ServerPlayer.java -@@ -423,6 +423,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - return this.viewDistanceHolder; - } - // Paper end - rewrite chunk system -+ public boolean hasTickedAtLeastOnceInNewWorld = false; // SparklyPaper - parallel world ticking (fixes bug in DreamResourceReset where the inventory is opened AFTER the player has changed worlds, if you click with the quick tp torch in a chest, because the inventory is opened AFTER the player has teleported) - - public ServerPlayer(MinecraftServer server, ServerLevel level, GameProfile gameProfile, ClientInformation clientInformation) { - super(level, level.getSharedSpawnPos(), level.getSharedSpawnAngle(), gameProfile); -@@ -792,6 +793,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - - @Override - public void tick() { -+ hasTickedAtLeastOnceInNewWorld = true; // SparklyPaper - parallel world ticking (see: PARALLEL_NOTES.md - Opening an inventory after a world switch) - // CraftBukkit start - if (this.joining) { - this.joining = false; -@@ -1415,6 +1417,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - return this; - } else { - // CraftBukkit start -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot change dimension of a player off-main, from world " + serverLevel().getWorld().getName() + " to world " + level.getWorld().getName()); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - /* - this.isChangingDimension = true; - LevelData levelData = level.getLevelData(); -@@ -1768,6 +1771,12 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - return OptionalInt.empty(); - } else { - // CraftBukkit start -+ // SparklyPaper start - parallel world ticking (see: PARALLEL_NOTES.md - Opening an inventory after a world switch) -+ if (!hasTickedAtLeastOnceInNewWorld) { -+ MinecraftServer.LOGGER.warn("Ignoring request to open container " + abstractContainerMenu + " because we haven't ticked in the current world yet!", new Throwable()); -+ return OptionalInt.empty(); -+ } -+ // SparklyPaper end - this.containerMenu = abstractContainerMenu; // Moved up - if (!this.isImmobile()) - this.connection -@@ -1832,6 +1841,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - } - @Override - public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ // SparklyPaper start - parallel world ticking (debugging) -+ if (net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.getLogContainerCreationStacktraces()) { -+ MinecraftServer.LOGGER.warn("Closing " + this.getBukkitEntity().getName() + " inventory that was created at", this.containerMenu.containerCreationStacktrace); -+ } -+ // SparklyPaper end - org.bukkit.craftbukkit.event.CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit - // Paper end - Inventory close reason - this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); -diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 5a4960fdbd97d830ac79845697eea9372c48a13b..76c17bc3425a081a0d691a10525f91b3b930ebd0 100644 ---- a/net/minecraft/server/players/PlayerList.java -+++ b/net/minecraft/server/players/PlayerList.java -@@ -113,7 +113,7 @@ public abstract class PlayerList { - private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); - private final MinecraftServer server; - public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety -- private final Map playersByUUID = Maps.newHashMap(); -+ private final Map playersByUUID = Maps.newHashMap(); // SparklyPaper - parallel world ticking (we don't need to replace the original map because we never iterate on top of this map) - private final UserBanList bans = new UserBanList(USERBANLIST_FILE); - private final IpBanList ipBans = new IpBanList(IPBANLIST_FILE); - private final ServerOpList ops = new ServerOpList(OPLIST_FILE); -@@ -134,7 +134,7 @@ public abstract class PlayerList { - - // CraftBukkit start - private org.bukkit.craftbukkit.CraftServer cserver; -- private final Map playersByName = new java.util.HashMap<>(); -+ private final Map playersByName = new java.util.HashMap<>(); // SparklyPaper - parallel world ticking (we don't need to replace the original map because we never iterate on top of this map) - public @Nullable String collideRuleTeamName; // Paper - Configurable player collision - - public PlayerList(MinecraftServer server, LayeredRegistryAccess registries, PlayerDataStorage playerIo, int maxPlayers) { -@@ -150,6 +150,7 @@ public abstract class PlayerList { - abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor - - public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot place new player off-main"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - player.isRealPlayer = true; // Paper - player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed - GameProfile gameProfile = player.getGameProfile(); -@@ -714,6 +715,13 @@ public abstract class PlayerList { - return this.respawn(player, keepInventory, reason, eventReason, null); - } - public ServerPlayer respawn(ServerPlayer player, boolean keepInventory, Entity.RemovalReason reason, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason eventReason, org.bukkit.Location location) { -+ System.out.println("respawning player - current player container is " + player.containerMenu + " but their inventory is " + player.inventoryMenu); -+ // SparklyPaper - parallel world ticking (additional concurrency issues logs) -+ if (location != null) // TODO: Is this really never null, or is IntelliJ IDEA tripping? Because I'm pretty sure that this can be null and there isn't any @NotNull annotations -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot respawn player off-main, from world " + player.serverLevel().getWorld().getName() + " to world " + location.getWorld().getName()); -+ else -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureOnlyTickThread("Cannot respawn player off-main, respawning in world " + player.serverLevel().getWorld().getName()); -+ // SparklyPaper end - player.stopRiding(); // CraftBukkit - this.players.remove(player); - this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -724,6 +732,7 @@ public abstract class PlayerList { - ServerPlayer serverPlayer = player; - Level fromWorld = player.level(); - player.wonGame = false; -+ serverPlayer.hasTickedAtLeastOnceInNewWorld = false; // SparklyPaper - parallel world ticking (see: PARALLEL_NOTES.md - Opening an inventory after a world switch) - // CraftBukkit end - serverPlayer.connection = player.connection; - serverPlayer.restoreFrom(player, keepInventory); -diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 1b54cf07616a10d93e9336dbd299ba5f09678a28..9548ccc63eebaca1a9ccdd504bdfb4f04e024544 100644 ---- a/net/minecraft/world/entity/Entity.java -+++ b/net/minecraft/world/entity/Entity.java -@@ -819,7 +819,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - // CraftBukkit start - public void postTick() { - // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle -- if (!(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities -+ if (false && !(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities // SparklyPaper - parallel world ticking (see issue #9, this is executed in the server level tick for non-player entities) - this.handlePortal(); - } - } -@@ -3805,6 +3805,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - } - - private Entity teleportCrossDimension(ServerLevel level, TeleportTransition teleportTransition) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(level, "Cannot teleport entity to another world off-main, from world " + this.level.getWorld().getName() + " to world " + level.getWorld().getName()); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - List passengers = this.getPassengers(); - List list = new ArrayList<>(passengers.size()); - this.ejectPassengers(); -diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index 50af953a4698a3c6e16b840fab764dd733b3fbc9..27b6fcb12f1f6a36529fbf19f10ca6330280525a 100644 ---- a/net/minecraft/world/inventory/AbstractContainerMenu.java -+++ b/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -91,8 +91,14 @@ public abstract class AbstractContainerMenu { - } - public void startOpen() {} - // CraftBukkit end -+ public Throwable containerCreationStacktrace; // SparklyPaper - parallel world ticking (debugging) - - protected AbstractContainerMenu(@Nullable MenuType menuType, int containerId) { -+ // SparklyPaper - parallel world ticking (debugging) -+ if (net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.getLogContainerCreationStacktraces()) { -+ this.containerCreationStacktrace = new Throwable(); -+ } -+ // SparklyPaper end - this.menuType = menuType; - this.containerId = containerId; - } -diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index 76f50437396f8f856381d0fbef52953ef7c263f6..199fec37b2c2b2ea6a55700cb8f4ec98aeb6504a 100644 ---- a/net/minecraft/world/item/ItemStack.java -+++ b/net/minecraft/world/item/ItemStack.java -@@ -407,8 +407,8 @@ public final class ItemStack implements DataComponentHolder { - if (interactionResult.consumesAction() && serverLevel.captureTreeGeneration && !serverLevel.capturedBlockStates.isEmpty()) { - serverLevel.captureTreeGeneration = false; - org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(clickedPos, serverLevel.getWorld()); -- org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeType; -- net.minecraft.world.level.block.SaplingBlock.treeType = null; -+ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeTypeRT.get(); // SparklyPaper - parallel world ticking -+ net.minecraft.world.level.block.SaplingBlock.treeTypeRT.set(null); - List blocks = new java.util.ArrayList<>(serverLevel.capturedBlockStates.values()); - serverLevel.capturedBlockStates.clear(); - org.bukkit.event.world.StructureGrowEvent structureEvent = null; -diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 9fcf29108234cc0d233b18b0b1a5631da7e3f382..61c56c58841f936c6bfabe6de493f7dcfdcee94a 100644 ---- a/net/minecraft/world/level/Level.java -+++ b/net/minecraft/world/level/Level.java -@@ -171,6 +171,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - - public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray - public net.sparklypower.sparklypaper.configs.SparklyPaperConfig.SparklyPaperWorldConfig sparklyPaperConfig; // SparklyPaper -+ public io.papermc.paper.redstone.RedstoneWireTurbo turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((net.minecraft.world.level.block.RedStoneWireBlock) net.minecraft.world.level.block.Blocks.REDSTONE_WIRE); // SparklyPaper - parallel world ticking (moved to world) - public static BlockPos lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; -@@ -1100,6 +1101,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - - @Override - public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, pos, "Updating block asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { - // Paper start - Protect Bedrock and End Portal/Frames from being destroyed -@@ -1484,7 +1486,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - tickingBlockEntity.tick(); - // Paper start - rewrite chunk system - if ((++tickedEntities & 7) == 0) { -- ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)(Level)(Object)this).moonrise$midTickTasks(); -+ // ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel)(Level)(Object)this).moonrise$midTickTasks(); // SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) - } - // Paper end - rewrite chunk system - } -@@ -1508,7 +1510,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); - // Paper end - Prevent block entity and entity crashes - } -- this.moonrise$midTickTasks(); // Paper - rewrite chunk system -+ // this.moonrise$midTickTasks(); // Paper - rewrite chunk system // SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) - } - - // Paper start - Option to prevent armor stands from doing entity lookups -@@ -1651,6 +1653,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - - @Nullable - public BlockEntity getBlockEntity(BlockPos pos, boolean validate) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThreadOrAsyncThread((ServerLevel) this, "Cannot read world asynchronously"); // SparklyPaper - parallel world ticking - // Paper start - Perf: Optimize capturedTileEntities lookup - net.minecraft.world.level.block.entity.BlockEntity blockEntity; - if (!this.capturedTileEntities.isEmpty() && (blockEntity = this.capturedTileEntities.get(pos)) != null) { -@@ -1668,6 +1671,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - } - - public void setBlockEntity(BlockEntity blockEntity) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel) this, "Cannot modify world asynchronously"); // SparklyPaper - parallel world ticking - BlockPos blockPos = blockEntity.getBlockPos(); - if (!this.isOutsideBuildHeight(blockPos)) { - // CraftBukkit start -@@ -1752,6 +1756,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - - @Override - public List getEntities(@Nullable Entity entity, AABB boundingBox, Predicate predicate) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, boundingBox, "Cannot getEntities asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - Profiler.get().incrementCounter("getEntities"); - List list = Lists.newArrayList(); - -@@ -2064,8 +2069,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - public abstract RecipeAccess recipeAccess(); - - public BlockPos getBlockRandomPos(int x, int y, int z, int yMask) { -- this.randValue = this.randValue * 3 + 1013904223; -- int i = this.randValue >> 2; -+ int i = this.random.nextInt() >> 2; // SparklyPaper - parallel world ticking - return new BlockPos(x + (i & 15), y + (i >> 16 & yMask), z + (i >> 8 & 15)); - } - -diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java -index e0a4d41e5bcf144ea4c10d6f633c3a95ed2c5aec..ff99bff5b1986798ac8170def2809cc0c553e500 100644 ---- a/net/minecraft/world/level/block/DispenserBlock.java -+++ b/net/minecraft/world/level/block/DispenserBlock.java -@@ -50,7 +50,8 @@ public class DispenserBlock extends BaseEntityBlock { - private static final DefaultDispenseItemBehavior DEFAULT_BEHAVIOR = new DefaultDispenseItemBehavior(); - public static final Map DISPENSER_REGISTRY = new IdentityHashMap<>(); - private static final int TRIGGER_DURATION = 4; -- public static boolean eventFired = false; // CraftBukkit -+ // public static boolean eventFired = false; // CraftBukkit // SparklyPaper - parallel world ticking -+ public static ThreadLocal eventFired = ThreadLocal.withInitial(() -> Boolean.FALSE); // SparklyPaper - parallel world ticking - - @Override - public MapCodec codec() { -@@ -96,7 +97,7 @@ public class DispenserBlock extends BaseEntityBlock { - DispenseItemBehavior dispenseMethod = this.getDispenseMethod(level, item); - if (dispenseMethod != DispenseItemBehavior.NOOP) { - if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(level, pos, item, randomSlot)) return; // Paper - Add BlockPreDispenseEvent -- DispenserBlock.eventFired = false; // CraftBukkit - reset event status -+ DispenserBlock.eventFired.set(Boolean.FALSE); // CraftBukkit - reset event status // SparklyPaper - parallel world ticking - dispenserBlockEntity.setItem(randomSlot, dispenseMethod.dispense(blockSource, item)); - } - } -diff --git a/net/minecraft/world/level/block/FungusBlock.java b/net/minecraft/world/level/block/FungusBlock.java -index 85f0eac75784565c658c5178c544f969db3d6f54..bfa0b1f72497cefecc112d9f484896edc9ec6f36 100644 ---- a/net/minecraft/world/level/block/FungusBlock.java -+++ b/net/minecraft/world/level/block/FungusBlock.java -@@ -76,9 +76,9 @@ public class FungusBlock extends BushBlock implements BonemealableBlock { - // CraftBukkit start - .map((value) -> { - if (this == Blocks.WARPED_FUNGUS) { -- SaplingBlock.treeType = org.bukkit.TreeType.WARPED_FUNGUS; -+ SaplingBlock.treeTypeRT.set(org.bukkit.TreeType.WARPED_FUNGUS); // SparklyPaper - parallel world ticking - } else if (this == Blocks.CRIMSON_FUNGUS) { -- SaplingBlock.treeType = org.bukkit.TreeType.CRIMSON_FUNGUS; -+ SaplingBlock.treeTypeRT.set(org.bukkit.TreeType.CRIMSON_FUNGUS); // SparklyPaper - parallel world ticking - } - return value; - }) -diff --git a/net/minecraft/world/level/block/MushroomBlock.java b/net/minecraft/world/level/block/MushroomBlock.java -index 904369f4d7db41026183f2de7c96c2f0f4dc204d..1ef0cf368fe9de49c7ba0ba3b647108b5bbe3e48 100644 ---- a/net/minecraft/world/level/block/MushroomBlock.java -+++ b/net/minecraft/world/level/block/MushroomBlock.java -@@ -94,7 +94,7 @@ public class MushroomBlock extends BushBlock implements BonemealableBlock { - return false; - } else { - level.removeBlock(pos, false); -- SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? org.bukkit.TreeType.BROWN_MUSHROOM : org.bukkit.TreeType.RED_MUSHROOM; // CraftBukkit -+ SaplingBlock.treeTypeRT.set((this == Blocks.BROWN_MUSHROOM) ? org.bukkit.TreeType.BROWN_MUSHROOM : org.bukkit.TreeType.RED_MUSHROOM); // CraftBukkit // SparklyPaper - parallel world ticking - if (optional.get().value().place(level, level.getChunkSource().getGenerator(), random, pos)) { - return true; - } else { -diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java -index 12c9d60314c99fb65e640d255a2d0c6b7790ad4d..833b180741cd361562d86794b16e3cd6a25410d5 100644 ---- a/net/minecraft/world/level/block/RedStoneWireBlock.java -+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java -@@ -292,7 +292,7 @@ public class RedStoneWireBlock extends Block { - - // Paper start - Optimize redstone (Eigencraft) - // The bulk of the new functionality is found in RedstoneWireTurbo.java -- io.papermc.paper.redstone.RedstoneWireTurbo turbo = new io.papermc.paper.redstone.RedstoneWireTurbo(this); -+ // io.papermc.paper.redstone.RedstoneWireTurbo turbo = new io.papermc.paper.redstone.RedstoneWireTurbo(this); // SparklyPaper - parallel world ticking (moved to world) - - /* - * Modified version of pre-existing updateSurroundingRedstone, which is called from -@@ -308,7 +308,7 @@ public class RedStoneWireBlock extends Block { - if (orientation != null) { - source = pos.relative(orientation.getFront().getOpposite()); - } -- turbo.updateSurroundingRedstone(worldIn, pos, state, source); -+ worldIn.turbo.updateSurroundingRedstone(worldIn, pos, state, source); // SparklyPaper - parallel world ticking - return; - } - updatePowerStrength(worldIn, pos, state, orientation, blockAdded); -@@ -336,7 +336,7 @@ public class RedStoneWireBlock extends Block { - // [Space Walker] suppress shape updates and emit those manually to - // bypass the new neighbor update stack. - if (level.setBlock(pos, state, Block.UPDATE_KNOWN_SHAPE | Block.UPDATE_CLIENTS)) { -- turbo.updateNeighborShapes(level, pos, state); -+ level.turbo.updateNeighborShapes(level, pos, state); // SparklyPaper - parallel world ticking - } - } - } -diff --git a/net/minecraft/world/level/block/SaplingBlock.java b/net/minecraft/world/level/block/SaplingBlock.java -index e014f052e9b0f5ca6b28044e2389782b7d0e0cb8..c9091b66f5ddf7bd7145becdfc5e252163b03300 100644 ---- a/net/minecraft/world/level/block/SaplingBlock.java -+++ b/net/minecraft/world/level/block/SaplingBlock.java -@@ -26,7 +26,7 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { - protected static final float AABB_OFFSET = 6.0F; - protected static final VoxelShape SHAPE = Block.box(2.0, 0.0, 2.0, 14.0, 12.0, 14.0); - protected final TreeGrower treeGrower; -- public static org.bukkit.TreeType treeType; // CraftBukkit -+ public static final ThreadLocal treeTypeRT = new ThreadLocal<>(); // CraftBukkit // SparklyPaper - parallel world ticking (from Folia) - - @Override - public MapCodec codec() { -@@ -63,8 +63,8 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { - this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random); - level.captureTreeGeneration = false; - if (!level.capturedBlockStates.isEmpty()) { -- org.bukkit.TreeType treeType = SaplingBlock.treeType; -- SaplingBlock.treeType = null; -+ org.bukkit.TreeType treeType = SaplingBlock.treeTypeRT.get(); // SparklyPaper - parallel world ticking -+ SaplingBlock.treeTypeRT.set(null); // SparklyPaper - parallel world ticking - org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level.getWorld()); - java.util.List blocks = new java.util.ArrayList<>(level.capturedBlockStates.values()); - level.capturedBlockStates.clear(); -diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -index 26db603ed681a6c302596627d4dd5bf8a9bafc4e..a2df3546922ea27b948ed89450428a27f65d93ed 100644 ---- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -+++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -@@ -77,6 +77,12 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co - return canUnlock(player, code, displayName, null); - } - public static boolean canUnlock(Player player, LockCode code, Component displayName, @Nullable BlockEntity blockEntity) { -+ // SparklyPaper - parallel world ticking (see: PARALLEL_NOTES.md - Opening an inventory after a world switch) -+ if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != serverPlayer.serverLevel()) { -+ net.minecraft.server.MinecraftServer.LOGGER.warn("Player " + serverPlayer.getScoreboardName() + " (" + serverPlayer.getStringUUID() + ") attempted to open a BlockEntity @ " + blockEntity.getLevel().getWorld().getName() + " " + blockEntity.getBlockPos().getX() + ", " + blockEntity.getBlockPos().getY() + ", " + blockEntity.getBlockPos().getZ() + " while they were in a different world " + serverPlayer.level().getWorld().getName() + " than the block themselves!"); -+ return false; -+ } -+ // SparklyPaper end - if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != null && blockEntity.getLevel().getBlockEntity(blockEntity.getBlockPos()) == blockEntity) { - final org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos()); - net.kyori.adventure.text.Component lockedMessage = net.kyori.adventure.text.Component.translatable("container.isLocked", io.papermc.paper.adventure.PaperAdventure.asAdventure(displayName)); -diff --git a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -index 1638eccef431fb68775af624110f1968f0c6dabd..a1096b17ddd4f02cdbe5615030803df88d200ed7 100644 ---- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -+++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -@@ -43,9 +43,9 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi - // Paper end - Fix NPE in SculkBloomEvent world access - - public static void serverTick(Level level, BlockPos pos, BlockState state, SculkCatalystBlockEntity sculkCatalyst) { -- org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = sculkCatalyst.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. -+ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverrideRT.set(pos); // SparklyPaper - parallel world ticking // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. - sculkCatalyst.catalystListener.getSculkSpreader().updateCursors(level, pos, level.getRandom(), true); -- org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = null; // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverrideRT.set(null); // SparklyPaper - parallel world ticking // CraftBukkit - } - - @Override -diff --git a/net/minecraft/world/level/block/grower/TreeGrower.java b/net/minecraft/world/level/block/grower/TreeGrower.java -index cf7311c507de09a8f89934e430b2201e8bdffe51..2ad658fa8e42f26a37fed9faff421827cb72607b 100644 ---- a/net/minecraft/world/level/block/grower/TreeGrower.java -+++ b/net/minecraft/world/level/block/grower/TreeGrower.java -@@ -204,55 +204,59 @@ public final class TreeGrower { - // CraftBukkit start - private void setTreeType(Holder> holder) { - ResourceKey> treeFeature = holder.unwrapKey().get(); -+ // SparklyPaper start - parallel world ticking -+ org.bukkit.TreeType treeType; - if (treeFeature == TreeFeatures.OAK || treeFeature == TreeFeatures.OAK_BEES_005) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.TREE; -+ treeType = org.bukkit.TreeType.TREE; - } else if (treeFeature == TreeFeatures.HUGE_RED_MUSHROOM) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.RED_MUSHROOM; -+ treeType = org.bukkit.TreeType.RED_MUSHROOM; - } else if (treeFeature == TreeFeatures.HUGE_BROWN_MUSHROOM) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.BROWN_MUSHROOM; -+ treeType = org.bukkit.TreeType.BROWN_MUSHROOM; - } else if (treeFeature == TreeFeatures.JUNGLE_TREE) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.COCOA_TREE; -+ treeType = org.bukkit.TreeType.COCOA_TREE; - } else if (treeFeature == TreeFeatures.JUNGLE_TREE_NO_VINE) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.SMALL_JUNGLE; -+ treeType = org.bukkit.TreeType.SMALL_JUNGLE; - } else if (treeFeature == TreeFeatures.PINE) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.TALL_REDWOOD; -+ treeType = org.bukkit.TreeType.TALL_REDWOOD; - } else if (treeFeature == TreeFeatures.SPRUCE) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.REDWOOD; -+ treeType = org.bukkit.TreeType.REDWOOD; - } else if (treeFeature == TreeFeatures.ACACIA) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.ACACIA; -+ treeType = org.bukkit.TreeType.ACACIA; - } else if (treeFeature == TreeFeatures.BIRCH || treeFeature == TreeFeatures.BIRCH_BEES_005) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.BIRCH; -+ treeType = org.bukkit.TreeType.BIRCH; - } else if (treeFeature == TreeFeatures.SUPER_BIRCH_BEES_0002) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.TALL_BIRCH; -+ treeType = org.bukkit.TreeType.TALL_BIRCH; - } else if (treeFeature == TreeFeatures.SWAMP_OAK) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.SWAMP; -+ treeType = org.bukkit.TreeType.SWAMP; - } else if (treeFeature == TreeFeatures.FANCY_OAK || treeFeature == TreeFeatures.FANCY_OAK_BEES_005) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.BIG_TREE; -+ treeType = org.bukkit.TreeType.BIG_TREE; - } else if (treeFeature == TreeFeatures.JUNGLE_BUSH) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.JUNGLE_BUSH; -+ treeType = org.bukkit.TreeType.JUNGLE_BUSH; - } else if (treeFeature == TreeFeatures.DARK_OAK) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.DARK_OAK; -+ treeType = org.bukkit.TreeType.DARK_OAK; - } else if (treeFeature == TreeFeatures.MEGA_SPRUCE) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.MEGA_REDWOOD; -+ treeType = org.bukkit.TreeType.MEGA_REDWOOD; - } else if (treeFeature == TreeFeatures.MEGA_PINE) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.MEGA_PINE; -+ treeType = org.bukkit.TreeType.MEGA_PINE; - } else if (treeFeature == TreeFeatures.MEGA_JUNGLE_TREE) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.JUNGLE; -+ treeType = org.bukkit.TreeType.JUNGLE; - } else if (treeFeature == TreeFeatures.AZALEA_TREE) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.AZALEA; -+ treeType = org.bukkit.TreeType.AZALEA; - } else if (treeFeature == TreeFeatures.MANGROVE) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.MANGROVE; -+ treeType = org.bukkit.TreeType.MANGROVE; - } else if (treeFeature == TreeFeatures.TALL_MANGROVE) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.TALL_MANGROVE; -+ treeType = org.bukkit.TreeType.TALL_MANGROVE; - } else if (treeFeature == TreeFeatures.CHERRY || treeFeature == TreeFeatures.CHERRY_BEES_005) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.CHERRY; -+ treeType = org.bukkit.TreeType.CHERRY; - } else if (treeFeature == TreeFeatures.PALE_OAK || treeFeature == TreeFeatures.PALE_OAK_BONEMEAL) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.PALE_OAK; -+ treeType = org.bukkit.TreeType.PALE_OAK; - } else if (treeFeature == TreeFeatures.PALE_OAK_CREAKING) { -- net.minecraft.world.level.block.SaplingBlock.treeType = org.bukkit.TreeType.PALE_OAK_CREAKING; -+ treeType = org.bukkit.TreeType.PALE_OAK_CREAKING; - } else { - throw new IllegalArgumentException("Unknown tree generator " + treeFeature); - } -+ net.minecraft.world.level.block.SaplingBlock.treeTypeRT.set(treeType); // SparklyPaper - parallel world ticking -+ // SparklyPaper end - } - // CraftBukkit end - } -diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index 761fdcd4a4e18f45547afd8edff44f61c6eeacb4..17fb7161171cbe44d145cf0065826f49183880b0 100644 ---- a/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/net/minecraft/world/level/chunk/LevelChunk.java -@@ -360,6 +360,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - - @Nullable - public BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving, boolean doPlace) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, pos, "Updating block asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - // CraftBukkit end - int y = pos.getY(); - LevelChunkSection section = this.getSection(this.getSectionIndex(y)); -diff --git a/net/minecraft/world/level/entity/EntityTickList.java b/net/minecraft/world/level/entity/EntityTickList.java -index 423779a2b690f387a4f0bd07b97b50e0baefda76..24f9632e73d73c2ad68ebf30eb0e4cca7befae2d 100644 ---- a/net/minecraft/world/level/entity/EntityTickList.java -+++ b/net/minecraft/world/level/entity/EntityTickList.java -@@ -10,17 +10,26 @@ import net.minecraft.world.entity.Entity; - - public class EntityTickList { - private final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system -+ // SparklyPaper start - parallel world ticking -+ // Used to track async entity additions/removals/loops -+ private final net.minecraft.server.level.ServerLevel serverLevel; -+ public EntityTickList(net.minecraft.server.level.ServerLevel serverLevel) { -+ this.serverLevel = serverLevel; -+ } -+ // SparklyPaper end - - private void ensureActiveIsNotIterated() { - // Paper - rewrite chunk system - } - - public void add(Entity entity) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(entity, "Asynchronous entity ticklist addition"); // Paper // SparklyPaper - parallel world ticking (additional concurrency issues logs) - this.ensureActiveIsNotIterated(); - this.entities.add(entity); // Paper - rewrite chunk system - } - - public void remove(Entity entity) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(entity, "Asynchronous entity ticklist removal"); // Paper // SparklyPaper - parallel world ticking (additional concurrency issues logs) - this.ensureActiveIsNotIterated(); - this.entities.remove(entity); // Paper - rewrite chunk system - } -@@ -30,6 +39,7 @@ public class EntityTickList { - } - - public void forEach(Consumer entity) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverLevel, "Asynchronous entity ticklist iteration"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - // Paper start - rewrite chunk system - // To ensure nothing weird happens with dimension travelling, do not iterate over new entries... - // (by dfl iterator() is configured to not iterate over new entries) -diff --git a/net/minecraft/world/level/saveddata/maps/MapIndex.java b/net/minecraft/world/level/saveddata/maps/MapIndex.java -index ffe604f8397a002800e6ecc2f878d0f6f1c98703..ee022449c1e00a106687496a1dfb98fc0d86fb72 100644 ---- a/net/minecraft/world/level/saveddata/maps/MapIndex.java -+++ b/net/minecraft/world/level/saveddata/maps/MapIndex.java -@@ -34,17 +34,20 @@ public class MapIndex extends SavedData { - - @Override - public CompoundTag save(CompoundTag tag, HolderLookup.Provider registries) { -+ synchronized (this.usedAuxIds) { // SparklyPaper start - make map data thread-safe - for (Entry entry : this.usedAuxIds.object2IntEntrySet()) { - tag.putInt(entry.getKey(), entry.getIntValue()); - } -- -+ } // SparklyPaper end - make map data thread-safe - return tag; - } - - public MapId getFreeAuxValueForMap() { -+ synchronized (this.usedAuxIds) { // SparklyPaper start - make map data thread-safe - int i = this.usedAuxIds.getInt("map") + 1; - this.usedAuxIds.put("map", i); - this.setDirty(); - return new MapId(i); -+ } // SparklyPaper end - make map data thread-safe - } - } diff --git a/sparklypaper-server/minecraft-patches/features/0019-SPARKLYPOWER-Remap-SparklyPower-hacky-legacy-NBT-tag.patch b/sparklypaper-server/minecraft-patches/features/0019-SPARKLYPOWER-Remap-SparklyPower-hacky-legacy-NBT-tag.patch deleted file mode 100644 index 70bbb86..0000000 --- a/sparklypaper-server/minecraft-patches/features/0019-SPARKLYPOWER-Remap-SparklyPower-hacky-legacy-NBT-tag.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Sat, 1 Jun 2024 01:22:41 -0300 -Subject: [PATCH] SPARKLYPOWER Remap SparklyPower hacky legacy NBT tags - -This is only useful for us in SparklyPower, but yeah... - -diff --git a/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterItemStackToDataComponents.java b/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterItemStackToDataComponents.java -index 2d29d89cc45866822189a62bffbe1a8fe57c477b..688230454b42fd7da72833ca8fe631e6fba06eb9 100644 ---- a/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterItemStackToDataComponents.java -+++ b/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterItemStackToDataComponents.java -@@ -1221,6 +1221,7 @@ public final class ConverterItemStackToDataComponents { - ret.setString("id", this.id); - ret.setInt("count", this.count); - if (!this.tag.isEmpty()) { -+ net.sparklypower.sparklypaper.LegacyNBTRemapper.INSTANCE.remap(this.tag); // SparklyPaper - Remap SparklyPower hacky legacy NBT tags - this.components.setMap("minecraft:custom_data", this.tag); - } - diff --git a/sparklypaper-server/minecraft-patches/features/0020-SPARKLYPOWER-Add-custom-blocks.patch b/sparklypaper-server/minecraft-patches/features/0020-SPARKLYPOWER-Add-custom-blocks.patch deleted file mode 100644 index 823e35c..0000000 --- a/sparklypaper-server/minecraft-patches/features/0020-SPARKLYPOWER-Add-custom-blocks.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Wed, 12 Jun 2024 11:53:09 -0300 -Subject: [PATCH] SPARKLYPOWER Add custom blocks - - -diff --git a/net/minecraft/world/level/block/Blocks.java b/net/minecraft/world/level/block/Blocks.java -index 0401a5e88fe7840ae667748409411ab73888799c..d83e8b92b77f6b8179b24f07eae528dda5f12ed2 100644 ---- a/net/minecraft/world/level/block/Blocks.java -+++ b/net/minecraft/world/level/block/Blocks.java -@@ -6775,6 +6775,52 @@ public class Blocks { - public static final Block POTTED_CLOSED_EYEBLOSSOM = register( - "potted_closed_eyeblossom", properties -> new FlowerPotBlock(CLOSED_EYEBLOSSOM, properties), flowerPotProperties().randomTicks() - ); -+ // SparklyPaper start - SparklyPower Survival custom blocks -+ // Blocks' strength should be synced with the replaced block on the client side! -+ public static final Block SPARKLYPOWER_RAINBOW_WOOL = register( -+ "sparklypower_rainbow_wool", -+ Block::new, -+ BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_RED).strength(0.5F).sound(SoundType.GRASS) -+ ); -+ public static final Block SPARKLYPOWER_RAINBOW_CONCRETE = register( -+ "sparklypower_rainbow_concrete", -+ Block::new, -+ BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_RED).strength(0.5F).sound(SoundType.GRASS) -+ ); -+ public static final Block SPARKLYPOWER_RAINBOW_TERRACOTTA = register( -+ "sparklypower_rainbow_terracotta", -+ Block::new, -+ BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_RED).strength(0.5F).sound(SoundType.GRASS) -+ ); -+ public static final Block SPARKLYPOWER_ASPHALT_SERVER = register( -+ "sparklypower_asphalt_server", -+ Block::new, -+ BlockBehaviour.Properties.of() -+ .mapColor(MapColor.COLOR_BLACK) -+ .instrument(NoteBlockInstrument.BASEDRUM) -+ .requiresCorrectToolForDrops() -+ .strength(1.5F, 6.0F) -+ ); -+ public static final Block SPARKLYPOWER_ASPHALT_SERVER_SLAB = register( -+ "sparklypower_asphalt_server_slab", -+ SlabBlock::new, -+ BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLACK).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(2.0F, 6.0F) -+ ); -+ public static final Block SPARKLYPOWER_ASPHALT_PLAYER = register( -+ "sparklypower_asphalt_player", -+ Block::new, -+ BlockBehaviour.Properties.of() -+ .mapColor(MapColor.COLOR_BLACK) -+ .instrument(NoteBlockInstrument.BASEDRUM) -+ .requiresCorrectToolForDrops() -+ .strength(1.5F, 6.0F) -+ ); -+ public static final Block SPARKLYPOWER_ASPHALT_PLAYER_SLAB = register( -+ "sparklypower_asphalt_player_slab", -+ SlabBlock::new, -+ BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLACK).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(2.0F, 6.0F) -+ ); -+ // SparklyPaper end - - private static ToIntFunction litBlockEmission(int lightValue) { - return state -> state.getValue(BlockStateProperties.LIT) ? lightValue : 0; diff --git a/sparklypaper-server/minecraft-patches/features/0021-Add-EntityGetProjectileForWeaponEvent.patch b/sparklypaper-server/minecraft-patches/features/0021-Add-EntityGetProjectileForWeaponEvent.patch deleted file mode 100644 index fd0a470..0000000 --- a/sparklypaper-server/minecraft-patches/features/0021-Add-EntityGetProjectileForWeaponEvent.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Sun, 23 Feb 2025 18:53:43 -0300 -Subject: [PATCH] Add EntityGetProjectileForWeaponEvent - - -diff --git a/net/minecraft/world/entity/monster/Monster.java b/net/minecraft/world/entity/monster/Monster.java -index d0d3c825cf8088df4794cf5bfde12a69f4d71754..4cad07ae00eb34b51b8ef3f25f0abf8ed0d267c5 100644 ---- a/net/minecraft/world/entity/monster/Monster.java -+++ b/net/minecraft/world/entity/monster/Monster.java -@@ -137,6 +137,12 @@ public abstract class Monster extends PathfinderMob implements Enemy { - @Override - public ItemStack getProjectile(ItemStack shootable) { - if (shootable.getItem() instanceof ProjectileWeaponItem) { -+ // SparklyPaper start - Add EntityGetProjectileForWeaponEvent -+ net.sparklypower.sparklypaper.event.entity.EntityGetProjectileForWeaponEvent event = new net.sparklypower.sparklypaper.event.entity.EntityGetProjectileForWeaponEvent(this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(shootable)); -+ event.callEvent(); -+ if (event.getArrow() != null) -+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getArrow()); -+ // SparklyPaper end - Predicate supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getSupportedHeldProjectiles(); - ItemStack heldProjectile = ProjectileWeaponItem.getHeldProjectile(this, supportedHeldProjectiles); - return heldProjectile.isEmpty() ? new ItemStack(Items.ARROW) : heldProjectile; -diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index a0813aa9ebf5b32375b1bc9f294d8fc34cc867fe..3e89356b177b5033fb58de314b0cb0f591ec4e5b 100644 ---- a/net/minecraft/world/entity/player/Player.java -+++ b/net/minecraft/world/entity/player/Player.java -@@ -2239,6 +2239,12 @@ public abstract class Player extends LivingEntity { - if (!(shootable.getItem() instanceof ProjectileWeaponItem)) { - return ItemStack.EMPTY; - } else { -+ // SparklyPaper start - Add EntityGetProjectileForWeaponEvent -+ net.sparklypower.sparklypaper.event.entity.EntityGetProjectileForWeaponEvent event = new net.sparklypower.sparklypaper.event.entity.EntityGetProjectileForWeaponEvent(this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(shootable)); -+ event.callEvent(); -+ if (event.getArrow() != null) -+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getArrow()); -+ // SparklyPaper end - final org.apache.commons.lang3.mutable.MutableBoolean anyEventCancelled = new org.apache.commons.lang3.mutable.MutableBoolean(); // Paper - PlayerReadyArrowEvent - Predicate supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getSupportedHeldProjectiles().and(item -> this.tryReadyArrow(shootable, item, anyEventCancelled)); // Paper - PlayerReadyArrowEvent - ItemStack heldProjectile = ProjectileWeaponItem.getHeldProjectile(this, supportedHeldProjectiles); diff --git a/sparklypaper-server/minecraft-patches/features/0005-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/server/MinecraftServer.java.patch similarity index 56% rename from sparklypaper-server/minecraft-patches/features/0005-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch rename to sparklypaper-server/minecraft-patches/sources/net/minecraft/server/MinecraftServer.java.patch index 3fa9012..06fe2a9 100644 --- a/sparklypaper-server/minecraft-patches/features/0005-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/server/MinecraftServer.java.patch @@ -1,28 +1,14 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Sun, 19 Nov 2023 12:35:16 -0300 -Subject: [PATCH] Skip EntityScheduler's executeTick checks if there isn't any - tasks to be run - -On each tick, Paper runs EntityScheduler's executeTick of each entity. This is a bit expensive, due to ArrayDeque's size() call because it ain't a simple "get the current queue size" function, due to the thread checks, and because it needs to iterate all entities in all worlds. - -To avoid the hefty ArrayDeque's size() call, we check if we *really* need to execute the executeTick, by adding all entities with scheduled tasks to a global set. - -Most entities won't have any scheduled tasks, so this is a nice performance bonus. These optimizations, however, wouldn't work in a Folia environment, but because in SparklyPaper executeTick is always executed on the main thread, it ain't an issue for us (yay). - -diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index ae220a732c78ab076261f20b5a54c71d7fceb407..6ad6bfe60026be304aa2178d5f04a79531cc66a6 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -303,6 +303,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation + public final Set entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (concurrent because plugins may schedule tasks async) public static S spin(Function threadFunction) { - ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system -@@ -1659,6 +1660,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop atomicReference = new AtomicReference<>(); +@@ -1657,6 +_,18 @@ this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit // Paper start - Folia scheduler API ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) org.bukkit.Bukkit.getGlobalRegionScheduler()).tick(); @@ -41,12 +27,29 @@ index ae220a732c78ab076261f20b5a54c71d7fceb407..6ad6bfe60026be304aa2178d5f04a795 getAllLevels().forEach(level -> { for (final net.minecraft.world.entity.Entity entity : level.getEntities().getAll()) { if (entity.isRemoved()) { -@@ -1670,6 +1683,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Mon, 13 Jan 2025 14:19:31 -0300 -Subject: [PATCH] Skip "distanceToSqr" call in "ServerEntity#sendChanges" if - the delta movement hasn't changed - -The "distanceToSqr" call is a bit expensive, so avoiding it is pretty nice, around ~15% calls are skipped with this check - -We could also check if the x,y,z coordinates are equal, but for now, let's just keep the identity check, which also helps us since Minecraft's code does reuse the original delta movement Vec3 object - -diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java -index 0fb253aa55a24b56b17f524b3261c5b75c7d7e59..8d0c259efc31de7de0ca5b900376677552e81f81 100644 --- a/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java -@@ -195,6 +195,7 @@ public class ServerEntity { +@@ -205,6 +_,7 @@ if (this.entity.hasImpulse || this.trackDelta || this.entity instanceof LivingEntity && ((LivingEntity)this.entity).isFallFlying()) { Vec3 deltaMovement = this.entity.getDeltaMovement(); @@ -20,7 +8,7 @@ index 0fb253aa55a24b56b17f524b3261c5b75c7d7e59..8d0c259efc31de7de0ca5b9003766775 double d = deltaMovement.distanceToSqr(this.lastSentMovement); if (d > 1.0E-7 || d > 0.0 && deltaMovement.lengthSqr() == 0.0) { this.lastSentMovement = deltaMovement; -@@ -212,6 +213,7 @@ public class ServerEntity { +@@ -222,6 +_,7 @@ this.broadcast.accept(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.lastSentMovement)); } } diff --git a/sparklypaper-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch new file mode 100644 index 0000000..d9422fe --- /dev/null +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/server/level/ServerLevel.java ++++ b/net/minecraft/server/level/ServerLevel.java +@@ -562,6 +_,12 @@ + } + // Paper end - chunk tick iteration + ++ // SparklyPaper start - track world's MSPT ++ public final MinecraftServer.TickTimes tickTimes5s = new MinecraftServer.TickTimes(100); ++ public final MinecraftServer.TickTimes tickTimes10s = new MinecraftServer.TickTimes(200); ++ public final MinecraftServer.TickTimes tickTimes60s = new MinecraftServer.TickTimes(1200); ++ // SparklyPaper end ++ + public ServerLevel( + MinecraftServer server, + Executor dispatcher, diff --git a/sparklypaper-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch new file mode 100644 index 0000000..f09c1f7 --- /dev/null +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -0,0 +1,131 @@ +--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -581,6 +_,31 @@ + LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7)); + } + ++ // SparklyPaper start - Add PlayerMoveControllableVehicleEvent ++ org.bukkit.entity.Player craftPlayer = this.getCraftPlayer(); ++ org.bukkit.entity.Entity bukkitVehicle = rootVehicle.getBukkitEntity(); ++ if (bukkitVehicle instanceof org.bukkit.entity.Vehicle) { ++ net.sparklypower.sparklypaper.event.player.PlayerMoveControllableVehicleEvent playerMoveControllableVehicleEvent = new net.sparklypower.sparklypaper.event.player.PlayerMoveControllableVehicleEvent( ++ craftPlayer, ++ (org.bukkit.entity.Vehicle) bukkitVehicle, ++ new org.bukkit.Location(craftPlayer.getWorld(), x, y, z, f, f1), ++ new org.bukkit.Location(craftPlayer.getWorld(), d, d1, d2, f, f1) ++ ); ++ if (!playerMoveControllableVehicleEvent.callEvent()) { ++ // Cancelled, move back! ++ rootVehicle.absSnapTo(x, y, z, f, f1); ++ this.player.absSnapTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // CraftBukkit ++ this.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle)); ++ return; ++ } ++ d = playerMoveControllableVehicleEvent.getTo().x(); ++ d1 = playerMoveControllableVehicleEvent.getTo().y(); ++ d2 = playerMoveControllableVehicleEvent.getTo().z(); ++ f = playerMoveControllableVehicleEvent.getTo().getYaw(); ++ f1 = playerMoveControllableVehicleEvent.getTo().getPitch(); ++ } ++ // SparklyPaper end ++ + rootVehicle.absSnapTo(d, d1, d2, f, f1); + this.player.absSnapTo(d, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit + // Paper start - optimise out extra getCubes +@@ -1468,7 +_,7 @@ + d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above + d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above + d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above +- boolean flag = d4 > 0.0; ++ boolean flag = d4 > 0.0; // SparklyPaper - diff on change, used to reset the fall distance, checks if d7 is > 0.0D (player is moving upwards) + if (this.player.onGround() && !packet.isOnGround() && flag) { + // Paper start - Add PlayerJumpEvent + org.bukkit.entity.Player player = this.getCraftPlayer(); +@@ -1502,7 +_,37 @@ + + boolean flag1 = this.player.verticalCollisionBelow; + this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5)); +- this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move ++ // SparklyPaper start - Add PlayerPreMoveEvent event ++ boolean isOnGround = packet.isOnGround(); ++ boolean horizontalCollision = packet.horizontalCollision(); ++ if (net.sparklypower.sparklypaper.event.player.PlayerPreMoveEvent.getHandlerList().getRegisteredListeners().length != 0) { ++ org.bukkit.entity.Player player = this.getCraftPlayer(); ++ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. ++ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. ++ ++ // If the packet contains movement information then we update the To location with the correct XYZ. ++ if (packet.hasPos) { ++ to.setX(packet.x); ++ to.setY(packet.y); ++ to.setZ(packet.z); ++ } ++ ++ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. ++ if (packet.hasRot) { ++ to.setYaw(packet.yRot); ++ to.setPitch(packet.xRot); ++ } ++ ++ net.sparklypower.sparklypaper.event.player.PlayerPreMoveEvent event = new net.sparklypower.sparklypaper.event.player.PlayerPreMoveEvent(player, from, to, packet.isOnGround(), packet.horizontalCollision(), flag); ++ ++ if (event.callEvent()) { ++ isOnGround = event.isOnGround(); ++ horizontalCollision = event.isHorizontalCollision(); ++ flag = event.isResetFallDistance(); ++ } ++ } ++ // SparklyPaper end ++ this.player.onGround = isOnGround; // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move // SparklyPaper - Add PlayerPreMoveEvent + final boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... + // Paper start - prevent position desync + if (this.awaitingPositionFromClient != null) { +@@ -1636,14 +_,14 @@ + && this.noBlocksAround(this.player); + this.player.serverLevel().getChunkSource().move(this.player); + Vec3 vec3 = new Vec3(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z); +- this.player.setOnGroundWithMovement(packet.isOnGround(), packet.horizontalCollision(), vec3); +- this.player.doCheckFallDamage(vec3.x, vec3.y, vec3.z, packet.isOnGround()); ++ this.player.setOnGroundWithMovement(isOnGround, horizontalCollision, vec3); // SparklyPaper - Add PlayerPreMoveEvent ++ this.player.doCheckFallDamage(vec3.x, vec3.y, vec3.z, isOnGround); // SparklyPaper - Add PlayerPreMoveEvent + this.handlePlayerKnownMovement(vec3); + if (flag) { + this.player.resetFallDistance(); + } + +- if (packet.isOnGround() ++ if (isOnGround // SparklyPaper - Add PlayerPreMoveEvent + || this.player.hasLandedInLiquid() + || this.player.onClimbable() + || this.player.isSpectator() +@@ -1658,7 +_,7 @@ + this.lastGoodZ = this.player.getZ(); + } else { + this.internalTeleport(x, y, z, f, f1); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet. +- this.player.doCheckFallDamage(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z, packet.isOnGround()); ++ this.player.doCheckFallDamage(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z, isOnGround); // SparklyPaper - Add PlayerPreMoveEvent + this.player.removeLatestMovementRecordingBatch(); + } + } +@@ -3163,6 +_,21 @@ + } else { + event = new CraftItemEvent(recipe, inventory, type, slotNum, click, action); + } ++ // SparklyPaper start - add CraftItemRecipeEvent ++ // We will pigback a bit on the current implementation ++ net.sparklypower.sparklypaper.event.inventory.CraftItemRecipeEvent craftItemRecipeEvent = new net.sparklypower.sparklypaper.event.inventory.CraftItemRecipeEvent( ++ ((org.bukkit.inventory.CraftingInventory) top).getMatrix(), // We cannot use the top inventory directly because (it seems) that the first slot is the "result" slot ++ recipe, ++ event.getCurrentItem() ++ ); ++ if (craftItemRecipeEvent.callEvent()) { ++ event.setCurrentItem(craftItemRecipeEvent.getResult()); ++ } else { ++ event.setCancelled(true); ++ cancelled = true; ++ event.setCurrentItem(craftItemRecipeEvent.getResult()); ++ } ++ // SparklyPaper end + } + } + diff --git a/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/entity/monster/Monster.java.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/entity/monster/Monster.java.patch new file mode 100644 index 0000000..537eb60 --- /dev/null +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/entity/monster/Monster.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/monster/Monster.java ++++ b/net/minecraft/world/entity/monster/Monster.java +@@ -137,6 +_,12 @@ + @Override + public ItemStack getProjectile(ItemStack shootable) { + if (shootable.getItem() instanceof ProjectileWeaponItem) { ++ // SparklyPaper start - Add EntityGetProjectileForWeaponEvent ++ net.sparklypower.sparklypaper.event.entity.EntityGetProjectileForWeaponEvent event = new net.sparklypower.sparklypaper.event.entity.EntityGetProjectileForWeaponEvent(this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(shootable)); ++ event.callEvent(); ++ if (event.getArrow() != null) ++ return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getArrow()); ++ // SparklyPaper end + Predicate supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getSupportedHeldProjectiles(); + ItemStack heldProjectile = ProjectileWeaponItem.getHeldProjectile(this, supportedHeldProjectiles); + return heldProjectile.isEmpty() ? new ItemStack(Items.ARROW) : heldProjectile; diff --git a/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/entity/player/Player.java.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/entity/player/Player.java.patch new file mode 100644 index 0000000..cc136ce --- /dev/null +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/entity/player/Player.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/entity/player/Player.java ++++ b/net/minecraft/world/entity/player/Player.java +@@ -2127,6 +_,12 @@ + if (!(shootable.getItem() instanceof ProjectileWeaponItem)) { + return ItemStack.EMPTY; + } else { ++ // SparklyPaper start - Add EntityGetProjectileForWeaponEvent ++ net.sparklypower.sparklypaper.event.entity.EntityGetProjectileForWeaponEvent event = new net.sparklypower.sparklypaper.event.entity.EntityGetProjectileForWeaponEvent(this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(shootable)); ++ event.callEvent(); ++ if (event.getArrow() != null) ++ return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getArrow()); ++ // SparklyPaper end + final org.apache.commons.lang3.mutable.MutableBoolean anyEventCancelled = new org.apache.commons.lang3.mutable.MutableBoolean(); // Paper - PlayerReadyArrowEvent + Predicate supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getSupportedHeldProjectiles().and(item -> this.tryReadyArrow(shootable, item, anyEventCancelled)); // Paper - PlayerReadyArrowEvent + ItemStack heldProjectile = ProjectileWeaponItem.getHeldProjectile(this, supportedHeldProjectiles); diff --git a/sparklypaper-server/minecraft-patches/features/0017-Add-PreEntityShootBowEvent.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/item/BowItem.java.patch similarity index 67% rename from sparklypaper-server/minecraft-patches/features/0017-Add-PreEntityShootBowEvent.patch rename to sparklypaper-server/minecraft-patches/sources/net/minecraft/world/item/BowItem.java.patch index 0627769..38c6cbd 100644 --- a/sparklypaper-server/minecraft-patches/features/0017-Add-PreEntityShootBowEvent.patch +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/item/BowItem.java.patch @@ -1,14 +1,6 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Sun, 12 Jan 2025 23:26:44 -0300 -Subject: [PATCH] Add PreEntityShootBowEvent - - -diff --git a/net/minecraft/world/item/BowItem.java b/net/minecraft/world/item/BowItem.java -index 57c933af200551162774f1d473437521e5a85833..9d8a6763efcdd2a57507e208c34faa3f180d5421 100644 --- a/net/minecraft/world/item/BowItem.java +++ b/net/minecraft/world/item/BowItem.java -@@ -33,6 +33,11 @@ public class BowItem extends ProjectileWeaponItem { +@@ -33,6 +_,11 @@ } else { int i = this.getUseDuration(stack, entity) - timeLeft; float powerForTime = getPowerForTime(i); diff --git a/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch new file mode 100644 index 0000000..2f2715e --- /dev/null +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch @@ -0,0 +1,51 @@ +--- a/net/minecraft/world/level/Level.java ++++ b/net/minecraft/world/level/Level.java +@@ -106,7 +_,7 @@ + public static final int TICKS_PER_DAY = 24000; + public static final int MAX_ENTITY_SPAWN_Y = 20000000; + public static final int MIN_ENTITY_SPAWN_Y = -20000000; +- public final List blockEntityTickers = Lists.newArrayList(); ++ public final net.sparklypower.sparklypaper.BlockEntityTickersList blockEntityTickers = new net.sparklypower.sparklypaper.BlockEntityTickersList(); // SparklyPaper - optimize block entity removals + protected final NeighborUpdater neighborUpdater; + private final List pendingBlockEntityTickers = Lists.newArrayList(); + private boolean tickingBlockEntities; +@@ -134,6 +_,7 @@ + + // CraftBukkit start + public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray ++ public net.sparklypower.sparklypaper.configs.SparklyPaperConfig.SparklyPaperWorldConfig sparklyPaperConfig; // SparklyPaper - config files + private final CraftWorld world; + public boolean pvpMode; + public @Nullable org.bukkit.generator.ChunkGenerator generator; +@@ -840,6 +_,7 @@ + // Paper end - getblock optimisations - cache world height/sections + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot + this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config ++ this.sparklyPaperConfig = net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.getWorldSettings(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // SparklyPaper - config files + this.generator = generator; + this.world = new CraftWorld((ServerLevel) this, generator, biomeProvider, environment); + +@@ -1455,13 +_,11 @@ + boolean runsNormally = this.tickRateManager().runsNormally(); + + int tickedEntities = 0; // Paper - rewrite chunk system +- var toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet(); // Paper - Fix MC-117075; use removeAll +- toRemove.add(null); // Paper - Fix MC-117075 + for (this.tileTickPosition = 0; this.tileTickPosition < this.blockEntityTickers.size(); this.tileTickPosition++) { // Paper - Disable tick limiters + TickingBlockEntity tickingBlockEntity = this.blockEntityTickers.get(this.tileTickPosition); + // Spigot end + if (tickingBlockEntity.isRemoved()) { +- toRemove.add(tickingBlockEntity); // Paper - Fix MC-117075; use removeAll ++ this.blockEntityTickers.markAsRemoved(this.tileTickPosition); // SparklyPaper - optimize block entity removals + } else if (runsNormally && this.shouldTickBlocksAt(tickingBlockEntity.getPos())) { + tickingBlockEntity.tick(); + // Paper start - rewrite chunk system +@@ -1471,7 +_,7 @@ + // Paper end - rewrite chunk system + } + } +- this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 ++ this.blockEntityTickers.removeMarkedEntries(); // SparklyPaper - optimize block entity removals + + this.tickingBlockEntities = false; + profilerFiller.pop(); diff --git a/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/Blocks.java.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/Blocks.java.patch new file mode 100644 index 0000000..debb5da --- /dev/null +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/Blocks.java.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/level/block/Blocks.java ++++ b/net/minecraft/world/level/block/Blocks.java +@@ -6899,6 +_,52 @@ + .sound(SoundType.SWEET_BERRY_BUSH) + .pushReaction(PushReaction.DESTROY) + ); ++ // SparklyPaper start - SparklyPower Survival custom blocks ++ // Blocks' strength should be synced with the replaced block on the client side! ++ public static final Block SPARKLYPOWER_RAINBOW_WOOL = register( ++ "sparklypower_rainbow_wool", ++ Block::new, ++ BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_RED).strength(0.5F).sound(SoundType.GRASS) ++ ); ++ public static final Block SPARKLYPOWER_RAINBOW_CONCRETE = register( ++ "sparklypower_rainbow_concrete", ++ Block::new, ++ BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_RED).strength(0.5F).sound(SoundType.GRASS) ++ ); ++ public static final Block SPARKLYPOWER_RAINBOW_TERRACOTTA = register( ++ "sparklypower_rainbow_terracotta", ++ Block::new, ++ BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_RED).strength(0.5F).sound(SoundType.GRASS) ++ ); ++ public static final Block SPARKLYPOWER_ASPHALT_SERVER = register( ++ "sparklypower_asphalt_server", ++ Block::new, ++ BlockBehaviour.Properties.of() ++ .mapColor(MapColor.COLOR_BLACK) ++ .instrument(NoteBlockInstrument.BASEDRUM) ++ .requiresCorrectToolForDrops() ++ .strength(1.5F, 6.0F) ++ ); ++ public static final Block SPARKLYPOWER_ASPHALT_SERVER_SLAB = register( ++ "sparklypower_asphalt_server_slab", ++ SlabBlock::new, ++ BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLACK).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(2.0F, 6.0F) ++ ); ++ public static final Block SPARKLYPOWER_ASPHALT_PLAYER = register( ++ "sparklypower_asphalt_player", ++ Block::new, ++ BlockBehaviour.Properties.of() ++ .mapColor(MapColor.COLOR_BLACK) ++ .instrument(NoteBlockInstrument.BASEDRUM) ++ .requiresCorrectToolForDrops() ++ .strength(1.5F, 6.0F) ++ ); ++ public static final Block SPARKLYPOWER_ASPHALT_PLAYER_SLAB = register( ++ "sparklypower_asphalt_player_slab", ++ SlabBlock::new, ++ BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLACK).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(2.0F, 6.0F) ++ ); ++ // SparklyPaper end + + private static ToIntFunction litBlockEmission(int lightValue) { + return state -> state.getValue(BlockStateProperties.LIT) ? lightValue : 0; diff --git a/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/CrafterBlock.java.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/CrafterBlock.java.patch new file mode 100644 index 0000000..ac94560 --- /dev/null +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/CrafterBlock.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/block/CrafterBlock.java ++++ b/net/minecraft/world/level/block/CrafterBlock.java +@@ -159,6 +_,12 @@ + } + itemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getResult()); + // CraftBukkit end ++ // SparklyPaper - add CraftItemRecipeEvent ++ net.sparklypower.sparklypaper.event.inventory.CraftItemRecipeEvent sparklyEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callCraftItemRecipeEvent(crafterBlockEntity, recipeHolder.toBukkitRecipe(), itemStack); ++ if (sparklyEvent.isCancelled()) ++ return; ++ itemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(sparklyEvent.getResult()); ++ // SparklyPaper end + if (itemStack.isEmpty()) { + level.levelEvent(1050, pos, 0); + } else { diff --git a/sparklypaper-server/minecraft-patches/features/0014-Allow-throttling-hopper-checks-if-the-target-contain.patch b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch similarity index 54% rename from sparklypaper-server/minecraft-patches/features/0014-Allow-throttling-hopper-checks-if-the-target-contain.patch rename to sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch index 318a2fa..4e8bb7b 100644 --- a/sparklypaper-server/minecraft-patches/features/0014-Allow-throttling-hopper-checks-if-the-target-contain.patch +++ b/sparklypaper-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/HopperBlockEntity.java.patch @@ -1,15 +1,6 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Fri, 23 Aug 2024 16:20:45 -0300 -Subject: [PATCH] Allow throttling hopper checks if the target container is - full - - -diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 5cd1326ad5d046c88b2b3449d610a78fa880b4cd..d512f44dcfc480b5608555aa319c93342ae5b208 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -419,6 +419,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -423,6 +_,7 @@ } else { Direction opposite = blockEntity.facing.getOpposite(); if (isFullContainer(attachedContainer, opposite)) { diff --git a/sparklypaper-server/paper-patches/features/0002-SparklyPaper-config-files.patch b/sparklypaper-server/paper-patches/features/0002-SparklyPaper-config-files.patch deleted file mode 100644 index a3c5441..0000000 --- a/sparklypaper-server/paper-patches/features/0002-SparklyPaper-config-files.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 13 Jan 2025 13:20:49 -0300 -Subject: [PATCH] SparklyPaper config files - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index cf5bcb0ebc79c318d106695e39ad2883a5734aa1..6ef9d7a47ff06f5f07c56c8e103bab550b99a904 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -111,6 +111,7 @@ import net.minecraft.world.level.storage.PlayerDataStorage; - import net.minecraft.world.level.storage.PrimaryLevelData; - import net.minecraft.world.level.validation.ContentValidationException; - import net.minecraft.world.phys.Vec3; -+import net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils; - import org.bukkit.BanList; - import org.bukkit.Bukkit; - import org.bukkit.ChatColor; -@@ -1088,6 +1089,7 @@ public final class CraftServer implements Server { - - org.spigotmc.SpigotConfig.init((File) this.console.options.valueOf("spigot-settings")); // Spigot - this.console.paperConfigurations.reloadConfigs(this.console); -+ net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.init((File) console.options.valueOf("sparklypaper-settings")); // SparklyPaper - for (ServerLevel world : this.console.getAllLevels()) { - // world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty - world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean)) -@@ -1103,6 +1105,7 @@ public final class CraftServer implements Server { - } - } - world.spigotConfig.init(); // Spigot -+ world.sparklyPaperConfig = SparklyPaperConfigUtils.INSTANCE.getWorldSettings(world.serverLevelData.getLevelName()); // SparklyPaper - } - - Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper -@@ -1120,6 +1123,7 @@ public final class CraftServer implements Server { - org.spigotmc.SpigotConfig.registerCommands(); // Spigot - io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper - this.spark.registerCommandBeforePlugins(this); // Paper - spark -+ net.sparklypower.sparklypaper.SparklyPaperCommands.INSTANCE.registerCommands(this.console); // SparklyPaper - this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); - this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index bf5343b0847e9f57ffbc7f33714ae6ca62f14332..8cd9a8eb70ebb170a7e0e2f8daa47bd16c457d79 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -176,6 +176,14 @@ public class Main { - .describedAs("Jar file"); - // Paper end - -+ // SparklyPaper Start -+ acceptsAll(asList("sparklypaper", "sparklypaper-settings"), "File for SparklyPaper settings") -+ .withRequiredArg() -+ .ofType(File.class) -+ .defaultsTo(new File("sparklypaper.yml")) -+ .describedAs("Yml file"); -+ // SparklyPaper end -+ - // Paper start - acceptsAll(asList("server-name"), "Name of the server") - .withRequiredArg() diff --git a/sparklypaper-server/paper-patches/features/0003-Fix-concurrency-issues-when-using-imageToBytes.patch b/sparklypaper-server/paper-patches/features/0003-Fix-concurrency-issues-when-using-imageToBytes.patch deleted file mode 100644 index 9ae6745..0000000 --- a/sparklypaper-server/paper-patches/features/0003-Fix-concurrency-issues-when-using-imageToBytes.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 13 Jan 2025 14:27:53 -0300 -Subject: [PATCH] Fix concurrency issues when using imageToBytes - - -diff --git a/src/main/java/org/bukkit/craftbukkit/map/CraftMapColorCache.java b/src/main/java/org/bukkit/craftbukkit/map/CraftMapColorCache.java -index 8149b9c51b78eb5c689b7218a2ca3aab60e73bcf..c983d8d7e79d55c9757add8ac1093a0a9d98e5b3 100644 ---- a/src/main/java/org/bukkit/craftbukkit/map/CraftMapColorCache.java -+++ b/src/main/java/org/bukkit/craftbukkit/map/CraftMapColorCache.java -@@ -145,7 +145,7 @@ public class CraftMapColorCache implements MapPalette.MapColorCache { - } - - @Override -- public boolean isCached() { -+ public synchronized boolean isCached() { // SparklyPaper - fix concurrency issues when using "imageToBytes" in multiple threads - return this.cached || (!this.running.get() && this.initCache().isDone()); - } - diff --git a/sparklypaper-server/paper-patches/features/0005-Optimize-canSee-checks.patch b/sparklypaper-server/paper-patches/features/0005-Optimize-canSee-checks.patch deleted file mode 100644 index aaee261..0000000 --- a/sparklypaper-server/paper-patches/features/0005-Optimize-canSee-checks.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 13 Jan 2025 15:04:15 -0300 -Subject: [PATCH] Optimize canSee checks - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 3260f20b667918dd7cd641d5d96688721fce2f9c..1117e41a6fd3c45e68b480e009fa8b3a6e2badaa 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -214,7 +214,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - private boolean hasPlayedBefore = false; - private final ConversationTracker conversationTracker = new ConversationTracker(); - private final Set channels = new HashSet(); -- private final Map>> invertedVisibilityEntities = new HashMap<>(); -+ private final Map>> invertedVisibilityEntities = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // SparklyPaper - optimize canSee checks - private final Set unlistedEntities = new HashSet<>(); // Paper - Add Listing API for Player - private static final WeakHashMap> pluginWeakReferences = new WeakHashMap<>(); - private int hash = 0; -@@ -2263,9 +2263,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public boolean canSee(org.bukkit.entity.Entity entity) { -- return this.equals(entity) || entity.isVisibleByDefault() ^ this.invertedVisibilityEntities.containsKey(entity.getUniqueId()); // SPIGOT-7312: Can always see self -+ return this.equals(entity) || entity.isVisibleByDefault() ^ (!invertedVisibilityEntities.isEmpty() && this.invertedVisibilityEntities.containsKey(entity.getUniqueId())); // SPIGOT-7312: Can always see self // SparklyPaper - optimize canSee checks - } - -+ // SparklyPaper - optimize canSee checks -+ // The check in ChunkMap#updatePlayer already rejects if it is the same entity, so we don't need to check it twice, especially because CraftPlayer's equals check is a bit expensive -+ public boolean canSeeChunkMapUpdatePlayer(org.bukkit.entity.Entity entity) { -+ return entity.isVisibleByDefault() ^ (!invertedVisibilityEntities.isEmpty() && this.invertedVisibilityEntities.containsKey(entity.getUniqueId())); // SPIGOT-7312: Can always see self // SparklyPaper - optimize canSee checks -+ } -+ // SparklyPaper end -+ - public boolean canSeePlayer(UUID uuid) { - org.bukkit.entity.Entity entity = this.getServer().getPlayer(uuid); - diff --git a/sparklypaper-server/paper-patches/features/0009-Parallel-world-ticking.patch b/sparklypaper-server/paper-patches/features/0009-Parallel-world-ticking.patch deleted file mode 100644 index 588a5f0..0000000 --- a/sparklypaper-server/paper-patches/features/0009-Parallel-world-ticking.patch +++ /dev/null @@ -1,628 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Tue, 7 Nov 2023 01:34:14 -0300 -Subject: [PATCH] Parallel world ticking - -"mom can we have folia?" "we already have folia at home" folia at home: - -diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java -index 69cdd304d255d52c9b7dc9b6a33ffdb630b79abe..d8314bae08146f75442c342275d2e94b316829bd 100644 ---- a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java -+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java -@@ -14,6 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger; - public class TickThread extends Thread { - - private static final Logger LOGGER = LoggerFactory.getLogger(TickThread.class); -+ public static final boolean HARD_THROW = !Boolean.getBoolean("sparklypaper.disableHardThrow"); // SparklyPaper - parallel world ticking - THIS SHOULD NOT BE DISABLED SINCE IT CAN CAUSE DATA CORRUPTION!!! Anyhow, for production servers, if you want to make a test run to see if the server could crash, you can test it with this disabled - - private static String getThreadContext() { - return "thread=" + Thread.currentThread().getName(); -@@ -26,14 +27,15 @@ public class TickThread extends Thread { - public static void ensureTickThread(final String reason) { - if (!isTickThread()) { - LOGGER.error("Thread failed main thread check: " + reason + ", context=" + getThreadContext(), new Throwable()); -- throw new IllegalStateException(reason); -+ if (HARD_THROW) -+ throw new IllegalStateException(reason); - } - } - - public static void ensureTickThread(final Level world, final BlockPos pos, final String reason) { - if (!isTickThreadFor(world, pos)) { - final String ex = "Thread failed main thread check: " + -- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos; -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + " - " + getTickThreadInformation(world.getServer()); - LOGGER.error(ex, new Throwable()); - throw new IllegalStateException(ex); - } -@@ -42,7 +44,7 @@ public class TickThread extends Thread { - public static void ensureTickThread(final Level world, final BlockPos pos, final int blockRadius, final String reason) { - if (!isTickThreadFor(world, pos, blockRadius)) { - final String ex = "Thread failed main thread check: " + -- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius; -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius + " - " + getTickThreadInformation(world.getServer()); - LOGGER.error(ex, new Throwable()); - throw new IllegalStateException(ex); - } -@@ -51,7 +53,7 @@ public class TickThread extends Thread { - public static void ensureTickThread(final Level world, final ChunkPos pos, final String reason) { - if (!isTickThreadFor(world, pos)) { - final String ex = "Thread failed main thread check: " + -- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos; -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos + " - " + getTickThreadInformation(world.getServer()); - LOGGER.error(ex, new Throwable()); - throw new IllegalStateException(ex); - } -@@ -60,7 +62,7 @@ public class TickThread extends Thread { - public static void ensureTickThread(final Level world, final int chunkX, final int chunkZ, final String reason) { - if (!isTickThreadFor(world, chunkX, chunkZ)) { - final String ex = "Thread failed main thread check: " + -- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ); -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ) + " - " + getTickThreadInformation(world.getServer()); - LOGGER.error(ex, new Throwable()); - throw new IllegalStateException(ex); - } -@@ -69,7 +71,7 @@ public class TickThread extends Thread { - public static void ensureTickThread(final Entity entity, final String reason) { - if (!isTickThreadFor(entity)) { - final String ex = "Thread failed main thread check: " + -- reason + ", context=" + getThreadContext() + ", entity=" + EntityUtil.dumpEntity(entity); -+ reason + ", context=" + getThreadContext() + ", entity=" + EntityUtil.dumpEntity(entity) + " - " + getTickThreadInformation(entity.getServer()); - LOGGER.error(ex, new Throwable()); - throw new IllegalStateException(ex); - } -@@ -78,7 +80,7 @@ public class TickThread extends Thread { - public static void ensureTickThread(final Level world, final AABB aabb, final String reason) { - if (!isTickThreadFor(world, aabb)) { - final String ex = "Thread failed main thread check: " + -- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb; -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb + " - " + getTickThreadInformation(world.getServer()); - LOGGER.error(ex, new Throwable()); - throw new IllegalStateException(ex); - } -@@ -87,12 +89,74 @@ public class TickThread extends Thread { - public static void ensureTickThread(final Level world, final double blockX, final double blockZ, final String reason) { - if (!isTickThreadFor(world, blockX, blockZ)) { - final String ex = "Thread failed main thread check: " + -- reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ); -+ reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ) + " - " + getTickThreadInformation(world.getServer()); - LOGGER.error(ex, new Throwable()); - throw new IllegalStateException(ex); - } - } - -+ // SparklyPaper - parallel world ticking -+ // This is an additional method to check if the tick thread is bound to a specific world because, by default, Paper's isTickThread methods do not provide this information -+ // Because we only tick worlds in parallel (instead of regions), we can use this for our checks -+ public static void ensureTickThread(final net.minecraft.server.level.ServerLevel world, final String reason) { -+ if (!isTickThreadFor(world)) { -+ LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason + " @ world " + world.getWorld().getName() + " - " + getTickThreadInformation(world.getServer()), new Throwable()); -+ if (HARD_THROW) -+ throw new IllegalStateException(reason); -+ } -+ } -+ -+ // SparklyPaper - parallel world ticking -+ // This is an additional method to check if it is a tick thread but ONLY a tick thread -+ public static void ensureOnlyTickThread(final String reason) { -+ boolean isTickThread = isTickThread(); -+ boolean isServerLevelTickThread = isServerLevelTickThread(); -+ if (!isTickThread || isServerLevelTickThread) { -+ LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread ONLY tick thread check: " + reason, new Throwable()); -+ if (HARD_THROW) -+ throw new IllegalStateException(reason); -+ } -+ } -+ -+ // SparklyPaper - parallel world ticking -+ // This is an additional method to check if the tick thread is bound to a specific world or if it is an async thread. -+ public static void ensureTickThreadOrAsyncThread(final net.minecraft.server.level.ServerLevel world, final String reason) { -+ boolean isValidTickThread = isTickThreadFor(world); -+ boolean isAsyncThread = !isTickThread(); -+ boolean isValid = isAsyncThread || isValidTickThread; -+ if (!isValid) { -+ LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread or async thread check: " + reason + " @ world " + world.getWorld().getName() + " - " + getTickThreadInformation(world.getServer()), new Throwable()); -+ if (HARD_THROW) -+ throw new IllegalStateException(reason); -+ } -+ } -+ -+ public static String getTickThreadInformation(net.minecraft.server.MinecraftServer minecraftServer) { -+ StringBuilder sb = new StringBuilder(); -+ Thread currentThread = Thread.currentThread(); -+ sb.append("Is tick thread? "); -+ sb.append(currentThread instanceof TickThread); -+ sb.append("; Is server level tick thread? "); -+ sb.append(currentThread instanceof ServerLevelTickThread); -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ sb.append("; Currently ticking level: "); -+ if (serverLevelTickThread.currentlyTickingServerLevel != null) { -+ sb.append(serverLevelTickThread.currentlyTickingServerLevel.getWorld().getName()); -+ } else { -+ sb.append("null"); -+ } -+ } -+ sb.append("; Is iterating over levels? "); -+ sb.append(minecraftServer.isIteratingOverLevels); -+ sb.append("; Are we going to hard throw? "); -+ sb.append(HARD_THROW); -+ return sb.toString(); -+ } -+ -+ public static boolean isServerLevelTickThread() { -+ return Thread.currentThread() instanceof ServerLevelTickThread; -+ } -+ - public final int id; /* We don't override getId as the spec requires that it be unique (with respect to all other threads) */ - - private static final AtomicInteger ID_GENERATOR = new AtomicInteger(); -@@ -127,7 +191,11 @@ public class TickThread extends Thread { - } - - public static boolean isTickThreadFor(final Level world, final BlockPos pos) { -- return isTickThread(); -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return currentThread instanceof TickThread; - } - - public static boolean isTickThreadFor(final Level world, final BlockPos pos, final int blockRadius) { -@@ -135,38 +203,103 @@ public class TickThread extends Thread { - } - - public static boolean isTickThreadFor(final Level world, final ChunkPos pos) { -- return isTickThread(); -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return currentThread instanceof TickThread; - } - - public static boolean isTickThreadFor(final Level world, final Vec3 pos) { -- return isTickThread(); -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return currentThread instanceof TickThread; - } - - public static boolean isTickThreadFor(final Level world, final int chunkX, final int chunkZ) { -- return isTickThread(); -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return currentThread instanceof TickThread; - } - - public static boolean isTickThreadFor(final Level world, final AABB aabb) { -- return isTickThread(); -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return currentThread instanceof TickThread; - } - - public static boolean isTickThreadFor(final Level world, final double blockX, final double blockZ) { -- return isTickThread(); -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return currentThread instanceof TickThread; - } - - public static boolean isTickThreadFor(final Level world, final Vec3 position, final Vec3 deltaMovement, final int buffer) { -- return isTickThread(); -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return currentThread instanceof TickThread; - } - - public static boolean isTickThreadFor(final Level world, final int fromChunkX, final int fromChunkZ, final int toChunkX, final int toChunkZ) { -- return isTickThread(); -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return currentThread instanceof TickThread; - } - - public static boolean isTickThreadFor(final Level world, final int chunkX, final int chunkZ, final int radius) { -- return isTickThread(); -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return currentThread instanceof TickThread; -+ } -+ -+ // SparklyPaper - parallel world ticking -+ // This is an additional method to check if the tick thread is bound to a specific world because, by default, Paper's isTickThread methods do not provide this information -+ // Because we only tick worlds in parallel (instead of regions), we can use this for our checks -+ public static boolean isTickThreadFor(final Level world) { -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == world; -+ } else return currentThread instanceof TickThread; - } - - public static boolean isTickThreadFor(final Entity entity) { -- return isTickThread(); -+ if (entity == null) { -+ return true; -+ } -+ -+ Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread instanceof ServerLevelTickThread serverLevelTickThread) { -+ return serverLevelTickThread.currentlyTickingServerLevel == entity.level(); -+ } else return currentThread instanceof TickThread; -+ } -+ -+ // SparklyPaper start - parallel world ticking -+ public static class ServerLevelTickThread extends TickThread { -+ public ServerLevelTickThread(String name) { -+ super(name); -+ } -+ -+ public ServerLevelTickThread(Runnable run, String name) { -+ super(run, name); -+ } -+ -+ public net.minecraft.server.level.ServerLevel currentlyTickingServerLevel; - } -+ // SparklyPaper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 1439d282167dc8a2e66f4896849153b810112988..7feeb6944848a9615fd6807cae2d7558a96ac350 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -455,7 +455,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - } - - private boolean unloadChunk0(int x, int z, boolean save) { -- org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot unload chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - if (!this.isChunkLoaded(x, z)) { - return true; - } -@@ -472,6 +472,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - - @Override - public boolean refreshChunk(int x, int z) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot refresh chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); - if (playerChunk == null) return false; - -@@ -522,7 +523,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - - @Override - public boolean loadChunk(int x, int z, boolean generate) { -- org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.getHandle(), x, z, "May not sync load chunks asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - warnUnsafeChunk("loading a faraway chunk", x, z); // Paper - ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper - -@@ -750,6 +751,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - - @Override - public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, loc.getX(), loc.getZ(), "Cannot generate tree asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - this.world.captureTreeGeneration = true; - this.world.captureBlockStates = true; - boolean grownTree = this.generateTree(loc, type); -@@ -865,6 +867,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - } - public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source, Consumer configurator) { - // Paper end - expand explosion API -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot create explosion asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - net.minecraft.world.level.Level.ExplosionInteraction explosionType; - if (!breakBlocks) { - explosionType = net.minecraft.world.level.Level.ExplosionInteraction.NONE; // Don't break blocks -@@ -956,6 +959,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - - @Override - public int getHighestBlockYAt(int x, int z, org.bukkit.HeightMap heightMap) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x >> 4, z >> 4, "Cannot retrieve chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - warnUnsafeChunk("getting a faraway chunk", x >> 4, z >> 4); // Paper - // Transient load for this tick - return this.world.getChunk(x >> 4, z >> 4).getHeight(CraftHeightMap.toNMS(heightMap), x, z); -@@ -986,6 +990,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - @Override - public void setBiome(int x, int y, int z, Holder bb) { - BlockPos pos = new BlockPos(x, 0, z); -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, pos, "Cannot retrieve chunk asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - if (this.world.hasChunkAt(pos)) { - net.minecraft.world.level.chunk.LevelChunk chunk = this.world.getChunkAt(pos); - -@@ -2289,6 +2294,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - - @Override - public void sendGameEvent(Entity sourceEntity, org.bukkit.GameEvent gameEvent, Vector position) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, position.getX(), position.getZ(), "Cannot send game event asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - getHandle().gameEvent(sourceEntity != null ? ((CraftEntity) sourceEntity).getHandle(): null, net.minecraft.core.registries.BuiltInRegistries.GAME_EVENT.get(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(gameEvent.getKey())).orElseThrow(), org.bukkit.craftbukkit.util.CraftVector.toBlockPos(position)); - } - // Paper end -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 5cb69d0b822e11a99a96aef4f59986d083b079f4..78f9c3f3b068f638570942961ad41969abc9c028 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -75,6 +75,11 @@ public class CraftBlock implements Block { - } - - public net.minecraft.world.level.block.state.BlockState getNMS() { -+ // Folia start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); -+ } -+ // Folia end - parallel world ticking - return this.world.getBlockState(this.position); - } - -@@ -157,6 +162,11 @@ public class CraftBlock implements Block { - } - - private void setData(final byte data, int flag) { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - this.world.setBlock(this.position, CraftMagicNumbers.getBlock(this.getType(), data), flag); - } - -@@ -198,6 +208,12 @@ public class CraftBlock implements Block { - } - - public static boolean setTypeAndData(LevelAccessor world, BlockPos position, net.minecraft.world.level.block.state.BlockState old, net.minecraft.world.level.block.state.BlockState blockData, boolean applyPhysics) { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking -+ - // SPIGOT-611: need to do this to prevent glitchiness. Easier to handle this here (like /setblock) than to fix weirdness in tile entity cleanup - if (old.hasBlockEntity() && blockData.getBlock() != old.getBlock()) { // SPIGOT-3725 remove old tile entity if block changes - // SPIGOT-4612: faster - just clear tile -@@ -343,18 +359,33 @@ public class CraftBlock implements Block { - - @Override - public Biome getBiome() { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - return this.getWorld().getBiome(this.getX(), this.getY(), this.getZ()); - } - - // Paper start - @Override - public Biome getComputedBiome() { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - return this.getWorld().getComputedBiome(this.getX(), this.getY(), this.getZ()); - } - // Paper end - - @Override - public void setBiome(Biome bio) { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - this.getWorld().setBiome(this.getX(), this.getY(), this.getZ(), bio); - } - -@@ -402,6 +433,11 @@ public class CraftBlock implements Block { - - @Override - public boolean isBlockFaceIndirectlyPowered(BlockFace face) { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - int power = this.world.getMinecraftWorld().getSignal(this.position, CraftBlock.blockFaceToNotch(face)); - - Block relative = this.getRelative(face); -@@ -414,6 +450,11 @@ public class CraftBlock implements Block { - - @Override - public int getBlockPower(BlockFace face) { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - int power = 0; - net.minecraft.world.level.Level world = this.world.getMinecraftWorld(); - int x = this.getX(); -@@ -484,6 +525,11 @@ public class CraftBlock implements Block { - - @Override - public boolean breakNaturally() { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - return this.breakNaturally(null); - } - -@@ -543,6 +589,11 @@ public class CraftBlock implements Block { - - @Override - public boolean applyBoneMeal(BlockFace face) { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - Direction direction = CraftBlock.blockFaceToNotch(face); - BlockFertilizeEvent event = null; - ServerLevel world = this.getCraftWorld().getHandle(); -@@ -554,8 +605,8 @@ public class CraftBlock implements Block { - world.captureTreeGeneration = false; - - if (world.capturedBlockStates.size() > 0) { -- TreeType treeType = SaplingBlock.treeType; -- SaplingBlock.treeType = null; -+ TreeType treeType = SaplingBlock.treeTypeRT.get(); // SparklyPaper - parallel world ticking -+ SaplingBlock.treeTypeRT.set(null); // SparklyPaper - parallel world ticking - List blocks = new ArrayList<>(world.capturedBlockStates.values()); - world.capturedBlockStates.clear(); - StructureGrowEvent structureEvent = null; -@@ -644,6 +695,11 @@ public class CraftBlock implements Block { - - @Override - public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode) { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - Preconditions.checkArgument(start != null, "Location start cannot be null"); - Preconditions.checkArgument(this.getWorld().equals(start.getWorld()), "Location start cannot be a different world"); - start.checkFinite(); -@@ -685,6 +741,11 @@ public class CraftBlock implements Block { - - @Override - public boolean canPlace(BlockData data) { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot read world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - Preconditions.checkArgument(data != null, "BlockData cannot be null"); - net.minecraft.world.level.block.state.BlockState iblockdata = ((CraftBlockData) data).getState(); - net.minecraft.world.level.Level world = this.world.getMinecraftWorld(); -@@ -719,6 +780,11 @@ public class CraftBlock implements Block { - - @Override - public void tick() { -+ // SparklyPaper start - parallel world ticking -+ if (world instanceof ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking - final ServerLevel level = this.world.getMinecraftWorld(); - this.getNMS().tick(level, this.position, level.random); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 768d3f93da2522d467183654260a8bd8653588b1..aa7dcdbf16882fd64ff1b62cce8d83a4a372951f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -25,7 +25,7 @@ public abstract class CraftBlockEntityState extends Craft - private final T tileEntity; - private final T snapshot; - public boolean snapshotDisabled; // Paper -- public static boolean DISABLE_SNAPSHOT = false; // Paper -+ public static ThreadLocal DISABLE_SNAPSHOT = ThreadLocal.withInitial(() -> Boolean.FALSE); // SparklyPaper - parallel world ticking - - public CraftBlockEntityState(World world, T tileEntity) { - super(world, tileEntity.getBlockPos(), tileEntity.getBlockState()); -@@ -34,8 +34,8 @@ public abstract class CraftBlockEntityState extends Craft - - try { // Paper - Show blockstate location if we failed to read it - // Paper start -- this.snapshotDisabled = DISABLE_SNAPSHOT; -- if (DISABLE_SNAPSHOT) { -+ this.snapshotDisabled = DISABLE_SNAPSHOT.get(); // SparklyPaper - parallel world ticking -+ if (DISABLE_SNAPSHOT.get()) { // SparklyPaper - parallel world ticking - this.snapshot = this.tileEntity; - } else { - this.snapshot = this.createSnapshot(tileEntity); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..9856860ee2987738bbcad5d752670e30f569ba74 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -@@ -215,6 +215,12 @@ public class CraftBlockState implements BlockState { - LevelAccessor access = this.getWorldHandle(); - CraftBlock block = this.getBlock(); - -+ // SparklyPaper start - parallel world ticking -+ if (access instanceof net.minecraft.server.level.ServerLevel serverWorld) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); -+ } -+ // SparklyPaper end - parallel world ticking -+ - if (block.getType() != this.getType()) { - if (!force) { - return false; -@@ -350,6 +356,7 @@ public class CraftBlockState implements BlockState { - - @Override - public java.util.Collection getDrops(org.bukkit.inventory.ItemStack item, org.bukkit.entity.Entity entity) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(world.getHandle(), position, "Cannot modify world asynchronously"); // SparklyPaper - parallel world ticking - this.requirePlaced(); - net.minecraft.world.item.ItemStack nms = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item); - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java -index 56453454cbd4b9e9270fc833f8ab38d5fa7a3763..ad507c36d89ce8639fbedbb1df0da66bdc96affa 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java -@@ -249,8 +249,8 @@ public final class CraftBlockStates { - net.minecraft.world.level.block.state.BlockState blockData = craftBlock.getNMS(); - BlockEntity tileEntity = craftBlock.getHandle().getBlockEntity(blockPosition); - // Paper start - block state snapshots -- boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; -- CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; -+ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT.get(); // SparklyPaper - parallel world ticking -+ CraftBlockEntityState.DISABLE_SNAPSHOT.set(!useSnapshot); // SparklyPaper - parallel world ticking - try { - // Paper end - CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockPosition, blockData, tileEntity); -@@ -258,7 +258,7 @@ public final class CraftBlockStates { - return blockState; - // Paper start - } finally { -- CraftBlockEntityState.DISABLE_SNAPSHOT = prev; -+ CraftBlockEntityState.DISABLE_SNAPSHOT.set(prev); // SparklyPaper - parallel world ticking - } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 80bb0371eed48dbcb0e4e62dfc7f23f8514bdf77..fc12bcad034ed4fc97029b83360548f226bc2060 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -951,7 +951,7 @@ public class CraftEventFactory { - return CraftEventFactory.handleBlockSpreadEvent(world, source, target, block, 2); - } - -- public static BlockPos sourceBlockOverride = null; // SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. -+ public static final ThreadLocal sourceBlockOverrideRT = new ThreadLocal<>(); // SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. // SparklyPaper - parallel world ticking (this is from Folia, fixes concurrency bugs with sculk catalysts) - - public static boolean handleBlockSpreadEvent(LevelAccessor world, BlockPos source, BlockPos target, net.minecraft.world.level.block.state.BlockState block, int flag) { - // Suppress during worldgen -@@ -963,7 +963,7 @@ public class CraftEventFactory { - CraftBlockState state = CraftBlockStates.getBlockState(world, target, flag); - state.setData(block); - -- BlockSpreadEvent event = new BlockSpreadEvent(state.getBlock(), CraftBlock.at(world, CraftEventFactory.sourceBlockOverride != null ? CraftEventFactory.sourceBlockOverride : source), state); -+ BlockSpreadEvent event = new BlockSpreadEvent(state.getBlock(), CraftBlock.at(world, CraftEventFactory.sourceBlockOverrideRT.get() != null ? CraftEventFactory.sourceBlockOverrideRT.get() : source), state); // SparklyPaper - parallel world ticking - Bukkit.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -@@ -2250,7 +2250,7 @@ public class CraftEventFactory { - CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemStack.copyWithCount(1)); - - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), CraftVector.toBukkit(to)); -- if (!net.minecraft.world.level.block.DispenserBlock.eventFired) { -+ if (!net.minecraft.world.level.block.DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking - if (!event.callEvent()) { - return itemStack; - } diff --git a/sparklypaper-server/paper-patches/features/0006-Track-how-much-MSPT-each-world-used.patch b/sparklypaper-server/paper-patches/files/src/main/java/io/papermc/paper/command/MSPTCommand.java.patch similarity index 79% rename from sparklypaper-server/paper-patches/features/0006-Track-how-much-MSPT-each-world-used.patch rename to sparklypaper-server/paper-patches/files/src/main/java/io/papermc/paper/command/MSPTCommand.java.patch index 8e4b5a6..522be8e 100644 --- a/sparklypaper-server/paper-patches/features/0006-Track-how-much-MSPT-each-world-used.patch +++ b/sparklypaper-server/paper-patches/files/src/main/java/io/papermc/paper/command/MSPTCommand.java.patch @@ -1,14 +1,6 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Mon, 6 Nov 2023 21:54:33 -0300 -Subject: [PATCH] Track how much MSPT each world used - - -diff --git a/src/main/java/io/papermc/paper/command/MSPTCommand.java b/src/main/java/io/papermc/paper/command/MSPTCommand.java -index 8b5293b0c696ef21d0101493ffa41b60bf0bc86b..601198a33adb29316b0617d5390d1620b7c1095c 100644 --- a/src/main/java/io/papermc/paper/command/MSPTCommand.java +++ b/src/main/java/io/papermc/paper/command/MSPTCommand.java -@@ -78,6 +78,46 @@ public final class MSPTCommand extends Command { +@@ -78,6 +_,46 @@ ) ) ); diff --git a/sparklypaper-server/paper-patches/features/0004-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch b/sparklypaper-server/paper-patches/files/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java.patch similarity index 50% rename from sparklypaper-server/paper-patches/features/0004-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch rename to sparklypaper-server/paper-patches/files/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java.patch index a218ea3..0a27de8 100644 --- a/sparklypaper-server/paper-patches/features/0004-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch +++ b/sparklypaper-server/paper-patches/files/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java.patch @@ -1,20 +1,6 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Sun, 19 Nov 2023 12:35:16 -0300 -Subject: [PATCH] Skip EntityScheduler's executeTick checks if there isn't any - tasks to be run - -On each tick, Paper runs EntityScheduler's executeTick of each entity. This is a bit expensive, due to ArrayDeque's size() call because it ain't a simple "get the current queue size" function, due to the thread checks, and because it needs to iterate all entities in all worlds. - -To avoid the hefty ArrayDeque's size() call, we check if we *really* need to execute the executeTick, by adding all entities with scheduled tasks to a global set. - -Most entities won't have any scheduled tasks, so this is a nice performance bonus. These optimizations, however, wouldn't work in a Folia environment, but because in SparklyPaper executeTick is always executed on the main thread, it ain't an issue for us (yay). - -diff --git a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java -index c03608fec96b51e1867f43d8f42e5aefb1520e46..15b21fa3907db1b77ed5b5d1050a37f42d27d5ab 100644 --- a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java +++ b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java -@@ -36,6 +36,7 @@ public final class EntityScheduler { +@@ -36,6 +_,7 @@ * The Entity. Note that it is the CraftEntity, since only that class properly tracks world transfers. */ public final CraftEntity entity; @@ -22,7 +8,7 @@ index c03608fec96b51e1867f43d8f42e5aefb1520e46..15b21fa3907db1b77ed5b5d1050a37f4 private static final record ScheduledTask(Consumer run, Consumer retired) {} -@@ -46,7 +47,8 @@ public final class EntityScheduler { +@@ -46,7 +_,8 @@ private final ArrayDeque currentlyExecuting = new ArrayDeque<>(); @@ -32,7 +18,7 @@ index c03608fec96b51e1867f43d8f42e5aefb1520e46..15b21fa3907db1b77ed5b5d1050a37f4 this.entity = Validate.notNull(entity); } -@@ -61,14 +63,16 @@ public final class EntityScheduler { +@@ -61,14 +_,16 @@ * @throws IllegalStateException If the scheduler is already retired. */ public void retire() { @@ -50,7 +36,7 @@ index c03608fec96b51e1867f43d8f42e5aefb1520e46..15b21fa3907db1b77ed5b5d1050a37f4 // correctly handle and order retiring while running executeTick for (int i = 0, len = this.currentlyExecuting.size(); i < len; ++i) { -@@ -124,6 +128,7 @@ public final class EntityScheduler { +@@ -124,6 +_,7 @@ if (this.tickCount == RETIRED_TICK_COUNT) { return false; } @@ -58,7 +44,7 @@ index c03608fec96b51e1867f43d8f42e5aefb1520e46..15b21fa3907db1b77ed5b5d1050a37f4 this.oneTimeDelayed.computeIfAbsent(this.tickCount + Math.max(1L, delay), (final long keyInMap) -> { return new ArrayList<>(); }).add(task); -@@ -143,6 +148,13 @@ public final class EntityScheduler { +@@ -143,6 +_,13 @@ TickThread.ensureTickThread(thisEntity, "May not tick entity scheduler asynchronously"); final List toRun; synchronized (this.stateLock) { @@ -72,24 +58,3 @@ index c03608fec96b51e1867f43d8f42e5aefb1520e46..15b21fa3907db1b77ed5b5d1050a37f4 if (this.tickCount == RETIRED_TICK_COUNT) { throw new IllegalStateException("Ticking retired scheduler"); } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 6d81a19741868983c54aff6c2c4c0e2bf690ba0d..6a9bd024e855925d4cfdfa84ee70e822166db24a 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -75,7 +75,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftEntity.DATA_TYPE_REGISTRY); - protected net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers - // Paper start - Folia shedulers -- public final io.papermc.paper.threadedregions.EntityScheduler taskScheduler = new io.papermc.paper.threadedregions.EntityScheduler(this); -+ public final io.papermc.paper.threadedregions.EntityScheduler taskScheduler; // = new io.papermc.paper.threadedregions.EntityScheduler(this); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run - private final io.papermc.paper.threadedregions.scheduler.FoliaEntityScheduler apiScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaEntityScheduler(this); - - @Override -@@ -88,6 +88,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - this.server = server; - this.entity = entity; - this.entityType = CraftEntityType.minecraftToBukkit(entity.getType()); -+ this.taskScheduler = new io.papermc.paper.threadedregions.EntityScheduler(this.entity.getServer(), this); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run - } - - public static CraftEntity getEntity(CraftServer server, T entity) { diff --git a/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/CraftServer.java.patch b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/CraftServer.java.patch new file mode 100644 index 0000000..234215f --- /dev/null +++ b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/CraftServer.java.patch @@ -0,0 +1,26 @@ +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1073,6 +_,7 @@ + + org.spigotmc.SpigotConfig.init((File) this.console.options.valueOf("spigot-settings")); // Spigot + this.console.paperConfigurations.reloadConfigs(this.console); ++ net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.init((File) console.options.valueOf("sparklypaper-settings")); // SparklyPaper - config files + for (ServerLevel world : this.console.getAllLevels()) { + // world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty + world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean)) +@@ -1088,6 +_,7 @@ + } + } + world.spigotConfig.init(); // Spigot ++ world.sparklyPaperConfig = net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.getWorldSettings(world.serverLevelData.getLevelName()); // SparklyPaper - config files + } + + Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper +@@ -1105,6 +_,7 @@ + org.spigotmc.SpigotConfig.registerCommands(); // Spigot + io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper + this.spark.registerCommandBeforePlugins(this); // Paper - spark ++ net.sparklypower.sparklypaper.SparklyPaperCommands.INSTANCE.registerCommands(this.console); // SparklyPaper - config files + this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); + this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); + diff --git a/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/Main.java.patch b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/Main.java.patch new file mode 100644 index 0000000..8dad70d --- /dev/null +++ b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/Main.java.patch @@ -0,0 +1,17 @@ +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -165,6 +_,14 @@ + .defaultsTo(new File[] {}) + .describedAs("Jar file"); + ++ // SparklyPaper start - config files ++ acceptsAll(asList("sparklypaper", "sparklypaper-settings"), "File for SparklyPaper settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File("sparklypaper.yml")) ++ .describedAs("Yml file"); ++ // SparklyPaper end ++ + acceptsAll(asList("server-name"), "Name of the server") + .withRequiredArg() + .ofType(String.class) diff --git a/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java.patch b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java.patch new file mode 100644 index 0000000..4764656 --- /dev/null +++ b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java.patch @@ -0,0 +1,19 @@ +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +@@ -85,7 +_,7 @@ + private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftEntity.DATA_TYPE_REGISTRY); + protected net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers + // Paper start - Folia shedulers +- public final io.papermc.paper.threadedregions.EntityScheduler taskScheduler = new io.papermc.paper.threadedregions.EntityScheduler(this); ++ public final io.papermc.paper.threadedregions.EntityScheduler taskScheduler; // = new io.papermc.paper.threadedregions.EntityScheduler(this); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run + private final io.papermc.paper.threadedregions.scheduler.FoliaEntityScheduler apiScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaEntityScheduler(this); + + @Override +@@ -98,6 +_,7 @@ + this.server = server; + this.entity = entity; + this.entityType = CraftEntityType.minecraftToBukkit(entity.getType()); ++ this.taskScheduler = new io.papermc.paper.threadedregions.EntityScheduler(this.entity.getServer(), this); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run + } + + public static CraftEntity getEntity(CraftServer server, T entity) { diff --git a/sparklypaper-server/paper-patches/features/0007-Add-CraftItemRecipeEvent.patch b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java.patch similarity index 59% rename from sparklypaper-server/paper-patches/features/0007-Add-CraftItemRecipeEvent.patch rename to sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java.patch index c67de14..9045282 100644 --- a/sparklypaper-server/paper-patches/features/0007-Add-CraftItemRecipeEvent.patch +++ b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java.patch @@ -1,19 +1,10 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Tue, 25 Jun 2024 02:52:32 -0300 -Subject: [PATCH] Add CraftItemRecipeEvent - -Used when a player OR a crafter block crafts an item, as an alternative to PrepareItemCraftEvent and CraftItemEvent, because both events are not triggered when a item is crafted from a crafter - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 57c3f8531bf85b53af3a4aad6e9e369d5cff0ce3..80bb0371eed48dbcb0e4e62dfc7f23f8514bdf77 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1474,6 +1474,24 @@ public class CraftEventFactory { +@@ -1307,6 +_,23 @@ Bukkit.getPluginManager().callEvent(crafterCraftEvent); return crafterCraftEvent; } -+ ++ + // SparklyPaper start - add CraftItemRecipeEvent + public static net.sparklypower.sparklypaper.event.inventory.CraftItemRecipeEvent callCraftItemRecipeEvent(net.minecraft.world.inventory.CraftingContainer container, Recipe recipe, ItemStack result) { + org.bukkit.inventory.ItemStack[] matrix = new org.bukkit.inventory.ItemStack[container.getItems().size()]; @@ -30,7 +21,6 @@ index 57c3f8531bf85b53af3a4aad6e9e369d5cff0ce3..80bb0371eed48dbcb0e4e62dfc7f23f8 + return event; + } + // SparklyPaper end -+ + // Paper start @Deprecated - public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, EntityHitResult position) { diff --git a/sparklypaper-server/paper-patches/features/0008-Allow-item-version-downgrades.patch b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch similarity index 60% rename from sparklypaper-server/paper-patches/features/0008-Allow-item-version-downgrades.patch rename to sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch index 3a33e3f..952615f 100644 --- a/sparklypaper-server/paper-patches/features/0008-Allow-item-version-downgrades.patch +++ b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch @@ -1,15 +1,6 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Fri, 21 Jun 2024 18:07:25 -0300 -Subject: [PATCH] Allow item version downgrades - -The server WON'T convert the item data from a newer version to an older version, so proceed with caution - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index bd8005cd3a52532f4cb2e123da473f1490b59dbb..2d23110b61024847c8ed554ac5652982a35dd74b 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -85,6 +85,7 @@ import org.bukkit.potion.PotionType; +@@ -87,6 +_,7 @@ public final class CraftMagicNumbers implements UnsafeValues { public static final CraftMagicNumbers INSTANCE = new CraftMagicNumbers(); public static final boolean DISABLE_OLD_API_SUPPORT = Boolean.getBoolean("paper.disableOldApiSupport"); // Paper @@ -17,21 +8,21 @@ index bd8005cd3a52532f4cb2e123da473f1490b59dbb..2d23110b61024847c8ed554ac5652982 private final Commodore commodore = new Commodore(); -@@ -246,7 +247,7 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -242,7 +_,7 @@ @Override public Material getMaterial(String material, int version) { Preconditions.checkArgument(material != null, "material == null"); - Preconditions.checkArgument(version <= this.getDataVersion(), "Newer version! Server downgrades are not supported!"); -+ Preconditions.checkArgument(JUST_CORRUPT_IT || version <= this.getDataVersion(), "Newer version! Server downgrades are not supported!"); // SparklyPaper - allow item downgrades ++ Preconditions.checkArgument(JUST_CORRUPT_IT || version <= this.getDataVersion(), "Newer version! Server downgrades are not supported!"); // Fastpath up to date materials if (version == this.getDataVersion()) { -@@ -676,7 +677,7 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -752,7 +_,7 @@ throw new RuntimeException(ex); } - int dataVersion = compound.getInt("DataVersion"); + int dataVersion = compound.getIntOr("DataVersion", 0); - Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); -+ Preconditions.checkArgument(JUST_CORRUPT_IT || dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); // SparklyPaper - allow item downgrades ++ Preconditions.checkArgument(JUST_CORRUPT_IT || dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); return compound; } diff --git a/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/Versioning.java.patch b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/Versioning.java.patch new file mode 100644 index 0000000..4b19558 --- /dev/null +++ b/sparklypaper-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/Versioning.java.patch @@ -0,0 +1,11 @@ +--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -11,7 +_,7 @@ + public static String getBukkitVersion() { + String result = "Unknown-Version"; + +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/io.papermc.paper/paper-api/pom.properties"); ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/net.sparklypower.sparklypaper/sparklypaper-api/pom.properties"); // SparklyPaper + Properties properties = new Properties(); + + if (stream != null) { diff --git a/sparklypaper-server/paper-patches/features/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch b/sparklypaper-server/paper-patches/files/src/main/java/org/spigotmc/WatchdogThread.java.patch similarity index 64% rename from sparklypaper-server/paper-patches/features/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch rename to sparklypaper-server/paper-patches/files/src/main/java/org/spigotmc/WatchdogThread.java.patch index c1b7857..4b59b5d 100644 --- a/sparklypaper-server/paper-patches/features/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch +++ b/sparklypaper-server/paper-patches/files/src/main/java/org/spigotmc/WatchdogThread.java.patch @@ -1,29 +1,8 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Sat, 12 Jun 2021 16:40:34 +0200 -Subject: [PATCH] new fork who dis - Rebrand to SparklyPaper and Build Changes - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 774556a62eb240da42e84db4502e2ed43495be17..9bc7b99b5b39a8ffe4118b8d86f5b8065c4fe460 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -@@ -11,7 +11,7 @@ public final class Versioning { - public static String getBukkitVersion() { - String result = "Unknown-Version"; - -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/io.papermc.paper/paper-api/pom.properties"); -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/net.sparklypower.sparklypaper/sparklypaper-api/pom.properties"); // SparklyPaper - Properties properties = new Properties(); - - if (stream != null) { -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index dced8899be0bb8d562093dc3a7673ed8185b85a6..1498c691d3f9b633494750ba4f5cb704468dfeb9 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -77,14 +77,14 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre +@@ -75,14 +_,14 @@ + this.lastEarlyWarning = currentTime; if (isLongTimeout) { - // Paper end logger.log(Level.SEVERE, "------------------------------"); - logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug."); // Paper + logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug. This could be a SparklyPaper bug and, in that case, MrPowerGamerBR probably made a fucky wucky!"); // SparklyPaper - branding changes // Paper @@ -39,12 +18,13 @@ index dced8899be0bb8d562093dc3a7673ed8185b85a6..1498c691d3f9b633494750ba4f5cb704 if (net.minecraft.world.level.Level.lastPhysicsProblem != null) { logger.log(Level.SEVERE, "------------------------------"); -@@ -109,7 +109,7 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre +@@ -107,8 +_,7 @@ } // Paper end - Different message for short timeout logger.log(Level.SEVERE, "------------------------------"); - logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):"); // Paper +- FeatureHooks.dumpAllChunkLoadInfo(MinecraftServer.getServer(), isLongTimeout); // Paper - log detailed tick information + logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to SparklyPaper!):"); // SparklyPaper - branding changes // Paper - FeatureHooks.dumpAllChunkLoadInfo(MinecraftServer.getServer(), isLongTimeout); // Paper - log detailed tick information WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE), logger); logger.log(Level.SEVERE, "------------------------------"); + diff --git a/sparklypaper-server/paper-patches/features/0010-SPARKLYPOWER-Add-custom-blocks.patch b/sparklypaper-server/paper-patches/files/src/test/java/org/bukkit/craftbukkit/legacy/LegacyTest.java.patch similarity index 53% rename from sparklypaper-server/paper-patches/features/0010-SPARKLYPOWER-Add-custom-blocks.patch rename to sparklypaper-server/paper-patches/files/src/test/java/org/bukkit/craftbukkit/legacy/LegacyTest.java.patch index c1b24cf..541c965 100644 --- a/sparklypaper-server/paper-patches/features/0010-SPARKLYPOWER-Add-custom-blocks.patch +++ b/sparklypaper-server/paper-patches/files/src/test/java/org/bukkit/craftbukkit/legacy/LegacyTest.java.patch @@ -1,17 +1,9 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Wed, 12 Jun 2024 11:53:09 -0300 -Subject: [PATCH] SPARKLYPOWER Add custom blocks - - -diff --git a/src/test/java/org/bukkit/craftbukkit/legacy/LegacyTest.java b/src/test/java/org/bukkit/craftbukkit/legacy/LegacyTest.java -index 002e635137a8b015af9799d6a8854ebc6330bfb4..0f02a9793937a492003bbfff827ac6483c1baa14 100644 --- a/src/test/java/org/bukkit/craftbukkit/legacy/LegacyTest.java +++ b/src/test/java/org/bukkit/craftbukkit/legacy/LegacyTest.java -@@ -135,6 +135,9 @@ public class LegacyTest { - // 1.21.4 - Material.OPEN_EYEBLOSSOM, Material.CLOSED_EYEBLOSSOM, Material.RESIN_CLUMP, Material.RESIN_BLOCK, Material.RESIN_BRICKS, Material.RESIN_BRICK_STAIRS, Material.RESIN_BRICK_SLAB, Material.RESIN_BRICK_WALL, Material.CHISELED_RESIN_BRICKS, +@@ -137,6 +_,9 @@ Material.RESIN_BRICK, Material.POTTED_OPEN_EYEBLOSSOM, Material.POTTED_CLOSED_EYEBLOSSOM, + // 1.21.5 + Material.WILDFLOWERS, Material.LEAF_LITTER, Material.TEST_BLOCK, Material.TEST_INSTANCE_BLOCK, Material.BUSH, Material.FIREFLY_BUSH, Material.SHORT_DRY_GRASS, Material.TALL_DRY_GRASS, Material.CACTUS_FLOWER, Material.BLUE_EGG, Material.BROWN_EGG, + // SparklyPower custom blocks + Material.SPARKLYPOWER_RAINBOW_WOOL, Material.SPARKLYPOWER_RAINBOW_CONCRETE, Material.SPARKLYPOWER_RAINBOW_TERRACOTTA, Material.SPARKLYPOWER_ASPHALT_PLAYER, Material.SPARKLYPOWER_ASPHALT_SERVER, Material.SPARKLYPOWER_ASPHALT_PLAYER_SLAB, + Material.SPARKLYPOWER_ASPHALT_SERVER_SLAB, diff --git a/sparklypaper-server/src/main/kotlin/net/sparklypower/sparklypaper/LegacyNBTRemapper.kt b/sparklypaper-server/src/main/kotlin/net/sparklypower/sparklypaper/LegacyNBTRemapper.kt deleted file mode 100644 index 399225f..0000000 --- a/sparklypaper-server/src/main/kotlin/net/sparklypower/sparklypaper/LegacyNBTRemapper.kt +++ /dev/null @@ -1,95 +0,0 @@ -package net.sparklypower.sparklypaper - -import ca.spottedleaf.dataconverter.types.MapType - -object LegacyNBTRemapper { - /** - * Remaps hacky direct NBT storage used in SparklyPower to proper PersistentDataContainer data - */ - fun remap(tag: MapType) { - val perfectDreamsMap = tag.getMap("PerfectDreams") - - if (perfectDreamsMap != null) { - val publicBukkitValuesMap = tag.getOrCreateMap("PublicBukkitValues") - - // The "setBoolean" functions do set bytes behind the scenes, just like how we do the things in SparklyPower - perfectDreamsMap.getStringAndRemove("isJetpack")?.let { - publicBukkitValuesMap.setBoolean("sparklypower:is_jetpack", it.toBoolean()) - } - - perfectDreamsMap.getStringAndRemove("disallowCrafting")?.let { - publicBukkitValuesMap.setBoolean("sparklypower:disallow_crafting", it.toBoolean()) - } - - perfectDreamsMap.getStringAndRemove("poop")?.let { - publicBukkitValuesMap.setBoolean("sparklypower:is_poop", it.toBoolean()) - } - - perfectDreamsMap.getStringAndRemove("renamedBySeuZe")?.let { - publicBukkitValuesMap.setBoolean("sparklypower:is_renamed_by_seu_ze", it.toBoolean()) - } - - perfectDreamsMap.getStringAndRemove("isMonsterPickaxe")?.let { - publicBukkitValuesMap.setBoolean("sparklypower:is_monster_tool", it.toBoolean()) - } - - perfectDreamsMap.getStringAndRemove("itemOwner")?.let { - publicBukkitValuesMap.setString("sparklypower:item_owner", it) - } - - perfectDreamsMap.getStringAndRemove("DreamFusca")?.let { - publicBukkitValuesMap.setString("sparklypower:fusca_info", it) - } - - perfectDreamsMap.getStringAndRemove("isFusca")?.let { - publicBukkitValuesMap.setBoolean("sparklypower:is_fusca", it.toBoolean()) - } - - perfectDreamsMap.getStringAndRemove("fancyLeatherArmor")?.let { - publicBukkitValuesMap.setBoolean("sparklypower:is_fancy_leather_armor", it.toBoolean()) - } - - perfectDreamsMap.getStringAndRemove("caixaSecretaLevel")?.let { - publicBukkitValuesMap.setInt("sparklypower:caixa_secreta_level", it.toInt()) - } - - perfectDreamsMap.getStringAndRemove("caixaSecretaWorld")?.let { - publicBukkitValuesMap.setString("sparklypower:caixa_secreta_world", it) - } - - perfectDreamsMap.getStringAndRemove("isMoveSpawners")?.let { - publicBukkitValuesMap.setBoolean("sparklypower:is_move_spawners_tool", it.toBoolean()) - } - - perfectDreamsMap.getStringAndRemove("spawnerType")?.let { - publicBukkitValuesMap.setString("sparklypower:spawner_type", it) - } - - perfectDreamsMap.getStringAndRemove("isMochila")?.let { - publicBukkitValuesMap.setBoolean("sparklypower:is_mochila", it.toBoolean()) - } - - perfectDreamsMap.getStringAndRemove("mochilaId")?.let { - publicBukkitValuesMap.setLong("sparklypower:mochila_id", it.toLong()) - } - - perfectDreamsMap.getStringAndRemove("customMapOwner")?.let { - publicBukkitValuesMap.setString("sparklypower:map_custom_owner", it) - } - - perfectDreamsMap.getStringAndRemove("quickTeleport")?.let { - publicBukkitValuesMap.setBoolean("sparklypower:is_quick_resources_teleport", it.toBoolean()) - } - - // If it is empty, then it means that we have migrated everything and we can remove the old PerfectDreams tag, yay! - if (perfectDreamsMap.isEmpty) - tag.remove("PerfectDreams") - } - } - - private fun MapType.getStringAndRemove(key: String): String? { - val v = getString(key) - remove(key) - return v - } -} \ No newline at end of file diff --git a/sparklypaper-server/src/main/kotlin/net/sparklypower/sparklypaper/ServerLevelTickExecutorThreadFactory.kt b/sparklypaper-server/src/main/kotlin/net/sparklypower/sparklypaper/ServerLevelTickExecutorThreadFactory.kt deleted file mode 100644 index 9a40afb..0000000 --- a/sparklypaper-server/src/main/kotlin/net/sparklypower/sparklypaper/ServerLevelTickExecutorThreadFactory.kt +++ /dev/null @@ -1,20 +0,0 @@ -package net.sparklypower.sparklypaper - -import ca.spottedleaf.moonrise.common.util.TickThread -import java.util.concurrent.ThreadFactory - -class ServerLevelTickExecutorThreadFactory(private val worldName: String) : ThreadFactory { - override fun newThread(p0: Runnable): Thread { - val tickThread = TickThread.ServerLevelTickThread(p0, "serverlevel-tick-worker [$worldName]") - - if (tickThread.isDaemon) { - tickThread.isDaemon = false - } - - if (tickThread.priority != 5) { - tickThread.priority = 5 - } - - return tickThread - } -} \ No newline at end of file