diff --git a/build-data/leaf.at b/build-data/leaf.at index 272f5d5a..16bc187c 100644 --- a/build-data/leaf.at +++ b/build-data/leaf.at @@ -2,7 +2,10 @@ # See CONTRIBUTING.md on how to add access transformers. protected net.minecraft.world.entity.Entity dimensions protected-f net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase$Cache largeCollisionShape +public net.minecraft.server.players.PlayerList SEND_PLAYER_INFO_INTERVAL public net.minecraft.util.Mth SIN +public net.minecraft.world.entity.Entity blockPosition +public net.minecraft.world.entity.Entity position public net.minecraft.world.entity.Entity updateInWaterStateAndDoWaterCurrentPushing()V public net.minecraft.world.entity.LivingEntity canGlide()Z public net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities lineOfSightTest @@ -12,11 +15,13 @@ public net.minecraft.world.entity.monster.Shulker MAX_SCALE public net.minecraft.world.entity.player.Player canGlide()Z public net.minecraft.world.item.CrossbowItem getShotPitch(Lnet/minecraft/util/RandomSource;I)F public net.minecraft.world.level.block.entity.FuelValues values +public net.minecraft.world.level.chunk.PaletteResize public net.minecraft.world.level.chunk.storage.RegionFile getOversizedData(II)Lnet/minecraft/nbt/CompoundTag; public net.minecraft.world.level.chunk.storage.RegionFile isOversized(II)Z public net.minecraft.world.level.chunk.storage.RegionFile recalculateHeader()Z public net.minecraft.world.level.chunk.storage.RegionFile setOversized(IIZ)V public net.minecraft.world.level.chunk.storage.RegionFile write(Lnet/minecraft/world/level/ChunkPos;Ljava/nio/ByteBuffer;)V +public net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece LOGGER public net.minecraft.world.level.material.FlowingFluid canHoldAnyFluid(Lnet/minecraft/world/level/block/state/BlockState;)Z public net.minecraft.world.level.pathfinder.SwimNodeEvaluator allowBreaching public-f net.minecraft.world.entity.EntityType dimensions diff --git a/build.gradle.kts b/build.gradle.kts index 1fbd35e5..f898c85a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -65,7 +65,6 @@ subprojects { paperweight { upstreams.paper { - repo = github("Dreeam-qwq", "Paper") ref = providers.gradleProperty("paperCommit") patchFile { diff --git a/gradle.properties b/gradle.properties index aa7697a5..6f1653ab 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ group=cn.dreeam.leaf mcVersion=1.21.5 version=1.21.5-R0.1-SNAPSHOT -paperCommit=bf0a1298ec5172d9ea46a4ff4670a615aae013c7 +paperCommit=ce91a8ca123f4e853629d08705e4ece3a09a5a4d org.gradle.configuration-cache=true org.gradle.caching=true diff --git a/leaf-api/build.gradle.kts.patch b/leaf-api/build.gradle.kts.patch index 870f6505..f133dcca 100644 --- a/leaf-api/build.gradle.kts.patch +++ b/leaf-api/build.gradle.kts.patch @@ -88,15 +88,15 @@ + // Leaf end - Bump Dependencies } --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() // Leaf - project setup +-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() // Leaf - project setup idea { module { - generatedSourceDirs.add(generatedApiPath.toFile()) + generatedSourceDirs.add(generatedDir.toFile()) @@ -103,6 +_,20 @@ main { java { - srcDir(generatedApiPath) + srcDir(generatedDir) + // Leaf start - project setup + srcDir(file("../paper-api/src/main/java")) + } @@ -192,7 +192,7 @@ } tasks.test { -@@ -243,6 +_,11 @@ +@@ -233,6 +_,11 @@ jarToScan.set(tasks.jar.flatMap { it.archiveFile }) classpath.from(configurations.compileClasspath) } @@ -202,5 +202,5 @@ +} +// Leaf end - Bump Dependencies tasks.check { - dependsOn(scanJarForOldGeneratedCode) + dependsOn(scanJarForBadCalls) } diff --git a/leaf-api/paper-patches/features/0001-Rebrand.patch b/leaf-api/paper-patches/features/0001-Rebrand.patch index eb92779c..cf5ff32e 100644 --- a/leaf-api/paper-patches/features/0001-Rebrand.patch +++ b/leaf-api/paper-patches/features/0001-Rebrand.patch @@ -3,7 +3,7 @@ From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Date: Tue, 21 May 2024 11:43:49 +0800 Subject: [PATCH] Rebrand -This patch is based on the following patch: +This patch is referring to the following patch: "Gale branding changes" By: Martijn Muijsers As part of: GaleMC (https://github.com/GaleMC/Gale) diff --git a/leaf-api/paper-patches/features/0006-Vectorized-map-color-conversion.patch b/leaf-api/paper-patches/features/0006-Vectorized-map-color-conversion.patch index 2db68dc9..d303715d 100644 --- a/leaf-api/paper-patches/features/0006-Vectorized-map-color-conversion.patch +++ b/leaf-api/paper-patches/features/0006-Vectorized-map-color-conversion.patch @@ -110,19 +110,19 @@ index 0000000000000000000000000000000000000000..00b16e4aacba50996b81fac81c3f78b6 + +} diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java -index 6995f9cc08d162e3adcd3a28f6bfa6d329661999..844ad65edd5ac9eb7ccce08905972ad0ba18ea69 100644 +index fc9728342de7605da69813fb44b008c1343124c0..4d55f8ece0bbe0be64b700f54a52d6a2cbfad9a5 100644 --- a/src/main/java/org/bukkit/map/MapPalette.java +++ b/src/main/java/org/bukkit/map/MapPalette.java -@@ -45,7 +45,7 @@ public final class MapPalette { +@@ -35,7 +35,7 @@ public final class MapPalette { } @NotNull - static final Color[] colors = { + public static final Color[] colors = { // Gale - Pufferfish - vectorized map color conversion - package -> public - c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0), - c(89, 125, 39), c(109, 153, 48), c(127, 178, 56), c(67, 94, 29), - c(174, 164, 115), c(213, 201, 140), c(247, 233, 163), c(130, 123, 86), -@@ -216,9 +216,15 @@ public final class MapPalette { + // Start generate - MapPalette#colors + // @GeneratedFrom 1.21.5 + new Color(0x00000000, true), +@@ -395,9 +395,15 @@ public final class MapPalette { temp.getRGB(0, 0, temp.getWidth(), temp.getHeight(), pixels, 0, temp.getWidth()); byte[] result = new byte[temp.getWidth() * temp.getHeight()]; diff --git a/leaf-server/gale-patches/features/0001-Leaf-Commands.patch b/leaf-archived-patches/unapplied/server/gale-patches/features/0001-Leaf-Commands.patch similarity index 100% rename from leaf-server/gale-patches/features/0001-Leaf-Commands.patch rename to leaf-archived-patches/unapplied/server/gale-patches/features/0001-Leaf-Commands.patch diff --git a/leaf-server/gale-patches/features/0002-Fix-Pufferfish-and-Purpur-patches.patch b/leaf-archived-patches/unapplied/server/gale-patches/features/0002-Fix-Pufferfish-and-Purpur-patches.patch similarity index 100% rename from leaf-server/gale-patches/features/0002-Fix-Pufferfish-and-Purpur-patches.patch rename to leaf-archived-patches/unapplied/server/gale-patches/features/0002-Fix-Pufferfish-and-Purpur-patches.patch diff --git a/leaf-server/gale-patches/features/0003-KeYi-Disable-arrow-despawn-counter-by-default.patch b/leaf-archived-patches/unapplied/server/gale-patches/features/0003-KeYi-Disable-arrow-despawn-counter-by-default.patch similarity index 100% rename from leaf-server/gale-patches/features/0003-KeYi-Disable-arrow-despawn-counter-by-default.patch rename to leaf-archived-patches/unapplied/server/gale-patches/features/0003-KeYi-Disable-arrow-despawn-counter-by-default.patch diff --git a/leaf-server/gale-patches/features/0004-Reduce-active-items-finding-hopper-nearby-check.patch b/leaf-archived-patches/unapplied/server/gale-patches/features/0004-Reduce-active-items-finding-hopper-nearby-check.patch similarity index 100% rename from leaf-server/gale-patches/features/0004-Reduce-active-items-finding-hopper-nearby-check.patch rename to leaf-archived-patches/unapplied/server/gale-patches/features/0004-Reduce-active-items-finding-hopper-nearby-check.patch diff --git a/leaf-server/minecraft-patches/features/0002-Leaf-config.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0002-Leaf-config.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0002-Leaf-config.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0002-Leaf-config.patch diff --git a/leaf-server/minecraft-patches/features/0003-Leaf-Commands.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0003-Leaf-Commands.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0003-Leaf-Commands.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0003-Leaf-Commands.patch diff --git a/leaf-server/minecraft-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch diff --git a/leaf-server/minecraft-patches/features/0005-Pufferfish-Dynamic-Activation-of-Brain.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0005-Pufferfish-Dynamic-Activation-of-Brain.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0005-Pufferfish-Dynamic-Activation-of-Brain.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0005-Pufferfish-Dynamic-Activation-of-Brain.patch diff --git a/leaf-server/minecraft-patches/features/0006-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0006-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0006-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0006-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch diff --git a/leaf-server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0007-Purpur-Server-Minecraft-Changes.patch diff --git a/leaf-server/minecraft-patches/features/0008-Fix-Pufferfish-and-Purpur-patches.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0008-Fix-Pufferfish-and-Purpur-patches.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0008-Fix-Pufferfish-and-Purpur-patches.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0008-Fix-Pufferfish-and-Purpur-patches.patch diff --git a/leaf-server/minecraft-patches/features/0009-Purpur-Configurable-server-mod-name.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0009-Purpur-Configurable-server-mod-name.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0009-Purpur-Configurable-server-mod-name.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0009-Purpur-Configurable-server-mod-name.patch diff --git a/leaf-server/minecraft-patches/features/0010-Configurable-server-GUI-name.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0010-Configurable-server-GUI-name.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0010-Configurable-server-GUI-name.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0010-Configurable-server-GUI-name.patch diff --git a/leaf-server/minecraft-patches/features/0011-Remove-vanilla-username-check.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0011-Remove-vanilla-username-check.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0011-Remove-vanilla-username-check.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0011-Remove-vanilla-username-check.patch diff --git a/leaf-server/minecraft-patches/features/0012-Remove-Spigot-check-for-broken-BungeeCord-configurat.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0012-Remove-Spigot-check-for-broken-BungeeCord-configurat.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0012-Remove-Spigot-check-for-broken-BungeeCord-configurat.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0012-Remove-Spigot-check-for-broken-BungeeCord-configurat.patch diff --git a/leaf-server/minecraft-patches/features/0013-Remove-UseItemOnPacket-Too-Far-check.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0013-Remove-UseItemOnPacket-Too-Far-check.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0013-Remove-UseItemOnPacket-Too-Far-check.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0013-Remove-UseItemOnPacket-Too-Far-check.patch diff --git a/leaf-server/minecraft-patches/features/0014-Remove-change-non-editable-sign-warning.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0014-Remove-change-non-editable-sign-warning.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0014-Remove-change-non-editable-sign-warning.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0014-Remove-change-non-editable-sign-warning.patch diff --git a/leaf-server/minecraft-patches/features/0015-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0015-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0015-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0015-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch diff --git a/leaf-server/minecraft-patches/features/0016-Carpet-Fixes-Optimized-getBiome-method.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0016-Carpet-Fixes-Optimized-getBiome-method.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0016-Carpet-Fixes-Optimized-getBiome-method.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0016-Carpet-Fixes-Optimized-getBiome-method.patch diff --git a/leaf-server/minecraft-patches/features/0017-Carpet-Fixes-Use-optimized-RecipeManager.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0017-Carpet-Fixes-Use-optimized-RecipeManager.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0017-Carpet-Fixes-Use-optimized-RecipeManager.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0017-Carpet-Fixes-Use-optimized-RecipeManager.patch diff --git a/leaf-server/minecraft-patches/features/0018-Akarin-Save-Json-list-asynchronously.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0018-Akarin-Save-Json-list-asynchronously.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0018-Akarin-Save-Json-list-asynchronously.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0018-Akarin-Save-Json-list-asynchronously.patch diff --git a/leaf-server/minecraft-patches/features/0019-Slice-Smooth-Teleports.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0019-Slice-Smooth-Teleports.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0019-Slice-Smooth-Teleports.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0019-Slice-Smooth-Teleports.patch diff --git a/leaf-server/minecraft-patches/features/0020-Parchment-Make-FixLight-use-action-bar.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0020-Parchment-Make-FixLight-use-action-bar.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0020-Parchment-Make-FixLight-use-action-bar.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0020-Parchment-Make-FixLight-use-action-bar.patch diff --git a/leaf-server/minecraft-patches/features/0021-Leaves-Protocol-Core.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0021-Leaves-Protocol-Core.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0021-Leaves-Protocol-Core.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0021-Leaves-Protocol-Core.patch diff --git a/leaf-server/minecraft-patches/features/0022-Leaves-Jade-Protocol.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0022-Leaves-Jade-Protocol.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0022-Leaves-Jade-Protocol.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0022-Leaves-Jade-Protocol.patch diff --git a/leaf-server/minecraft-patches/features/0023-Leaves-Xaero-Map-Protocol.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0023-Leaves-Xaero-Map-Protocol.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0023-Leaves-Xaero-Map-Protocol.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0023-Leaves-Xaero-Map-Protocol.patch diff --git a/leaf-server/minecraft-patches/features/0024-Leaves-Syncmatica-Protocol.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0024-Leaves-Syncmatica-Protocol.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0024-Leaves-Syncmatica-Protocol.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0024-Leaves-Syncmatica-Protocol.patch diff --git a/leaf-server/minecraft-patches/features/0025-Leaves-Replay-Mod-API.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0025-Leaves-Replay-Mod-API.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0025-Leaves-Replay-Mod-API.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0025-Leaves-Replay-Mod-API.patch diff --git a/leaf-server/minecraft-patches/features/0026-Petal-Async-Pathfinding.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0026-Petal-Async-Pathfinding.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0026-Petal-Async-Pathfinding.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0026-Petal-Async-Pathfinding.patch diff --git a/leaf-server/minecraft-patches/features/0027-Petal-reduce-work-done-by-game-event-system.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0027-Petal-reduce-work-done-by-game-event-system.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0027-Petal-reduce-work-done-by-game-event-system.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0027-Petal-reduce-work-done-by-game-event-system.patch diff --git a/leaf-server/minecraft-patches/features/0028-Reduce-canSee-work.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0028-Reduce-canSee-work.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0028-Reduce-canSee-work.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0028-Reduce-canSee-work.patch diff --git a/leaf-server/minecraft-patches/features/0029-Fix-sprint-glitch.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0029-Fix-sprint-glitch.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0029-Fix-sprint-glitch.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0029-Fix-sprint-glitch.patch diff --git a/leaf-server/minecraft-patches/features/0030-Configurable-movement-speed-of-more-entities.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0030-Configurable-movement-speed-of-more-entities.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0030-Configurable-movement-speed-of-more-entities.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0030-Configurable-movement-speed-of-more-entities.patch diff --git a/leaf-server/minecraft-patches/features/0031-Faster-sequencing-of-futures-for-chunk-structure-gen.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0031-Faster-sequencing-of-futures-for-chunk-structure-gen.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0031-Faster-sequencing-of-futures-for-chunk-structure-gen.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0031-Faster-sequencing-of-futures-for-chunk-structure-gen.patch diff --git a/leaf-server/minecraft-patches/features/0032-Reduce-active-items-finding-hopper-nearby-check.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0032-Reduce-active-items-finding-hopper-nearby-check.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0032-Reduce-active-items-finding-hopper-nearby-check.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0032-Reduce-active-items-finding-hopper-nearby-check.patch diff --git a/leaf-server/minecraft-patches/features/0033-Linear-region-file-format.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0033-Linear-region-file-format.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0033-Linear-region-file-format.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0033-Linear-region-file-format.patch diff --git a/leaf-server/minecraft-patches/features/0034-Plazma-Add-some-missing-Pufferfish-configurations.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0034-Plazma-Add-some-missing-Pufferfish-configurations.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0034-Plazma-Add-some-missing-Pufferfish-configurations.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0034-Plazma-Add-some-missing-Pufferfish-configurations.patch diff --git a/leaf-server/minecraft-patches/features/0035-Plazma-Add-missing-purpur-configuration-options.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0035-Plazma-Add-missing-purpur-configuration-options.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0035-Plazma-Add-missing-purpur-configuration-options.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0035-Plazma-Add-missing-purpur-configuration-options.patch diff --git a/leaf-server/minecraft-patches/features/0036-SparklyPaper-Skip-distanceToSqr-call-in-ServerEntity.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0036-SparklyPaper-Skip-distanceToSqr-call-in-ServerEntity.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0036-SparklyPaper-Skip-distanceToSqr-call-in-ServerEntity.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0036-SparklyPaper-Skip-distanceToSqr-call-in-ServerEntity.patch diff --git a/leaf-server/minecraft-patches/features/0037-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0037-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0037-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0037-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch diff --git a/leaf-server/minecraft-patches/features/0038-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0038-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0038-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0038-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch diff --git a/leaf-server/minecraft-patches/features/0039-SparklyPaper-Optimize-canSee-checks.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0039-SparklyPaper-Optimize-canSee-checks.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0039-SparklyPaper-Optimize-canSee-checks.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0039-SparklyPaper-Optimize-canSee-checks.patch diff --git a/leaf-server/minecraft-patches/features/0040-SparklyPaper-Allow-throttling-hopper-checks-if-the-t.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0040-SparklyPaper-Allow-throttling-hopper-checks-if-the-t.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0040-SparklyPaper-Allow-throttling-hopper-checks-if-the-t.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0040-SparklyPaper-Allow-throttling-hopper-checks-if-the-t.patch diff --git a/leaf-server/minecraft-patches/features/0041-Polpot-Make-egg-and-snowball-can-knockback-player.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0041-Polpot-Make-egg-and-snowball-can-knockback-player.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0041-Polpot-Make-egg-and-snowball-can-knockback-player.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0041-Polpot-Make-egg-and-snowball-can-knockback-player.patch diff --git a/leaf-server/minecraft-patches/features/0042-Redirect-vanilla-getProfiler-to-inactive-in-PathNavi.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0042-Redirect-vanilla-getProfiler-to-inactive-in-PathNavi.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0042-Redirect-vanilla-getProfiler-to-inactive-in-PathNavi.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0042-Redirect-vanilla-getProfiler-to-inactive-in-PathNavi.patch diff --git a/leaf-server/minecraft-patches/features/0043-Remove-useless-creating-stats-json-bases-on-player-n.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0043-Remove-useless-creating-stats-json-bases-on-player-n.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0043-Remove-useless-creating-stats-json-bases-on-player-n.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0043-Remove-useless-creating-stats-json-bases-on-player-n.patch diff --git a/leaf-server/minecraft-patches/features/0044-Improve-Purpur-AFK-system.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0044-Improve-Purpur-AFK-system.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0044-Improve-Purpur-AFK-system.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0044-Improve-Purpur-AFK-system.patch diff --git a/leaf-server/minecraft-patches/features/0045-Virtual-thread-for-chat-executor.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0045-Virtual-thread-for-chat-executor.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0045-Virtual-thread-for-chat-executor.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0045-Virtual-thread-for-chat-executor.patch diff --git a/leaf-server/minecraft-patches/features/0046-Virtual-thread-for-user-authenticator.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0046-Virtual-thread-for-user-authenticator.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0046-Virtual-thread-for-user-authenticator.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0046-Virtual-thread-for-user-authenticator.patch diff --git a/leaf-server/minecraft-patches/features/0047-Mirai-Configurable-chat-message-signatures.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0047-Mirai-Configurable-chat-message-signatures.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0047-Mirai-Configurable-chat-message-signatures.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0047-Mirai-Configurable-chat-message-signatures.patch diff --git a/leaf-server/minecraft-patches/features/0048-Cache-player-profileResult.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0048-Cache-player-profileResult.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0048-Cache-player-profileResult.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0048-Cache-player-profileResult.patch diff --git a/leaf-server/minecraft-patches/features/0049-Matter-Secure-Seed.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0049-Matter-Secure-Seed.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0049-Matter-Secure-Seed.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0049-Matter-Secure-Seed.patch diff --git a/leaf-server/minecraft-patches/features/0050-Matter-Secure-Seed-command.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0050-Matter-Secure-Seed-command.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0050-Matter-Secure-Seed-command.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0050-Matter-Secure-Seed-command.patch diff --git a/leaf-server/minecraft-patches/features/0051-Faster-random-generator.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0051-Faster-random-generator.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0051-Faster-random-generator.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0051-Faster-random-generator.patch diff --git a/leaf-server/minecraft-patches/features/0052-Don-t-save-primed-tnt-entity.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0052-Don-t-save-primed-tnt-entity.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0052-Don-t-save-primed-tnt-entity.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0052-Don-t-save-primed-tnt-entity.patch diff --git a/leaf-server/minecraft-patches/features/0053-Don-t-save-falling-block-entity.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0053-Don-t-save-falling-block-entity.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0053-Don-t-save-falling-block-entity.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0053-Don-t-save-falling-block-entity.patch diff --git a/leaf-server/minecraft-patches/features/0054-Configurable-connection-message.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0054-Configurable-connection-message.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0054-Configurable-connection-message.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0054-Configurable-connection-message.patch diff --git a/leaf-server/minecraft-patches/features/0055-Configurable-unknown-command-message.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0055-Configurable-unknown-command-message.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0055-Configurable-unknown-command-message.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0055-Configurable-unknown-command-message.patch diff --git a/leaf-server/minecraft-patches/features/0056-Remove-stream-in-BlockBehaviour-cache-blockstate.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0056-Remove-stream-in-BlockBehaviour-cache-blockstate.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0056-Remove-stream-in-BlockBehaviour-cache-blockstate.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0056-Remove-stream-in-BlockBehaviour-cache-blockstate.patch diff --git a/leaf-server/minecraft-patches/features/0057-Remove-stream-in-entity-visible-effects-filter.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0057-Remove-stream-in-entity-visible-effects-filter.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0057-Remove-stream-in-entity-visible-effects-filter.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0057-Remove-stream-in-entity-visible-effects-filter.patch diff --git a/leaf-server/minecraft-patches/features/0058-Remove-stream-and-double-iteration-in-enough-deep-sl.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0058-Remove-stream-and-double-iteration-in-enough-deep-sl.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0058-Remove-stream-and-double-iteration-in-enough-deep-sl.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0058-Remove-stream-and-double-iteration-in-enough-deep-sl.patch diff --git a/leaf-server/minecraft-patches/features/0059-Remove-stream-in-trial-spawner-ticking.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0059-Remove-stream-in-trial-spawner-ticking.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0059-Remove-stream-in-trial-spawner-ticking.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0059-Remove-stream-in-trial-spawner-ticking.patch diff --git a/leaf-server/minecraft-patches/features/0060-Remove-stream-in-Brain.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0060-Remove-stream-in-Brain.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0060-Remove-stream-in-Brain.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0060-Remove-stream-in-Brain.patch diff --git a/leaf-server/minecraft-patches/features/0061-Remove-stream-in-BehaviorUtils.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0061-Remove-stream-in-BehaviorUtils.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0061-Remove-stream-in-BehaviorUtils.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0061-Remove-stream-in-BehaviorUtils.patch diff --git a/leaf-server/minecraft-patches/features/0062-Remove-stream-in-YieldJobSite.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0062-Remove-stream-in-YieldJobSite.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0062-Remove-stream-in-YieldJobSite.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0062-Remove-stream-in-YieldJobSite.patch diff --git a/leaf-server/minecraft-patches/features/0063-Remove-stream-in-PlayerSensor.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0063-Remove-stream-in-PlayerSensor.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0063-Remove-stream-in-PlayerSensor.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0063-Remove-stream-in-PlayerSensor.patch diff --git a/leaf-server/minecraft-patches/features/0064-Remove-stream-in-GolemSensor.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0064-Remove-stream-in-GolemSensor.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0064-Remove-stream-in-GolemSensor.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0064-Remove-stream-in-GolemSensor.patch diff --git a/leaf-server/minecraft-patches/features/0065-Remove-stream-in-GateBehavior.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0065-Remove-stream-in-GateBehavior.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0065-Remove-stream-in-GateBehavior.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0065-Remove-stream-in-GateBehavior.patch diff --git a/leaf-server/minecraft-patches/features/0066-Remove-stream-in-updateFluidOnEyes.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0066-Remove-stream-in-updateFluidOnEyes.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0066-Remove-stream-in-updateFluidOnEyes.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0066-Remove-stream-in-updateFluidOnEyes.patch diff --git a/leaf-server/minecraft-patches/features/0067-Remove-stream-in-matchingSlot.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0067-Remove-stream-in-matchingSlot.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0067-Remove-stream-in-matchingSlot.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0067-Remove-stream-in-matchingSlot.patch diff --git a/leaf-server/minecraft-patches/features/0068-Replace-Entity-active-effects-map-with-optimized-col.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0068-Replace-Entity-active-effects-map-with-optimized-col.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0068-Replace-Entity-active-effects-map-with-optimized-col.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0068-Replace-Entity-active-effects-map-with-optimized-col.patch diff --git a/leaf-server/minecraft-patches/features/0069-Replace-criterion-map-with-optimized-collection.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0069-Replace-criterion-map-with-optimized-collection.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0069-Replace-criterion-map-with-optimized-collection.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0069-Replace-criterion-map-with-optimized-collection.patch diff --git a/leaf-server/minecraft-patches/features/0070-Replace-brain-maps-with-optimized-collection.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0070-Replace-brain-maps-with-optimized-collection.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0070-Replace-brain-maps-with-optimized-collection.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0070-Replace-brain-maps-with-optimized-collection.patch diff --git a/leaf-server/minecraft-patches/features/0071-Reduce-worldgen-allocations.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0071-Reduce-worldgen-allocations.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0071-Reduce-worldgen-allocations.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0071-Reduce-worldgen-allocations.patch diff --git a/leaf-server/minecraft-patches/features/0072-Use-caffeine-cache-for-kickPermission-instead-of-usi.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0072-Use-caffeine-cache-for-kickPermission-instead-of-usi.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0072-Use-caffeine-cache-for-kickPermission-instead-of-usi.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0072-Use-caffeine-cache-for-kickPermission-instead-of-usi.patch diff --git a/leaf-server/minecraft-patches/features/0073-Do-not-place-player-if-the-server-is-full.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0073-Do-not-place-player-if-the-server-is-full.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0073-Do-not-place-player-if-the-server-is-full.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0073-Do-not-place-player-if-the-server-is-full.patch diff --git a/leaf-server/minecraft-patches/features/0074-Fix-MC-65198.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0074-Fix-MC-65198.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0074-Fix-MC-65198.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0074-Fix-MC-65198.patch diff --git a/leaf-server/minecraft-patches/features/0075-Fix-MC-200418.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0075-Fix-MC-200418.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0075-Fix-MC-200418.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0075-Fix-MC-200418.patch diff --git a/leaf-server/minecraft-patches/features/0076-Fix-MC-119417.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0076-Fix-MC-119417.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0076-Fix-MC-119417.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0076-Fix-MC-119417.patch diff --git a/leaf-server/minecraft-patches/features/0077-Fix-MC-223153.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0077-Fix-MC-223153.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0077-Fix-MC-223153.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0077-Fix-MC-223153.patch diff --git a/leaf-server/minecraft-patches/features/0078-Configurable-player-knockback-zombie.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0078-Configurable-player-knockback-zombie.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0078-Configurable-player-knockback-zombie.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0078-Configurable-player-knockback-zombie.patch diff --git a/leaf-server/minecraft-patches/features/0079-Hide-specified-item-components.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0079-Hide-specified-item-components.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0079-Hide-specified-item-components.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0079-Hide-specified-item-components.patch diff --git a/leaf-server/minecraft-patches/features/0080-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0080-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0080-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0080-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch diff --git a/leaf-server/minecraft-patches/features/0081-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0081-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0081-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0081-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch diff --git a/leaf-server/minecraft-patches/features/0082-PaperPR-Fix-some-beacon-event-issues.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0082-PaperPR-Fix-some-beacon-event-issues.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0082-PaperPR-Fix-some-beacon-event-issues.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0082-PaperPR-Fix-some-beacon-event-issues.patch diff --git a/leaf-server/minecraft-patches/features/0083-Dont-send-useless-entity-packets.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0083-Dont-send-useless-entity-packets.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0083-Dont-send-useless-entity-packets.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0083-Dont-send-useless-entity-packets.patch diff --git a/leaf-server/minecraft-patches/features/0084-Don-t-spawn-if-lastSpawnState-is-null.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0084-Don-t-spawn-if-lastSpawnState-is-null.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0084-Don-t-spawn-if-lastSpawnState-is-null.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0084-Don-t-spawn-if-lastSpawnState-is-null.patch diff --git a/leaf-server/minecraft-patches/features/0085-Multithreaded-Tracker.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0085-Multithreaded-Tracker.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0085-Multithreaded-Tracker.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0085-Multithreaded-Tracker.patch diff --git a/leaf-server/minecraft-patches/features/0086-Nitori-Async-playerdata-Save.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0086-Nitori-Async-playerdata-Save.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0086-Nitori-Async-playerdata-Save.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0086-Nitori-Async-playerdata-Save.patch diff --git a/leaf-server/minecraft-patches/features/0087-Optimize-nearby-alive-players-for-spawning.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0087-Optimize-nearby-alive-players-for-spawning.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0087-Optimize-nearby-alive-players-for-spawning.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0087-Optimize-nearby-alive-players-for-spawning.patch diff --git a/leaf-server/minecraft-patches/features/0088-Cache-blockstate-cache-array.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0088-Cache-blockstate-cache-array.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0088-Cache-blockstate-cache-array.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0088-Cache-blockstate-cache-array.patch diff --git a/leaf-server/minecraft-patches/features/0089-Asynchronous-locator.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0089-Asynchronous-locator.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0089-Asynchronous-locator.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0089-Asynchronous-locator.patch diff --git a/leaf-server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch diff --git a/leaf-server/minecraft-patches/features/0091-Further-reduce-memory-footprint-of-CompoundTag.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0091-Further-reduce-memory-footprint-of-CompoundTag.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0091-Further-reduce-memory-footprint-of-CompoundTag.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0091-Further-reduce-memory-footprint-of-CompoundTag.patch diff --git a/leaf-server/minecraft-patches/features/0092-Optimize-Entity-distanceToSqr.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0092-Optimize-Entity-distanceToSqr.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0092-Optimize-Entity-distanceToSqr.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0092-Optimize-Entity-distanceToSqr.patch diff --git a/leaf-server/minecraft-patches/features/0093-EMC-Don-t-use-snapshots-for-TileEntity-getOwner.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0093-EMC-Don-t-use-snapshots-for-TileEntity-getOwner.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0093-EMC-Don-t-use-snapshots-for-TileEntity-getOwner.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0093-EMC-Don-t-use-snapshots-for-TileEntity-getOwner.patch diff --git a/leaf-server/minecraft-patches/features/0094-Cache-tile-entity-position.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0094-Cache-tile-entity-position.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0094-Cache-tile-entity-position.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0094-Cache-tile-entity-position.patch diff --git a/leaf-server/minecraft-patches/features/0095-TT20-Lag-compensation.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0095-TT20-Lag-compensation.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0095-TT20-Lag-compensation.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0095-TT20-Lag-compensation.patch diff --git a/leaf-server/minecraft-patches/features/0096-C2ME-Reduce-Allocations.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0096-C2ME-Reduce-Allocations.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0096-C2ME-Reduce-Allocations.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0096-C2ME-Reduce-Allocations.patch diff --git a/leaf-server/minecraft-patches/features/0097-Lithium-Skip-unnecessary-calculations-if-player-is-n.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0097-Lithium-Skip-unnecessary-calculations-if-player-is-n.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0097-Lithium-Skip-unnecessary-calculations-if-player-is-n.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0097-Lithium-Skip-unnecessary-calculations-if-player-is-n.patch diff --git a/leaf-server/minecraft-patches/features/0098-Lithium-fast-util.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0098-Lithium-fast-util.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0098-Lithium-fast-util.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0098-Lithium-fast-util.patch diff --git a/leaf-server/minecraft-patches/features/0099-Lithium-cached-iterate-outwards.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0099-Lithium-cached-iterate-outwards.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0099-Lithium-cached-iterate-outwards.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0099-Lithium-cached-iterate-outwards.patch diff --git a/leaf-server/minecraft-patches/features/0100-Smooth-teleport-config.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0100-Smooth-teleport-config.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0100-Smooth-teleport-config.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0100-Smooth-teleport-config.patch diff --git a/leaf-server/minecraft-patches/features/0101-Use-faster-and-thread-safe-ban-list-date-format-pars.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0101-Use-faster-and-thread-safe-ban-list-date-format-pars.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0101-Use-faster-and-thread-safe-ban-list-date-format-pars.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0101-Use-faster-and-thread-safe-ban-list-date-format-pars.patch diff --git a/leaf-server/minecraft-patches/features/0102-Collect-then-startEachNonRunningBehavior-in-Brain.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0102-Collect-then-startEachNonRunningBehavior-in-Brain.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0102-Collect-then-startEachNonRunningBehavior-in-Brain.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0102-Collect-then-startEachNonRunningBehavior-in-Brain.patch diff --git a/leaf-server/minecraft-patches/features/0103-Lithium-equipment-tracking.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0103-Lithium-equipment-tracking.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0103-Lithium-equipment-tracking.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0103-Lithium-equipment-tracking.patch diff --git a/leaf-server/minecraft-patches/features/0104-C2ME-Optimize-world-gen-math.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0104-C2ME-Optimize-world-gen-math.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0104-C2ME-Optimize-world-gen-math.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0104-C2ME-Optimize-world-gen-math.patch diff --git a/leaf-server/minecraft-patches/features/0105-Cache-chunk-key.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0105-Cache-chunk-key.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0105-Cache-chunk-key.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0105-Cache-chunk-key.patch diff --git a/leaf-server/minecraft-patches/features/0106-Cache-random-tick-block-status.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0106-Cache-random-tick-block-status.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0106-Cache-random-tick-block-status.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0106-Cache-random-tick-block-status.patch diff --git a/leaf-server/minecraft-patches/features/0107-Cache-part-of-canHoldFluid-result.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0107-Cache-part-of-canHoldFluid-result.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0107-Cache-part-of-canHoldFluid-result.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0107-Cache-part-of-canHoldFluid-result.patch diff --git a/leaf-server/minecraft-patches/features/0108-Configurable-tripwire-dupe.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0108-Configurable-tripwire-dupe.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0108-Configurable-tripwire-dupe.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0108-Configurable-tripwire-dupe.patch diff --git a/leaf-server/minecraft-patches/features/0109-PaperPR-Fix-MC-117075-Block-Entities-Unload-Lag-Spik.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0109-PaperPR-Fix-MC-117075-Block-Entities-Unload-Lag-Spik.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0109-PaperPR-Fix-MC-117075-Block-Entities-Unload-Lag-Spik.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0109-PaperPR-Fix-MC-117075-Block-Entities-Unload-Lag-Spik.patch diff --git a/leaf-server/minecraft-patches/features/0110-Sepals-Rearrange-the-attackable-conditions.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0110-Sepals-Rearrange-the-attackable-conditions.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0110-Sepals-Rearrange-the-attackable-conditions.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0110-Sepals-Rearrange-the-attackable-conditions.patch diff --git a/leaf-server/minecraft-patches/features/0111-SparklyPaper-Skip-dirty-stats-copy-when-requesting-p.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0111-SparklyPaper-Skip-dirty-stats-copy-when-requesting-p.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0111-SparklyPaper-Skip-dirty-stats-copy-when-requesting-p.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0111-SparklyPaper-Skip-dirty-stats-copy-when-requesting-p.patch diff --git a/leaf-server/minecraft-patches/features/0112-SparklyPaper-Reset-dirty-flag-when-loading-maps-from.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0112-SparklyPaper-Reset-dirty-flag-when-loading-maps-from.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0112-SparklyPaper-Reset-dirty-flag-when-loading-maps-from.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0112-SparklyPaper-Reset-dirty-flag-when-loading-maps-from.patch diff --git a/leaf-server/minecraft-patches/features/0113-Optimize-checking-nearby-players-for-spawning.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0113-Optimize-checking-nearby-players-for-spawning.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0113-Optimize-checking-nearby-players-for-spawning.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0113-Optimize-checking-nearby-players-for-spawning.patch diff --git a/leaf-server/minecraft-patches/features/0114-Cache-supporting-block-check.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0114-Cache-supporting-block-check.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0114-Cache-supporting-block-check.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0114-Cache-supporting-block-check.patch diff --git a/leaf-server/minecraft-patches/features/0115-Avoid-useless-deque-clear-on-LevelTicks-cleanupAfter.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0115-Avoid-useless-deque-clear-on-LevelTicks-cleanupAfter.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0115-Avoid-useless-deque-clear-on-LevelTicks-cleanupAfter.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0115-Avoid-useless-deque-clear-on-LevelTicks-cleanupAfter.patch diff --git a/leaf-server/minecraft-patches/features/0116-Replace-brain-activity-maps-with-optimized-collectio.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0116-Replace-brain-activity-maps-with-optimized-collectio.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0116-Replace-brain-activity-maps-with-optimized-collectio.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0116-Replace-brain-activity-maps-with-optimized-collectio.patch diff --git a/leaf-server/minecraft-patches/features/0117-Remove-stream-in-villagers.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0117-Remove-stream-in-villagers.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0117-Remove-stream-in-villagers.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0117-Remove-stream-in-villagers.patch diff --git a/leaf-server/minecraft-patches/features/0118-Optimize-baby-villager-sensor.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0118-Optimize-baby-villager-sensor.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0118-Optimize-baby-villager-sensor.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0118-Optimize-baby-villager-sensor.patch diff --git a/leaf-server/minecraft-patches/features/0119-Only-player-pushable.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0119-Only-player-pushable.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0119-Only-player-pushable.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0119-Only-player-pushable.patch diff --git a/leaf-server/minecraft-patches/features/0120-Remove-iterators-from-Inventory-contains.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0120-Remove-iterators-from-Inventory-contains.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0120-Remove-iterators-from-Inventory-contains.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0120-Remove-iterators-from-Inventory-contains.patch diff --git a/leaf-server/minecraft-patches/features/0121-Alternative-Brain-Behaviour.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0121-Alternative-Brain-Behaviour.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0121-Alternative-Brain-Behaviour.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0121-Alternative-Brain-Behaviour.patch diff --git a/leaf-server/minecraft-patches/features/0122-Cache-eligible-players-for-despawn-checks.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0122-Cache-eligible-players-for-despawn-checks.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0122-Cache-eligible-players-for-despawn-checks.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0122-Cache-eligible-players-for-despawn-checks.patch diff --git a/leaf-server/minecraft-patches/features/0123-Slightly-optimise-getNearestPlayer.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0123-Slightly-optimise-getNearestPlayer.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0123-Slightly-optimise-getNearestPlayer.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0123-Slightly-optimise-getNearestPlayer.patch diff --git a/leaf-server/minecraft-patches/features/0124-ShreddedPaper-Don-t-block-main-thread-in-Connection-.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0124-ShreddedPaper-Don-t-block-main-thread-in-Connection-.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0124-ShreddedPaper-Don-t-block-main-thread-in-Connection-.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0124-ShreddedPaper-Don-t-block-main-thread-in-Connection-.patch diff --git a/leaf-server/minecraft-patches/features/0125-Use-ensureCapacity-to-pre-populate-the-size-of-ticki.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0125-Use-ensureCapacity-to-pre-populate-the-size-of-ticki.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0125-Use-ensureCapacity-to-pre-populate-the-size-of-ticki.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0125-Use-ensureCapacity-to-pre-populate-the-size-of-ticki.patch diff --git a/leaf-server/minecraft-patches/features/0126-Directly-use-the-pre-filtered-ticking-chunks-list-as.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0126-Directly-use-the-pre-filtered-ticking-chunks-list-as.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0126-Directly-use-the-pre-filtered-ticking-chunks-list-as.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0126-Directly-use-the-pre-filtered-ticking-chunks-list-as.patch diff --git a/leaf-server/minecraft-patches/features/0127-Bulk-writes-to-writeLongArray-during-chunk-loading.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0127-Bulk-writes-to-writeLongArray-during-chunk-loading.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0127-Bulk-writes-to-writeLongArray-during-chunk-loading.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0127-Bulk-writes-to-writeLongArray-during-chunk-loading.patch diff --git a/leaf-server/minecraft-patches/features/0128-Optimize-AABB.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0128-Optimize-AABB.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0128-Optimize-AABB.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0128-Optimize-AABB.patch diff --git a/leaf-server/minecraft-patches/features/0129-Improve-sorting-in-SortedArraySet.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0129-Improve-sorting-in-SortedArraySet.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0129-Improve-sorting-in-SortedArraySet.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0129-Improve-sorting-in-SortedArraySet.patch diff --git a/leaf-server/minecraft-patches/features/0130-Make-removeIf-slightly-faster.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0130-Make-removeIf-slightly-faster.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0130-Make-removeIf-slightly-faster.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0130-Make-removeIf-slightly-faster.patch diff --git a/leaf-server/minecraft-patches/features/0131-Optimize-LinearPalette.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0131-Optimize-LinearPalette.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0131-Optimize-LinearPalette.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0131-Optimize-LinearPalette.patch diff --git a/leaf-server/minecraft-patches/features/0132-Slightly-optimized-VarInt-write.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0132-Slightly-optimized-VarInt-write.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0132-Slightly-optimized-VarInt-write.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0132-Slightly-optimized-VarInt-write.patch diff --git a/leaf-server/minecraft-patches/features/0133-Rewrite-ClientboundLightUpdatePacketData.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0133-Rewrite-ClientboundLightUpdatePacketData.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0133-Rewrite-ClientboundLightUpdatePacketData.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0133-Rewrite-ClientboundLightUpdatePacketData.patch diff --git a/leaf-server/minecraft-patches/features/0134-Some-Optimizations-on-SerializableChunkData.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0134-Some-Optimizations-on-SerializableChunkData.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0134-Some-Optimizations-on-SerializableChunkData.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0134-Some-Optimizations-on-SerializableChunkData.patch diff --git a/leaf-server/minecraft-patches/features/0135-Rework-ChunkHolderManager.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0135-Rework-ChunkHolderManager.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0135-Rework-ChunkHolderManager.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0135-Rework-ChunkHolderManager.patch diff --git a/leaf-server/minecraft-patches/features/0136-Optimize-chunkUnload.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0136-Optimize-chunkUnload.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0136-Optimize-chunkUnload.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0136-Optimize-chunkUnload.patch diff --git a/leaf-server/minecraft-patches/features/0137-Async-chunk-sending.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0137-Async-chunk-sending.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0137-Async-chunk-sending.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0137-Async-chunk-sending.patch diff --git a/leaf-server/minecraft-patches/features/0138-Spawner-Configurations.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0138-Spawner-Configurations.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0138-Spawner-Configurations.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0138-Spawner-Configurations.patch diff --git a/leaf-server/minecraft-patches/features/0139-SparklyPaper-Parallel-world-ticking.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0139-SparklyPaper-Parallel-world-ticking.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0139-SparklyPaper-Parallel-world-ticking.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0139-SparklyPaper-Parallel-world-ticking.patch diff --git a/leaf-server/minecraft-patches/features/0140-SparklyPaper-Track-each-world-MSPT.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0140-SparklyPaper-Track-each-world-MSPT.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0140-SparklyPaper-Track-each-world-MSPT.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0140-SparklyPaper-Track-each-world-MSPT.patch diff --git a/leaf-server/minecraft-patches/features/0141-PaperPR-Fix-cancelled-Projectile-Events-still-consum.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0141-PaperPR-Fix-cancelled-Projectile-Events-still-consum.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0141-PaperPR-Fix-cancelled-Projectile-Events-still-consum.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0141-PaperPR-Fix-cancelled-Projectile-Events-still-consum.patch diff --git a/leaf-server/minecraft-patches/features/0142-Optimize-SetLookAndInteract-and-NearestVisibleLiving.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0142-Optimize-SetLookAndInteract-and-NearestVisibleLiving.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0142-Optimize-SetLookAndInteract-and-NearestVisibleLiving.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0142-Optimize-SetLookAndInteract-and-NearestVisibleLiving.patch diff --git a/leaf-server/minecraft-patches/features/0143-Remove-streams-on-InsideBrownianWalk.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0143-Remove-streams-on-InsideBrownianWalk.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0143-Remove-streams-on-InsideBrownianWalk.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0143-Remove-streams-on-InsideBrownianWalk.patch diff --git a/leaf-server/minecraft-patches/features/0144-Use-BFS-on-getSlopeDistance.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0144-Use-BFS-on-getSlopeDistance.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0144-Use-BFS-on-getSlopeDistance.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0144-Use-BFS-on-getSlopeDistance.patch diff --git a/leaf-server/minecraft-patches/features/0145-Paper-PR-Throttle-failed-spawn-attempts.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0145-Paper-PR-Throttle-failed-spawn-attempts.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0145-Paper-PR-Throttle-failed-spawn-attempts.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0145-Paper-PR-Throttle-failed-spawn-attempts.patch diff --git a/leaf-server/minecraft-patches/features/0146-Improve-BlockEntity-ticking-isRemoved-check.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0146-Improve-BlockEntity-ticking-isRemoved-check.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0146-Improve-BlockEntity-ticking-isRemoved-check.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0146-Improve-BlockEntity-ticking-isRemoved-check.patch diff --git a/leaf-server/minecraft-patches/features/0147-Raytrace-AntiXray-SDK-integration.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0147-Raytrace-AntiXray-SDK-integration.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0147-Raytrace-AntiXray-SDK-integration.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0147-Raytrace-AntiXray-SDK-integration.patch diff --git a/leaf-server/minecraft-patches/features/0148-Optimize-addOrUpdateTransientModifier.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0148-Optimize-addOrUpdateTransientModifier.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0148-Optimize-addOrUpdateTransientModifier.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0148-Optimize-addOrUpdateTransientModifier.patch diff --git a/leaf-server/minecraft-patches/features/0149-Optimize-ContextMap.create.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0149-Optimize-ContextMap.create.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0149-Optimize-ContextMap.create.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0149-Optimize-ContextMap.create.patch diff --git a/leaf-server/minecraft-patches/features/0150-Micro-optimizations-for-random-tick.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0150-Micro-optimizations-for-random-tick.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0150-Micro-optimizations-for-random-tick.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0150-Micro-optimizations-for-random-tick.patch diff --git a/leaf-server/minecraft-patches/features/0151-Remove-streams-on-updateConnectedPlayersWithinRange.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0151-Remove-streams-on-updateConnectedPlayersWithinRange.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0151-Remove-streams-on-updateConnectedPlayersWithinRange.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0151-Remove-streams-on-updateConnectedPlayersWithinRange.patch diff --git a/leaf-server/minecraft-patches/features/0152-Remove-streams-on-PlayerDetector.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0152-Remove-streams-on-PlayerDetector.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0152-Remove-streams-on-PlayerDetector.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0152-Remove-streams-on-PlayerDetector.patch diff --git a/leaf-server/minecraft-patches/features/0153-AsyncBlockFinding.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0153-AsyncBlockFinding.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0153-AsyncBlockFinding.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0153-AsyncBlockFinding.patch diff --git a/leaf-server/minecraft-patches/features/0154-Direct-iteration-on-Sensing.tick.patch b/leaf-archived-patches/unapplied/server/minecraft-patches/features/0154-Direct-iteration-on-Sensing.tick.patch similarity index 100% rename from leaf-server/minecraft-patches/features/0154-Direct-iteration-on-Sensing.tick.patch rename to leaf-archived-patches/unapplied/server/minecraft-patches/features/0154-Direct-iteration-on-Sensing.tick.patch diff --git a/leaf-archived-patches/unapplied/server/paper-patches/features/0001-Rebrand.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0001-Rebrand.patch new file mode 100644 index 00000000..9a49e32a --- /dev/null +++ b/leaf-archived-patches/unapplied/server/paper-patches/features/0001-Rebrand.patch @@ -0,0 +1,730 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> +Date: Thu, 16 Sep 2021 20:39:45 -0400 +Subject: [PATCH] Rebrand + + +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +index 3d8ed4ff9a5a30d123508aeb485250271b528a6e..49ac2b52fc134bfa77a108bf58de3e81be38c683 100644 +--- a/src/main/java/com/destroystokyo/paper/Metrics.java ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -592,7 +592,7 @@ public class Metrics { + boolean logFailedRequests = config.getBoolean("logFailedRequests", false); + // Only start Metrics, if it's enabled in the config + if (config.getBoolean("enabled", true)) { +- Metrics metrics = new Metrics("Gale", serverUUID, logFailedRequests, Bukkit.getLogger()); // Gale - branding changes - metrics ++ Metrics metrics = new Metrics("Leaf", serverUUID, logFailedRequests, Bukkit.getLogger()); // Gale - branding changes - metrics // Leaf - Rebrand + + metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { + String minecraftVersion = Bukkit.getVersion(); +@@ -602,15 +602,15 @@ public class Metrics { + + metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); + metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : "offline")); +- final String galeVersion; // Gale - branding changes - metrics ++ final String leafVersion; // Gale - branding changes - metrics // Leaf - Rebrand + final String implVersion = org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion(); + if (implVersion != null) { + final String buildOrHash = implVersion.substring(implVersion.lastIndexOf('-') + 1); +- galeVersion = "git-Gale-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash); // Gale - branding changes - metrics ++ leafVersion = "git-Leaf-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash); // Gale - branding changes - metrics // Leaf - Rebrand + } else { +- galeVersion = "unknown"; // Gale - branding changes - metrics ++ leafVersion = "unknown"; // Gale - branding changes - metrics // Leaf - Rebrand + } +- metrics.addCustomChart(new Metrics.SimplePie("gale_version", () -> galeVersion)); // Gale - branding changes - metrics ++ metrics.addCustomChart(new Metrics.SimplePie("leaf_version", () -> leafVersion)); // Gale - branding changes - metrics // Leaf - Rebrand + + metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { + Map> map = new HashMap<>(2); // Gale - metrics - reduce HashMap capacity +diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +index b78828e83d8128eace986aeb73213da3b3f905e4..f59879ae7d3c73cd4c4233d30667988bf22f12f1 100644 +--- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java ++++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +@@ -20,7 +20,7 @@ public final class PaperConsole extends SimpleTerminalConsole { + @Override + protected LineReader buildReader(LineReaderBuilder builder) { + builder +- .appName("Gale") // Gale - branding changes ++ .appName("Leaf") // Gale - branding changes // Leaf - Rebrand + .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) + .completer(new ConsoleCommandCompleter(this.server)) + .option(LineReader.Option.COMPLETE_IN_WORD, true); +diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java +index 2596e0ee4df5b96f181e28a742ef345981fc97e3..5b844d2fea387f2cb655169f458ec0ca627f1c65 100644 +--- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java ++++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java +@@ -32,6 +32,9 @@ public record ServerBuildInfoImpl( + + private static final String BRAND_PAPER_NAME = "Paper"; + private static final String BRAND_GALE_NAME = "Gale"; // Gale - branding changes ++ // Leaf start - Rebrand ++ private static final String BRAND_LEAF_NAME = "Leaf"; ++ // Leaf end - Rebrand + + private static final String BUILD_DEV = "DEV"; + +@@ -43,9 +46,9 @@ public record ServerBuildInfoImpl( + this( + getManifestAttribute(manifest, ATTRIBUTE_BRAND_ID) + .map(Key::key) +- .orElse(BRAND_GALE_ID), // Gale - branding changes ++ .orElse(BRAND_LEAF_ID), // Gale - branding changes // Leaf - Rebrand + getManifestAttribute(manifest, ATTRIBUTE_BRAND_NAME) +- .orElse(BRAND_GALE_NAME), // Gale - branding changes ++ .orElse(BRAND_LEAF_NAME), // Gale - branding changes // Leaf - Rebrand + SharedConstants.getCurrentVersion().getId(), + SharedConstants.getCurrentVersion().getName(), + getManifestAttribute(manifest, ATTRIBUTE_BUILD_NUMBER) +@@ -62,7 +65,11 @@ public record ServerBuildInfoImpl( + + @Override + public boolean isBrandCompatible(final @NotNull Key brandId) { +- return brandId.equals(this.brandId) || brandId.equals(BRAND_PAPER_ID); // Gale - branding changes ++ // Leaf start - Rebrand ++ return brandId.equals(this.brandId) ++ || brandId.equals(BRAND_PAPER_ID) ++ || brandId.equals(BRAND_GALE_ID); // Gale - branding changes ++ // Leaf end - Rebrand + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index f6bc955c3496b52cda1a20aabd78769803ef471f..f6f787db016f4d1ac14648ebf2b8e162a3e85962 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -491,7 +491,7 @@ public class CraftScheduler implements BukkitScheduler { + this.parsePending(); + } else { + // this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(this.currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper +- task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Gale"); // Paper // Gale - branding changes ++ task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Leaf"); // Paper // Gale - branding changes // Leaf - Rebrand + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index ebe1136e2487d0d13e5a924a644f2237900a86a6..bef2ae29856a72344d3d755926f1b2dce4907df1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -508,7 +508,7 @@ public final class CraftMagicNumbers implements UnsafeValues { + // Paper start + @Override + public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { +- return new org.galemc.gale.version.GaleVersionFetcher(); // Gale - branding changes - version fetcher ++ return new org.dreeam.leaf.version.LeafVersionFetcher(); // Gale - branding changes - version fetcher // Leaf - Rebrand + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +index 0b5979723bb30f9011ac64c36d894aa41713ec9b..c3d45e60e262b8e34d76f0425f6bef79f034e8ab 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/org.galemc.gale/gale-api/pom.properties"); // Gale - branding changes ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/cn.dreeam.leaf/leaf-api/pom.properties"); // Gale - branding changes // Leaf - Rebrand + 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 349f8207d8a9bc4b2c6be9e64b4325a7a406e706..e45d5da04428c26fc6aa97fba974bde3573d7950 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -25,7 +25,7 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre + private volatile boolean stopping; + + private WatchdogThread(long timeoutTime, boolean restart) { +- super("Paper Watchdog Thread"); ++ super("Watchdog Thread"); // Leaf - Rebrand - Purpur - use a generic name + this.timeoutTime = timeoutTime; + this.restart = restart; + this.earlyWarningEvery = Math.min(GlobalConfiguration.get().watchdog.earlyWarningEvery, timeoutTime); // Paper +@@ -82,15 +82,15 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre + We do not want people to report thread issues to Paper, + but we do want people to report thread issues to Gale. + */ +- logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug. This could be a Gale bug."); // Paper ++ logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug. This could be a Leaf bug."); // Paper // Leaf - Rebrand + // Gale end - branding changes + logger.log(Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author"); + logger.log(Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring"); + logger.log(Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once"); + logger.log(Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes"); +- logger.log(Level.SEVERE, "If you are unsure or think this is a Gale bug, please report this to https://github.com/GaleMC/Gale/issues - and if you think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues"); // Gale - branding changes ++ logger.log(Level.SEVERE, "If you are unsure or think this is a Leaf bug, please report this to https://github.com/Winds-Studio/Leaf/issues - and if you think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues"); // Gale - branding changes // Leaf - Rebrand + logger.log(Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports"); +- logger.log(Level.SEVERE, "Gale version: " + Bukkit.getServer().getVersion()); // Gale - branding changes ++ logger.log(Level.SEVERE, "Leaf version: " + Bukkit.getServer().getVersion()); // Gale - branding changes // Leaf - Rebrand + + if (net.minecraft.world.level.Level.lastPhysicsProblem != null) { + logger.log(Level.SEVERE, "------------------------------"); +@@ -115,13 +115,13 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre + We do not want people to report thread issues to Paper, + but we do want people to report thread issues to Gale. + */ +- logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - If you think this is a Gale bug, please report it at https://github.com/GaleMC/Gale/issues - THIS IS NOT A PAPER BUG OR CRASH - " + Bukkit.getServer().getVersion() + " ---"); ++ logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - If you think this is a Leaf bug, please report it at https://github.com/Winds-Studio/Leaf/issues - THIS IS NOT A PAPER BUG OR CRASH - " + Bukkit.getServer().getVersion() + " ---"); // Leaf - Rebrand + // Gale end - branding changes + logger.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); + } + // 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 Gale!):"); // Paper // Gale - branding changes ++ logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Leaf!):"); // Paper // Gale - branding changes // Leaf - Rebrand + 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, "------------------------------"); +@@ -139,7 +139,7 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre + We do not want people to report thread issues to Paper, + but we do want people to report thread issues to Gale. + */ +- logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - If you think this is a Gale bug, please report it at https://github.com/GaleMC/Gale/issues - THIS IS NOT A PAPER BUG OR CRASH ---"); ++ logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - If you think this is a Leaf bug, please report it at https://github.com/Winds-Studio/Leaf/issues - THIS IS NOT A PAPER BUG OR CRASH ---"); // Leaf - Rebrand + // Gale end - branding changes + } + +diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png +index e7e9fd9a6077535b89c6c9d7b0164e8b87c54bed..9e698edad90ebcd641fc59ade84643556b427070 100644 +GIT binary patch +literal 19657 +zcmbTdWmFtZ)HOPTyE}sf_W;42;I4zaI|TP2!QI{6-EDvbm!QEJf;&Nj=JLGvd)Ie= +z-yhw*x@&cHRh>F}?{lg;N>y0~9fbr1005xN$x5ofU&sDCkPzO_bvpI=?-w|0aV2p8 +zpeX_M#S|U@K#{YRkWh6~m-$R7Cndqd!Oz3P%E`t70LVt=X?W?RJP?R%KUiXFeO|e0 +z%5VqKY#x9+ne +zm>jZ({{aA8!TNXyx;Kix02`bEFaVb&HX5AKoqwU-s&v`_$|L}k3g-|Nn5YgIW78bN +z1B?*?8Z}xhPynd_fP;_!XDUE7I^gV9P6QsXQkAkn2v{iwRUrZ5fPgFp85$U|9)Jlr +zSe*q1G6X2B6{BKkVJ{W)mIqozpr6O!0 +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 +zh{GqAp*NSxpuHDs-O23fw&RYB! +zIG;O>9Rizs-o&dV38%C6-e31)MhJ6|HpA2RGmUAt5DB%`@J-=6l`MmvBju0puMd~z +z1Umza>W@%^QpzI!So_qtLa~DT)G4(8ac&q@ocPr +zwDt?BC$=PsRn~k}Sbf?58-_x6+$(qJBLp=_5MLNRAh`%GKGt8(2;f#kQU-JHnRblF +z^q@GF7DK-AUS)O!IqU|C5c<9@AG<%Xi{XXiFckyJR<%e@$&D_*%ipW}`dLIiWGeTe +zBSEL2*hx-L>;#_=x3T=PReXfbpx#XT;>>tvYZNMk5M3R!xm9&eR1b0F +zyI{4DexDV*wZUbel6_~&*_5>5i2mc0+;XLUkxOK``-ZGtrk>TN=2-@xJ>caEQ@&dJ^K>c +z0otHiWf>vJ7Y#CK;=({#e0IT2UVBj%2PSwy8O5QDuOIR;%ZC*r?3CEy`H8!!bnKLy +z5aq0g3{txK8xjiYjr*333(CJf&h%BRPiFr058>vlbmU&yQCJ5`&|VYd#u7F>k@jCI-Kb*Ko4Us&mcjd7z!8P^le6mR9iarijfh_ves +z?OcFG*ZCR0LFbs%t3RyMV$E%^=1jYbZ-}| +zN46Bj?jb!1sn#)t98z_<-o#)nwl#N!eMOjDK$%fBCK4tAxT0RELoK64NQw3x5l}G{ +z&s1HA?sjAcO`ly{T)eZn^IH*bf`_*;Gtn`yExpjz1%nY$L82dTq2V%2VoVz|7np#L +z>bKQSQlVSxq-B_hGJ)XfHqTDz&*JGO3KzWRFG;=N)h|d6&c9+ugI{;5l+7^261aj4 +z;!_AjOOG-nST0gBy9Sfw^H-r)T$p?zoJ0hi^&38rx%ycd42*jqM#yzYbH6zAF*=w9 +zT+5ONV^no?YBQ^dvSMZmW#^`Ql!r!UIg3sahm@#JDr!4nY!MQIXq}f>LN|<*DjJ)L +zH1V6F;hj?4P2HtOXAV|2HQK$Jp^eiYzp+^c`NLjef;au9R67R+LY11gm~ytX^Tq0#Un2)U +z!GUyLctgh;#sXt$uY5-~oS)m@aJ+kj3=2Npr0H5vrh*7`kR`L9%G8&6QpfS633oI* +z6tF2ffd5dh=Ccr*4&&#~S-V{Wo?Kk;w6|f|4_RDv#?=vI;x`WfGRRniLZiu+fi76B +zIfxOz4HqxA!drRM2rVlF{)chXq!+Urg;mJ;m6_|(Q8#E%$U5<`j+ +z@ASg}k56bC5#yX=>=03=sX*pvB5tsVujFNjMCz{EBn1@729JC#4=o|Y1?_3Lw!sfL +zdSkeh3YS@4P_hw8U}|Jt%OL(|$Kvbb4dwEQFw_fJzU0TRMDDq?V`-f&x&syFZ^Tns +z@DW*mgP}+h>^U4EdV~n^pIKWBy7r)bUtL<=a+F3F&0X;gx*mO$WfF7Dt5V}UR@Ra? +z4xmMIU*O-{{J`vch~;7v{#e5J^|sUXnII`3i2B$X5Uau^ZMwr@S&D@Hhd$b$* +z>J9>4Q%P+{_+7#c~xu#BH+HAA`dxJWCY#kKlMqxSUtKZV=tv +z7##J?zMIeFA5R2k41>O4V>_KJvoOZCSi~-3qBg83Z0!_myt`Bz6!IMdUWS<^9t2{% +zp@8ALu4^9%BySFQpyg6jdg@Yf0Z?9DN#HL;v6FmhY6OBlQopkDsVr?k8Md|<0{Hk4 +z+C@VjF%aUz<5$v1D=JhtG +zwOpy<{|>gq8pY5{4BTj7FSzTTS&dxalbOIE(1J$^ai2t11|4fKVCLbOjfZcnV$W{! +z!Tdi{{Rnz@9Tw-Mq|nfSkl|Rn@Q&K*)M@mc-VE}Vs&x3TC07hUDo9W8B^eBc%1yUx +zlyj`r#CJ#TX)=A6#L$kc3jV>l8Al#6jfC-~(+Nu_m%S(5Usupj>Q;9oi&_<}Jtaq5C +zRUe!UQ}gg3C}3{yhXvBVRsyaE7@zt~v~$VJL(7;uSO-L}4n{Hy4nJ?h9^@l}=JME~ +zk&WfPbOyzWE)b;k@(%HiE!0{xzs% +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 +zNzQ*D +zY}>?Hr)`DUyE^0tkZx#{_S`~Mf{i$hHq +z_(bZD?1M$|pf?Za>{-oyoXIb0oWVcGJ_RIKSl;59w3JHK-qQ@U*CWXSu|hn%KmUMT +zhqie@*Z-lh=L;IJIr9GgOX6PNQUJzzW4n6ar--KyQ%U_P_&XRou4+5SJjIO +zhj)MnLOlKXBH~S+M3HmliltUIH<{D);QL#VonZ-m^^k1H@$FIL$=|cNv*_{v$h^^i +z&XglLI4E^J+_EvJ@x#evb`}U(YF8t{u~`gHA&6-Sd{d{gsuw%aDR*eGCYlct*8GA- +zjTmsFxE(Yp?q5`pNJX{orr@lMs%@ +z@F!2V%{L>E%inkl00#)<3?C>&zHURa;r0(>H_8(c#3wKL<>J6{w>CA3c;#EnNNWPK +zY*@M+u1l)8Wtoz4*-+{vhi9d<2W9jP+`glcXnd^2_}wqX#Z^oZQ*c^i6aW53m@R`a2)@EHveT2M+sEvq +zL+-$i5?>k#t*z;`#UNgNzbRS2B0_E#Sa1@0AON(XhmWq`Mv@KoB?zWwCZ5(rz(vQT +ze5CiL_w!S%SXibeoLfM5SDpkJ59i5*)B<~=^Bw8~UN)eSH`C^chl54WFo>O`ZV!ZB +zLbAVAUPqx&nn +zkK;4W{oH*YtT7zQwzSZ3yoj{4aJA&hDjDzP+2KWz$fSWk_JeSeIM?j)#UcJCoHDtf +zix^#5-T5d(komj&2yq>pJ=)r55{}D8yMIYx@28}#-9siGX0QKf?&Mzldj+5Ld3_NS +z4AiKwIEh(D;yK|w(SqTE9n%8GtSPKb#h09Z4Su5}t!eD(Q79?|%yRu2XN(PaXA2*s +z71i6PgC|vpxWOcF>x1^Kb#TF0oD3Wt?mp_nB|KW5!a(bex>_ +z3BzXnSRUV4?S>U3oNUa%Oqj +z8OwH5UT5?Ojujj-vCRnqbP;E&9_ik5DSHdY9Aj-{-YonuU2_duuXI;W^WN3+orhb7 +zJRK)S$2%vtD)rKMa$$Q2xEzwD%0$f66Q|lxI-cRFU}3Y97G~cZ-ef#Wt2i;j3h}G& +zPAl4|^*Z>mC(S;^Z>wL{dH^rH(3EjjEYphZH}CB5(U%t~HjStQwWejfS1Om$osi)< +z;NTxys9&(06D1hl{#4^aRM^V0?7`uNnWj(8gqY2XtWt)pJw{&ptr%tL;5d`f>M3`$ +z+QPfTB&E~1subz8-101Fr-UcP(;OUIPo6_QTk2=W9VEW3@xXOiMdyVMFQdr@gJ`+|aOq^W3WiPPh5f2SB17BQS7y+u +znv)_G?e61!>;Z#_6P4nSYYJeGHH<_B7wt?r0+SaVPinhS7F@HQaMwp=3mYl;!&Sg_ +zxqGs`&Q|2q0HbiHSw2nW|X|CK%RDO4-gHNAMK0a~2 +z&YnyKR4pXATU@2@GP9*LB^x)xj$4?u35s!X5=FZ<@h7aVHuJO2@D-S@)`pOw@MfK= +z9CF^x_2TSZNH39)5xmnwrrNyMm8sOfi`p-XD1^(|DKb`=&w7J4jaVCe$QSidF#s%1 +z2_M?LGU>3Ie$)QQaSi->Rbx!*2n4SLU%ZDO2OP|@h;~Cf=R#6$wnx0KNib&@7hwVH +zrC0tpk%Ev>1@u%Kqac3_Z`HZc$Iif<;c6-VoDyVKD4DBALXv;GGa4A4G-u+Vd}iyx +zB?i*=Q`v98}{1Lo29R9EJ +z;#fEkn@a$Q^4g#w1#Xchdc-*jHX%^b^+Ak{jAF9otzN%Qcsl21vs-?4# +z`1Sp0U7=U@=|}k;4dj5T`z_Xdrafi|@k}WzhLHuDqeAZok%mpu#=^ujH60 +zPJz$VQfn*sbP-b{nen&g4td3f_wvG#@ny +zHYrU=OK(@s`Ss%dM~&u%iMYDd%+0Uj@-?AhB!FRbp@4n#lTQA7+zp_Jam2_GK?ALs +zC%*F~Cd1Qn%abt}1LWuT$*?EiN%gk+$O`x-%}bHW!YR(c+FY$Q1q}~&6^mS|a&cpe +z8(lG?*YtqNMA$E&nMm?RdNgGQr#zc`;D<5yE+vAfk0w5c_r +z;BdO-%vP$}c5^q!oh+8_Yqm^~Z!gI6Jd6fDR#|#0zGAzm<1@imsU?LxO(o=M;x@+A +zzie9=Ik{reUvQEqDD)iuVh}PO?mY85Yq5FH-LyaqAsSDEYO4Jh_fS*HF1!GWt3MxJ +z3zSX0M&%NMPsbcLtDVZbt?{F^-EubNzom9@B6#YLC=|vzie+da6tM0-69sovPLx>& +z4B&p$M5BsaX02rwheb}qRSBZ^Gku3fe%BX|+u>{e? +zjYIUHWA}-tWv%ghz~A(vC+Z~-BDc<30vzyffRyph?)$zb16L+~7#lRr8pW3e4i~Vh +ziMjc=N;Gf-plkDC2tqZ1V=OHODAAHMDw<--4-XJw){T901}uhrmrW;#^Ql(1ek}ux1n<4;?~H>{`F368o>iTeX3f5)-2M+3``WhXxR~Jny +ztMzgqE4jLAP?WEw3FZvPd8JJ{P^gT)uzREJX}t8GvJqLDWC$w?W<+bUK? +z!u`)q2aI`8+hd6kZCi{P+4&ybxjXK59CtjkQO~m*4D!wfb|Wjxzby{J#A<4RMQ; +zG-=jvYH6F8Ksv~*w0;snxT8g1F)3x*6En?Z;i~WPFVagD?ZW!4G!XKATt0k}O&;6vS>mnylV42j8t&gkH4lQ3`=&!F!?Sj0snCPePbg}spUx9AqMtMal4F0k^ +z@G-9Yo^_TtuXJu8Lt~Y&Klf1wK6!)xExd7W9u$^rMWti#HL;QV7AYE;f7}z+D%u-g +z#$^vgiw@bdTW<~ct&4uws{uAHt>01HoqGOU6MZfEF8z^3)DyL(yj +z*H6*U9hBoTB8O$6l{)!v{M8@FRzc4|8MzQHw&iV-HDhc`0rH}SrI9{CZ`Mbciwl3Yr^XhGUjDoyq?KiPLPTMb=A_=C~T6*Zo44WS8r645N +z`SK6=aV@P7n*%SFD-6y(!yZ9DKg|-gW46GSY7u^>$A13Sa4K{J**xDSp;v^f_ss#h +zBzr74paSr%d8iECgvB9^4R^)s;IGJ2Pb&B|myOgNg2|se635ispL<;o%VbP)pqLRC +zYt3wyh|&uQNS#rV<8l!&L^#f1Au=P^Hru8m0xPeWq!$$UV>P)SVbka*-E3W+YDXq18G7YdjIaQ}<$;{=L>TGR9&+v&mIOODh50dd75((I&#vt@K`pa8z3) +zmXHXmdQtZGT)V|r?Cg!1ppMSX&eV#Yc&tcU_-$OUi9UX`K(^ao6F$+RAA6>tmA2&Zm(a8%}eP>F-F#Wns}6b>My +zlc(TZX63`3LYH`1Rn$A^Lo +zQOpQ=11EU-M~+JiN{;GD+u#N0 +z9N=Tz6&HQ#P#_#Q)UAj#78e9!MUoS8B(p~xkZd;E69YhL`#-Z0Q>&us3UMD%Puqi{ +z98ST1IEG&+jznizO{j*vg-iqNTU307z;n(CzqjbepqF2#ilyYRf(kVLw!`+g%0Yk^ +zv~~PKIP!gN@c8&>8Lhvnyq|~JW$14NP`u?}5Kxwqbc8u5n_`{Ba6Y-Rc!Z#TM#cG; +zlf~dI%EEStFejfXVH}?AHw)=}#t>fJ~Ii#lQ4#n-Y +zG4h3?Z0fm4%KLo^l2=n`dhY}qbY;WK-~aqgwS=#zETE$Liec61RoaeSodQZ3B-Pb-b)obYYQR3&FartS|1&WVL{w21T#&W4?ihzZ-{$MNPsz=x7+QT0N-owE_WV||Kxg8jQS|BCV=#2~NqYl?5-&Up8JO)Rg1 +z8wWcb7l@#!r240*B6R9#MP>CR`VF$l$VZqy0|34_N_A-rH)O1CgzkgExG-!^uQUt| +zB_wosDOEmp=AhBm@a99NfXRq@scj2c_BRazLxdP<)F2ZQtj}HZ@4x7L)s$?Zuhmxn +zVrpOV5M}r!zveQkc-u(M13D`2+G>M8xuCDsFE@wl*6F&?XukZ9vv-vw%Ru=Did&`j +ztm?iG*He?81eYN*GBwraCTAf~skuVjCUN#w%M@rzqXxr7MVWPv-hs#?D{U6}?Gsig +zQ)c+lTH4LSygUZ*@2`-4`VJT53){H6Iwfg!fm0OCJBpz78oMJ67*Rog*4zXF$5Ov1 +zzN;9By=fyeuV#~hU-eDySRMY-jK{Piv5@&!eMxP>o2Dw1Ag1n%&-Vx;yq_!}vYQ{^ +zCAWH(`pAgNbv;;|sA1F~w_3&S#gvKUbZqphX2)jZ+k&Do#D%%Q0Ey#%O{!eO0mzoc +z#^G{6KGQa_fV?-Vx?>s&C>3KE;m<85en3=lLc}0~PwpGw6GrKUY?5!9TEME%$x<9- +z62wgGZAUMxhj6a<N2Idn)S2P6yHzAA +z31)aU`r9wL{U_VY%E>KV~XJi!9R_>pgRSjy}Wfrj71Zxad*;o=@&WupTWi^ +z^}pZ(Z`sk@6e5tZf{ayf1%nzk5&2ZzuWa#(hfXfgr%^<0=GhR9(l(5Zjr-G7)iXtd +z(|>1eM}+>3<%-m#Vg|o++=8n^ipiSY61zq}qfZdrYKcl;^+UGavu( +z{)DRNtE&-sx)hF*>+*{`ZW5pVJx3U~&VLUw5$IU(Z~es-S{?~-cm`bvAj5175jORz +z6WrL7$?Uiraez-%vGKB@{PQneQKd@juxQ%w21-+Jvk@g)8MXcBpxqm;Hn@3Oo)dja +z-HQit!FmG4!J{cI66~D3^~J39Zx46@_+gh)-DEeyJnbDiRTH&38Ux7taKOAmiCW?y0^Tq{^fWrn9=j)ORPERIlE +zg>JWtuV}k#e8aJyXr=Z0C-vbAqfUaC6EOiNr%n5@T#c_bX&*?P=Fell$4K@>76!w` +z@k@fYS;i2@6QM%vhrAz6z8S>lD@qAoK*GEilyfGTG#!v{GeL-EQ0;(=ucr!NgBftOeYeLYS#61 +z=2ddjfTl(Ea@9&XsQ{Hx`A@v2t{vh;4*2~PI~AYWT6g&dx<Pj4(R10q +zh#DdPTUrl}P$ER7G?y}t5ybwJ-9E#~r+RCey3q0rZc#U$86R(>^e85@KH?1H{rf|N +zo=BKa9k#W|rp+lB|C1RhYZNO^rM?pJ>|Y;zrpwoBQ|6@Z+xp>P5(3N`JPd@BLpr$6 +zXETmwqD5DsWqu#194?$%n)>)B?eD_%9;+|1x3Q8sW|y%DWFneUjEYr&&fkeIS|Gtp +z4}e2!aCLF)i3SpLrDDYG?z7|_aXsy%WL`Es#}o>abhqE;ek3tx$Aa*r7$&WxUBaG2 +z3WU#Dz`jpCIGgBZwbuTVgdxM*q^*<@hOdbB{}X=;fb?2Km`o>J*j(>>&ja92ReiI$ +z{v7by!}eOmbeQ`fIr>FK|9e&aZYY7nuj-n8Paq)`E+5}Wg`j=Y?dT>&--t9fv|R|h +zo9>^-%H9VP*=cj3TGR1j#P~+SSX(365s%cPT%NpIWj$Pxl!)3-RH&jlmFf+GG&>Q& +zles>;tIBr?`e#MyfpB4K14T<8zX3R@sy{>b3AG9E{gqT-EEPB`x>zcfrPl+`RP+vC +zZy-xlefTeC_o-&3zKj#~wP-a!!YOYQIhY|R87jMOg>M} +zd)4Ld;%#5j`fUFt=tn$0o7djyR2|a@7(Q2X4}TE%EMArbVQqVZy~(&&wW?KrRMD?8 +zCEq9_zjtwEhog((#fs@1@ZG>4D0*!S4g;9a&#XymPEN0-QmZfAe~oI>F;%#l$6hM}W|yGOtVFT4ODs7GDqEA(2D-6GIO^s)d6PrB*(tbk +z{hYm7;XQU%ELBy-#?BU-JLSXQ1W@JcK;LAde-ZTU18mDfp`(x>0Dr9Ls}z3K*c@#u +z&EJ_%XQ~QUOmB8yTI!!bL3tbKWtN%k3MfhTCRCCj?k6Z2x_ODzC?9UhN0P%ziBMWJ +z^^|}RNsK<%Zg8DmwByoNni{`(*-I;s-EIReHEnZUX)jV0O1=@32tj; +zfDjj#ARONKKzc}%flCtf%jan&OzLp&&mJ~ium@h3Ct-MkQXRdvXp&QqS`Dul}&kWky +z-CP>Xu_`_LsUrag8uMGD_o%1~2tRsC2h +zk+Muv-T`u_3wD1!PN>OKlOZU6!JQwoO} +zPZ@KnzLBe^Pe4f@Ol-jLcMx9bBRsnY5XtaPLRobxX2y~lWq&ggp-X7515mVJvQol? +zO+V7#bYzkV#lb{=i1=B%N8x3_NBX7pB`Lm30K5rzUco1Tzd_-noyUQW +zBS0Wy{MAf2r8n^S$(;xlg~PP}I`EI$t2{sSlSDVv0;9PO!=_Bc#I`OcB|^2R16y8= +z>iUy{uWcn)hPGNe0OBaHdmPeUb#Hyk2Z2|B-aB*J5LT-dR-+f6RFzs4rS^LrKY;R+ +zxQ`)yCj%ZxJxV&R012pO!sYe#Jbvd<48f97 +zJu;#tRthXwa^X;wYT}}mJttX$XRjp4fmf@d-UelIW6F;pKXx@C-;}yj3SZ5@Z_$hC +zXU>sh;{GP^^T7833q67TFzHwWM42*Tm769{WyA^U{DN~O@B!edxx}1K9wmnPVoB2c +zO;+tFY*iZRN+h7MDXyp_z3fym)4l{(;csi)+q~&`;#u(5+7AQd*23`pK(U1big^n#il$wfF9zVX5%j@e);8+EI8F>ESiu)u+0WhIT6lD#VIcC_L +zR0w~YDkAmEw2^?tv?XzWG7={pZbIVrAl}%xT?bOu_|DNwabFJpI$&WRwz*hzYyl!v +zJZ^jkSJXFBGcINO7dZd^W(Ugu3sx*#IjjV{fcFUl}L#!D*R2y +z7{&cE@DG^l14V=B>9|LRUQf@i`*Eh@@Tf^bZZq&YPSua;0|&V8hRi&6vSYO}IO0^R +z__Qm0q`nxOG`}Gj;@?i&ie-XP!%TcvZ&ZKMc1eB|2J8NR9OP?p>d#!@80h{G+@Tx) +zmP-^Ia7+OLPJ#@ecLHCDJ0~e$k71xvddFT8m5Bh62`BbIMj`4XgONm$dSr8leU6o= +z2sMMLZRIY3?**O<{QjJk%tH!nA7cF%g^n#i=6JZ}lfVmb-jUDyNVjtPP@XIh!nm#u +zAIgQZn{){P!uC@G+oWW=8cV4dSZQB#Bmkcm_&Wl30Po=vaIqc-I>rE*izYbN;WGr@ +zAaEBFGJZ^X=8ZyD?TNzH7D#KzqO8!Kb?5dNN8hDL3d*Em2d5vI6DLqmE +z;%N=|Cx|>9_*=jSAvI!hf~B(!a?l})%gYv%d28-r-)-V(8HT5KmLw>5iWQ-VR)c)61U&@?0EvZUZj!1xiMGKsi%n +zKh(b6JF~V2aZka15a)&ZBuh{n8a0KQ{jXRt0VWZbx{sIMwV)2)6)_1+GLm +z5u4MYd`Mx`$L>A$JGi}rbAo&h_%qzM8b6K$`1zTmThc=4(F~B7#<=fn-%WTr;EKRC +zxCbF`0v?0#c--gPZUn9cuEsqRcBKd>K(4~gt>R85UnM+kX9ov>4V>|O9(V{ijc^Ze +zHzN1o&Z9lgCA`sgsnZf5vuOf6-2C?+6s>To*kvGB0#}J}3I~!C&F>11v9E6Osxjox +zH}!7f0CJ(J|3VWt=oIcH9X`onoOiXPB|TE;k+u)Aq$MqsmH=7Ol6q(fkR>gthn4_Y +z(vo^;36Lc%sfU&TS<;evXbF%dEvbi=09n$KdT0rdB`v9kmH=7Ol6vU>2aPAsPCpqk +Qng9R*07*qoM6N<$g0t|Fy8r+H + +literal 8324 +zcma)CWl&sAu)T{c4!b~b!Xm+46P&Pk(BKXmEVw5SED%`S0>P6I65QQggS)!~celq^ +z_1^#YV{TXV?VjqMxwmKLoC#G^k;B8Lzy<&SPeC58@g#fxYnb4tXQ6IU#*@HulGk$u +z0Mw2D8mK`@;_69B?k1z__SVtT&C|@q0`T7*W32VHtpOsLDw{jRK+%dU4Hf8PDP(tEaY +zVb;TO?zg>+y0e^=)H~9ck{1xzJJsKD<2QMWE<<4w$ku+?Nz~ +z?sw*04{Ntj2t(m?vGNT6Z&4?~J_DA=4@RZ|Hy|?L2baGw-~xOA-T`VLCt&4+Es7dJ +z3rqB1K#)Ht +zM;a6WNe+K~@E)jy^0nkG4{!%88+0X^_i_yf#-MD!UOnz)0W6pOg`AvCsp#J@n!d~L +zCVJ83uVFsD4tN05H1Ti{d&m(pugW$|17?Hwda!DnL8l=`_8ey*(%(4BM7^w__ +z29jw+qAw%K`BPELftPW%&SF96Iq +z_h)d~d@n?_dd(h4B}06FF_)p)nqY@o2W0}0k!fDPNE=n60)9Z1ad$Q2*UaJYIWokv +z-YS-7Pdx#2eP~Ya<+J1YRpR69RWsr44_urWbIB`C{fwD97K&lSNUb+huWn><5yoYB +zJfUnktJt254fv(LN1LG_v8d+K$*{JMVsT|C=wGYwMq)%b#mJ%{U3S +z3eOditQ%g>1&0d*gJeo>(pn)%r<8<&V=*Y6MZ|vjseW!0G4f*AyoOjh^n**XNNygpr52-!$+5s79~Rz!atG0AJ~ +zaLfL^_!UEf*!wv|>{tUMEVChL@bJ7VVyP{&`32M_;g)srdhGDfd*c_n>)Eu<6%~5 +zXz4zr{*Ya1{haF#(VA;Dlz!_!w!vA}mSI?pFpKT}D5t6tuIgcFQ^&`ihd_avR-x

@y(HdF(KVXFH}bp|wUaw6&QXCUa*zVm->M@=&FCKVp97YM|kve_3*VCW46 +zv!#8UFWTMyY4J+6m;I<#=$7m +zvIxO0NZyc8eys_L$J5|l<8aShl<6-W9Ux5Aw;1X-A*d|~znVkzbk~W9NS>&l06W&r +z81yNRW4XxCw4Q;`80-AJ0^JHD+(Ld}1M>T0KVc9A%jak_H8K+KT&aIL$9Yj{OwBsL +zi2A95!ZqP=dZaZjR5`2~3(lW{1Vhz*b*AYMF=(OA6b`(1Ehoh!e(1-&%>?^8@^6A5 +z{;YtsV$bNqlh-7LCkxfTnr1`I0`dcMIZD$kxbZku8$`3YrKX5Uk(spqYh +zz_N=sHsL;;DZ@TN>NwJZ2}p`Ul{vd;|ID)}R50=*NyUdB^$XQk88m|MZmkHOfep#< +zzpW_boa0-TB|CQC=plYSmJNqQ$Q=9@3P7a4zeOQ{L0(gfdR_i*D4RJ}5#WFvhZr#f +zpXZ0^);*ZmA%T458)_hcfwjJ0md)%R6*(R)!cKk-p_wl0EUYhkMtkW6apETFb28WQ +z4Mr#(QduSc1>s5h0i;rz#fJT4`6?ZjPm_lwr{!mvh!p@w7-I%Z_x=86oCm?^|4<)8 +z=$={{fGneBRf<}8)D3UL@M`bMg{F5AwQ4@5G3#t45l==axYJ4x9G47q)($$J@=@VI +z-Y!i+)Uo`F$q=Q3XBA3T_D`PpsL>6Mx4o-;&M{QBLJK6f;^0Rs9W?w@U_H8UL4 +zC<<6>UoFr6a8`MftsZLN7PJe>FpW^b?mA=9bI_jUn!2_yOZ)|xt7s4cHEZ;mY&G&={=sV`v1dU>v(H>0l%EsXcuV*0XE_*?nG +zwAp1c&4Q4%zq04fe%pX0p*k30Hxp~jLW>&P`{whYJ +zzJkFrrGP>Fd{IB8M&J0sk-7EX_Al~AhU4m{BiC-N8e+EFzQE6fx~9#Xf4W +zTRkXFzM{UunB;+Os7PyK|1qdU?R#%myF?+&G(?q&(NroYmBe0wlhR*;mu+A9q3JlL +zCpSCOmC%GJA@7BvKd`Y=s>FS}ixpv(yR$(^u#@RKn_nK} +z>R!=gxS9R?c(a{+!Il+}5&fj$ubAFFpQ}FY8!o@1KFW +zgd#)3#sg)MA-L41dVrsku5bKRmnOzp`GB^EO}3v{9=z{$K;nKL;e}0IQO*28T3TAe +zLoIq^SG`zr6}x1jkj)m}_Qt#{T!{>kA|@qV2g6Y{C;imh<|m$IL$T6>&JZ=XF~(#I +ze$g&Ik%OmSei6-t%`oS8 +z!RzV810Fzdj(4EGfU`l(E9NZg=liA9sdUi;C{pZ1WO&eu8fsKqA$nu2S-r{6F&Nnr +z6}kJoajWZ8Vv;TvpNZyjo3F+F@bu7F++{E8X(N`1D^$Kv@M#m-Ur&ZOoGnwcCJRP1 +zlg4uR==108HF-X4sCF*Na?O&4)YJB7GgIJIWOn3c!WF+a9qN2ra6aFYNrz$p{DPA^ +z)%WY;exJ@RoBMSTBR<;GMA|k%Ty3fhyyaGBm}r5mxQXdja#Mt<+-?hxgXPipb$NES +zxNY84ES)}*GUXnb$wpzf>U2Lj2_O1|TnOPxe5y_)HG19%K +zX8AWbA=>wR(RNYW=oYXGnFc#$)pdBy4>m%aN24jHjQv(GH$(&rK2D#NsQwC24&&)3 +zAuxBs-+rw@L#I()e1C9B(BJH)a7Rm>xjYZe#c~>J&zJ9cyblyII+M9GK$S$tCtg3m +zE!8fjMr(0i8rt-|tA3Us(c9O{=ek<*tL)2nyKoGiw>a8WMK*P2SIzfMt%aAyJcnaf +zbFz?U&!hE&duRl@QUCy1%oxkXPamf +z6-b#Z< +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 +ziumNvw(uoEt?aYT +z^=6lWI(cfI3ocV8i}suxydCuBrc6}0vmoX^RlL-jY?|e%%K#@`zRcD_w9?gY@;Dti +zQ;7WgCz9e>^G}WdWEfz0wRq7}(g^a&BBwOV5g0IOgn1Gx3P+NhdJ84%{oI6KZ6zM1 +z<@smeE%VaxHhObCA2ZB#Sr;!AbPCYB9WU|YTP1JH{Y)(H^+TqL%fQlO%2@aJ{4R-r +zQLf7e!0fCuL1;11?e0+d;9wH6LBdIP@nZHW1kbBoQo&0tb%|brxN5jU#;hhe}L^ +z8{yrF((CTOab2hx#9%q^;kJ2tdpjbZnq~&Ib#nPQz3ORi&y{W(48CqN2i4425serF +zT0jc0XW~8tQp1c@7o{@4<#^fRaGhmyLAueWS7K_#N^q;g_B-DIrt$AB*s2UK#x3d1 +zrrRxVw8)wwx8+T+9rDQ6(J}H(k9&Dt=)LFwuy7>iS@q9WREzNN{k)7~E(e^)&j&mNH)~|l=aEqnT}X9JnpM;f +zC?Fp>HMZ&od}VsTSL8-0@C>%y2?1p850Y`EwNc&^cQQCh;39YXD8?|x_D>NAf +zR>Uqk{l2<96$2)9pfPeMj{EO^{i48!J1YO$czewd*y{V4lY08Y#af;R`DgITuCM=< +ztdai+%WaWFFKX281E;fB7ltTQ3YYkD@8O0E^_zZlT*l`zcbAx;oYIv;1o_kFs)R}R +z+}TFrlV)$2+`}^SbAeQ{QwAeUdjYy4oq|TLllcvr?tLL(FVat0@97^T{Y;iZ3^MiV +z&7SDtG~B1+_hls84daz~0{ufG)Bhf7;D5lEByLuj`8nbHWKM}kS6d7K5oL}I!FlZN +z`02c%X&FrlmlQw^$wHyu>G(kD<-zQD-+?ePsOPJk%BcrI7>FvzCUv1Z*?CN&*s8O8 +z@oUF&db`Q3@mZw7L&Q#Gq1YD!I&M{*ER5~vL2D+iAV5DTVxrjoM}L|{!Bx$Olh=)B +zu0Wnfmr%p0?fC}Vl1xd_IXFiam@s-DuJGh#ObjB6kY3d3o)}8sqxyI=6dNltGMT?S +zBBoh>u62K&DlVIKJiJ^Fl2n{%*um6*EkuhVS;Imi@zcIZ2t-CEIn%n_45A<=)7(`$ +zpg09emChaZ44Y8%OIGmoMF62&F?Gb#;1;%z{V;cluC1sU!a}woOM9%MUS7(kcH2=(5?M +zxX6|{0vM8?MzJ!47}i@^TZx21biBA`K +gx-fwL-(3LIPg|59oc((uo)mzBj0(Kywdv>o0sO6>y#N3J + diff --git a/leaf-server/paper-patches/features/0002-Leaf-Bootstrap.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0002-Leaf-Bootstrap.patch similarity index 100% rename from leaf-server/paper-patches/features/0002-Leaf-Bootstrap.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0002-Leaf-Bootstrap.patch diff --git a/leaf-server/paper-patches/features/0003-Leaf-Commands.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0003-Leaf-Commands.patch similarity index 100% rename from leaf-server/paper-patches/features/0003-Leaf-Commands.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0003-Leaf-Commands.patch diff --git a/leaf-server/paper-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch similarity index 100% rename from leaf-server/paper-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0004-Pufferfish-Optimize-mob-spawning.patch diff --git a/leaf-server/paper-patches/features/0005-Purpur-Server-Paper-Changes.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0005-Purpur-Server-Paper-Changes.patch similarity index 100% rename from leaf-server/paper-patches/features/0005-Purpur-Server-Paper-Changes.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0005-Purpur-Server-Paper-Changes.patch diff --git a/leaf-server/paper-patches/features/0006-Fix-Pufferfish-and-Purpur-patches.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0006-Fix-Pufferfish-and-Purpur-patches.patch similarity index 100% rename from leaf-server/paper-patches/features/0006-Fix-Pufferfish-and-Purpur-patches.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0006-Fix-Pufferfish-and-Purpur-patches.patch diff --git a/leaf-server/paper-patches/features/0007-Remove-Timings.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0007-Remove-Timings.patch similarity index 100% rename from leaf-server/paper-patches/features/0007-Remove-Timings.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0007-Remove-Timings.patch diff --git a/leaf-server/paper-patches/features/0008-KeYi-Player-Skull-API.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0008-KeYi-Player-Skull-API.patch similarity index 100% rename from leaf-server/paper-patches/features/0008-KeYi-Player-Skull-API.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0008-KeYi-Player-Skull-API.patch diff --git a/leaf-server/paper-patches/features/0009-Slice-Smooth-Teleports.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0009-Slice-Smooth-Teleports.patch similarity index 100% rename from leaf-server/paper-patches/features/0009-Slice-Smooth-Teleports.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0009-Slice-Smooth-Teleports.patch diff --git a/leaf-server/paper-patches/features/0010-Leaves-Protocol-Core.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0010-Leaves-Protocol-Core.patch similarity index 100% rename from leaf-server/paper-patches/features/0010-Leaves-Protocol-Core.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0010-Leaves-Protocol-Core.patch diff --git a/leaf-server/paper-patches/features/0011-Leaves-Replay-Mod-API.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0011-Leaves-Replay-Mod-API.patch similarity index 100% rename from leaf-server/paper-patches/features/0011-Leaves-Replay-Mod-API.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0011-Leaves-Replay-Mod-API.patch diff --git a/leaf-server/paper-patches/features/0012-Skip-event-if-no-listeners.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0012-Skip-event-if-no-listeners.patch similarity index 100% rename from leaf-server/paper-patches/features/0012-Skip-event-if-no-listeners.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0012-Skip-event-if-no-listeners.patch diff --git a/leaf-server/paper-patches/features/0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch similarity index 100% rename from leaf-server/paper-patches/features/0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch diff --git a/leaf-server/paper-patches/features/0014-SparklyPaper-Optimize-canSee-checks.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0014-SparklyPaper-Optimize-canSee-checks.patch similarity index 100% rename from leaf-server/paper-patches/features/0014-SparklyPaper-Optimize-canSee-checks.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0014-SparklyPaper-Optimize-canSee-checks.patch diff --git a/leaf-server/paper-patches/features/0015-Including-5s-in-getTPS.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0015-Including-5s-in-getTPS.patch similarity index 100% rename from leaf-server/paper-patches/features/0015-Including-5s-in-getTPS.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0015-Including-5s-in-getTPS.patch diff --git a/leaf-server/paper-patches/features/0016-Don-t-throw-exception-on-missing-ResourceKey-value.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0016-Don-t-throw-exception-on-missing-ResourceKey-value.patch similarity index 100% rename from leaf-server/paper-patches/features/0016-Don-t-throw-exception-on-missing-ResourceKey-value.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0016-Don-t-throw-exception-on-missing-ResourceKey-value.patch diff --git a/leaf-server/paper-patches/features/0017-Virtual-Thread-for-async-scheduler.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0017-Virtual-Thread-for-async-scheduler.patch similarity index 100% rename from leaf-server/paper-patches/features/0017-Virtual-Thread-for-async-scheduler.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0017-Virtual-Thread-for-async-scheduler.patch diff --git a/leaf-server/paper-patches/features/0018-Mirai-Configurable-chat-message-signatures.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0018-Mirai-Configurable-chat-message-signatures.patch similarity index 100% rename from leaf-server/paper-patches/features/0018-Mirai-Configurable-chat-message-signatures.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0018-Mirai-Configurable-chat-message-signatures.patch diff --git a/leaf-server/paper-patches/features/0019-Matter-Secure-Seed.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0019-Matter-Secure-Seed.patch similarity index 100% rename from leaf-server/paper-patches/features/0019-Matter-Secure-Seed.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0019-Matter-Secure-Seed.patch diff --git a/leaf-server/paper-patches/features/0020-Faster-random-generator.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0020-Faster-random-generator.patch similarity index 100% rename from leaf-server/paper-patches/features/0020-Faster-random-generator.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0020-Faster-random-generator.patch diff --git a/leaf-server/paper-patches/features/0021-Configurable-unknown-command-message.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0021-Configurable-unknown-command-message.patch similarity index 100% rename from leaf-server/paper-patches/features/0021-Configurable-unknown-command-message.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0021-Configurable-unknown-command-message.patch diff --git a/leaf-server/paper-patches/features/0022-Replace-world-map-with-optimized-collection.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0022-Replace-world-map-with-optimized-collection.patch similarity index 100% rename from leaf-server/paper-patches/features/0022-Replace-world-map-with-optimized-collection.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0022-Replace-world-map-with-optimized-collection.patch diff --git a/leaf-server/paper-patches/features/0023-Cache-CraftEntityType-minecraftToBukkit-convert.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0023-Cache-CraftEntityType-minecraftToBukkit-convert.patch similarity index 100% rename from leaf-server/paper-patches/features/0023-Cache-CraftEntityType-minecraftToBukkit-convert.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0023-Cache-CraftEntityType-minecraftToBukkit-convert.patch diff --git a/leaf-server/paper-patches/features/0024-Multithreaded-Tracker.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0024-Multithreaded-Tracker.patch similarity index 100% rename from leaf-server/paper-patches/features/0024-Multithreaded-Tracker.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0024-Multithreaded-Tracker.patch diff --git a/leaf-server/paper-patches/features/0025-Asynchronous-locator.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0025-Asynchronous-locator.patch similarity index 100% rename from leaf-server/paper-patches/features/0025-Asynchronous-locator.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0025-Asynchronous-locator.patch diff --git a/leaf-server/paper-patches/features/0026-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0026-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch similarity index 100% rename from leaf-server/paper-patches/features/0026-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0026-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch diff --git a/leaf-server/paper-patches/features/0027-Faster-CraftServer-getworlds-list-creation.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0027-Faster-CraftServer-getworlds-list-creation.patch similarity index 100% rename from leaf-server/paper-patches/features/0027-Faster-CraftServer-getworlds-list-creation.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0027-Faster-CraftServer-getworlds-list-creation.patch diff --git a/leaf-server/paper-patches/features/0028-Cache-chunk-key.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0028-Cache-chunk-key.patch similarity index 100% rename from leaf-server/paper-patches/features/0028-Cache-chunk-key.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0028-Cache-chunk-key.patch diff --git a/leaf-server/paper-patches/features/0029-Async-structure-locate-api.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0029-Async-structure-locate-api.patch similarity index 100% rename from leaf-server/paper-patches/features/0029-Async-structure-locate-api.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0029-Async-structure-locate-api.patch diff --git a/leaf-server/paper-patches/features/0030-PlayerInventoryOverflowEvent.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0030-PlayerInventoryOverflowEvent.patch similarity index 100% rename from leaf-server/paper-patches/features/0030-PlayerInventoryOverflowEvent.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0030-PlayerInventoryOverflowEvent.patch diff --git a/leaf-server/paper-patches/features/0031-SparklyPaper-Parallel-world-ticking.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0031-SparklyPaper-Parallel-world-ticking.patch similarity index 100% rename from leaf-server/paper-patches/features/0031-SparklyPaper-Parallel-world-ticking.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0031-SparklyPaper-Parallel-world-ticking.patch diff --git a/leaf-server/paper-patches/features/0032-Paper-PR-Throttle-failed-spawn-attempts.patch b/leaf-archived-patches/unapplied/server/paper-patches/features/0032-Paper-PR-Throttle-failed-spawn-attempts.patch similarity index 100% rename from leaf-server/paper-patches/features/0032-Paper-PR-Throttle-failed-spawn-attempts.patch rename to leaf-archived-patches/unapplied/server/paper-patches/features/0032-Paper-PR-Throttle-failed-spawn-attempts.patch diff --git a/leaf-server/build.gradle.kts.patch b/leaf-server/build.gradle.kts.patch index ed73aa0a..660b8d20 100644 --- a/leaf-server/build.gradle.kts.patch +++ b/leaf-server/build.gradle.kts.patch @@ -1,6 +1,6 @@ --- a/paper-server/build.gradle.kts +++ b/paper-server/build.gradle.kts -@@ -9,10 +_,11 @@ +@@ -13,10 +_,11 @@ } val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/" @@ -13,7 +13,7 @@ testRuntimeOnly("org.junit.platform:junit-platform-launcher") } -@@ -24,6 +_,19 @@ +@@ -28,6 +_,19 @@ // oldPaperCommit = "f4f275519f7c1fbe9db173b7144a4fe81440e365" //} @@ -32,8 +32,8 @@ + spigot { buildDataRef = "702e1a0a5072b2c4082371d5228cb30525687efc" - packageVersion = "v1_21_R3" // also needs to be updated in MappingEnvironment -@@ -46,6 +_,7 @@ + packageVersion = "v1_21_R4" // also needs to be updated in MappingEnvironment +@@ -50,6 +_,7 @@ libraryRepositories.addAll( "https://repo.maven.apache.org/maven2/", paperMavenPublicUrl, @@ -41,7 +41,7 @@ ) } -@@ -104,7 +_,22 @@ +@@ -108,7 +_,22 @@ } } @@ -65,7 +65,7 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { extendsFrom(configurations.compileClasspath.get()) } -@@ -122,10 +_,20 @@ +@@ -130,10 +_,20 @@ } dependencies { @@ -88,8 +88,8 @@ + implementation("org.jline:jline-terminal-jni:3.29.0") // fall back to jni on java 21 // Leaf - Bump Dependencies implementation("net.minecrell:terminalconsoleappender:1.3.0") implementation("net.kyori:adventure-text-serializer-ansi:4.18.0") // Keep in sync with adventureVersion from Paper-API build file - -@@ -135,36 +_,55 @@ + runtimeConfiguration(sourceSets.main.map { it.runtimeClasspath }) +@@ -144,36 +_,53 @@ all its classes to check if they are plugins. Scanning takes about 1-2 seconds so adding this speeds up the server start. */ @@ -154,9 +154,7 @@ + testImplementation("org.junit.platform:junit-platform-suite-engine:1.12.1") + testImplementation("org.hamcrest:hamcrest:3.0") + testImplementation("org.mockito:mockito-core:5.16.1") -+ mockitoAgent("org.mockito:mockito-core:5.16.1") { -+ isTransitive = false -+ } // Configure mockito agent that is needed in newer java versions ++ mockitoAgent("org.mockito:mockito-core:5.16.1") { isTransitive = false } // Configure mockito agent that is needed in newer java versions testImplementation("org.ow2.asm:asm-tree:9.7.1") - testImplementation("org.junit-pioneer:junit-pioneer:2.2.0") // CartesianTest + testImplementation("org.junit-pioneer:junit-pioneer:2.3.0") // CartesianTest @@ -164,7 +162,7 @@ implementation("net.neoforged:srgutils:1.0.9") // Mappings handling implementation("net.neoforged:AutoRenamingTool:2.0.3") // Remap plugins -@@ -178,28 +_,40 @@ +@@ -187,28 +_,40 @@ // Spark implementation("me.lucko:spark-api:0.1-20240720.200737-2") implementation("me.lucko:spark-paper:1.10.119-20241121.092015-1") @@ -207,12 +205,21 @@ - "Brand-Id" to "papermc:paper", - "Brand-Name" to "Paper", + "Specification-Vendor" to "Winds Studio", // Leaf - Rebrand -+ "Brand-Id" to "winds-studio:Leaf", // Leaf - Rebrand ++ "Brand-Id" to "winds-studio:leaf", // Leaf - Rebrand + "Brand-Name" to "Leaf", // Leaf - Rebrand "Build-Number" to (build ?: ""), "Build-Time" to buildTime.toString(), "Git-Branch" to gitBranch, -@@ -285,6 +_,8 @@ +@@ -262,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() // Leaf - project setup + idea { + module { + generatedSourceDirs.add(generatedDir.toFile()) +@@ -320,6 +_,8 @@ val memoryGb = providers.gradleProperty("paper.runMemoryGb").getOrElse("2") minHeapSize = "${memoryGb}G" maxHeapSize = "${memoryGb}G" @@ -221,7 +228,7 @@ doFirst { workingDir.mkdirs() -@@ -330,3 +_,62 @@ +@@ -365,3 +_,62 @@ classpath(tasks.createReobfPaperclipJar.flatMap { it.outputZip }) mainClass.set(null as String?) } diff --git a/leaf-server/minecraft-patches/features/0001-Rebrand.patch b/leaf-server/minecraft-patches/features/0001-Rebrand.patch index 4ec276e9..13d4b901 100644 --- a/leaf-server/minecraft-patches/features/0001-Rebrand.patch +++ b/leaf-server/minecraft-patches/features/0001-Rebrand.patch @@ -5,14 +5,14 @@ Subject: [PATCH] Rebrand diff --git a/net/minecraft/CrashReport.java b/net/minecraft/CrashReport.java -index 3e0e88afcf010d9a3d46e48bca5cbdf98fe97544..5a9173b6039ee8404529a04904c5f9e9343d74d8 100644 +index 3e0e88afcf010d9a3d46e48bca5cbdf98fe97544..18e63dca2a315ad01fa5b80ec126f4eac71f45fd 100644 --- a/net/minecraft/CrashReport.java +++ b/net/minecraft/CrashReport.java @@ -30,6 +30,7 @@ public class CrashReport { private boolean trackingStackTrace = true; private StackTraceElement[] uncategorizedStackTrace = new StackTraceElement[0]; private final SystemReport systemReport = new SystemReport(); -+ private List extraInfo = List.of("", "DO NOT REPORT THIS TO PAPER OR GALE! REPORT TO LEAF INSTEAD!", ""); // Leaf - Rebrand ++ private List extraInfo = List.of("", "DO NOT REPORT THIS TO PAPER! REPORT TO LEAF INSTEAD!", ""); // Leaf - Rebrand public CrashReport(String title, Throwable exception) { io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception); // Paper @@ -35,28 +35,28 @@ index 3e0e88afcf010d9a3d46e48bca5cbdf98fe97544..5a9173b6039ee8404529a04904c5f9e9 public SystemReport getSystemReport() { diff --git a/net/minecraft/world/damagesource/DamageSource.java b/net/minecraft/world/damagesource/DamageSource.java -index fb5e47278a62f3896a2a1ed144bad45ba3de080a..0d9e5aab214df54a7a24bec45fcc8ad85f699710 100644 +index bb021fc9de91f8c4f79e6a753d57fa157efbbda7..9926848124f0b74ebb615fbbc45d95ebce64233f 100644 --- a/net/minecraft/world/damagesource/DamageSource.java +++ b/net/minecraft/world/damagesource/DamageSource.java @@ -49,7 +49,7 @@ public class DamageSource { public DamageSource eventEntityDamager(final Entity entity) { if (this.directEntity != null) { -- throw new IllegalStateException("Cannot set an event damager when a direct entity is already set (report a bug to Paper, if you think this is a Gale bug, please report it at https://github.com/GaleMC/Gale/issues)"); // Gale - branding changes -+ throw new IllegalStateException("Cannot set an event damager when a direct entity is already set (report a bug to Paper, if you think this is a Leaf bug, please report it at https://github.com/Winds-Studio/Leaf/issues)"); // Gale - branding changes // Leaf - Rebrand +- throw new IllegalStateException("Cannot set an event damager when a direct entity is already set (report a bug to Paper)"); ++ throw new IllegalStateException("Cannot set an event damager when a direct entity is already set (if you think this is a Leaf bug, please report it at https://github.com/Winds-Studio/Leaf/issues)"); // Leaf - Rebrand } final DamageSource damageSource = this.copy(); damageSource.eventEntityDamager = entity; diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 3abb8aefcca325e28f0af07bd859be74f0aee08d..320e9e24711d2a326313b3a202c7ef987f71f229 100644 +index 763879cdc389fc4d80135b38aa96a5bec448ae9e..c7cec4a8a32e0c978a198904dbaf9920649ec879 100644 --- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -288,7 +288,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise - We do not want people to report thread issues to Paper, - but we do want people to report thread issues to Gale. - */ -- org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER OR GALE - You may ask for help on Discord, but do not file an issue. These error messages can not be removed. - If you think this is a Gale bug, please report it at https://github.com/GaleMC/Gale/issues)"); +@@ -49,7 +49,7 @@ public final class RegionFileStorage implements AutoCloseable { + + // Paper start + private static void printOversizedLog(String msg, Path file, int x, int z) { +- org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); + org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER OR LEAF - You may ask for help on Discord, but do not file an issue. These error messages can not be removed. - If you think this is a Leaf bug, please report it at https://github.com/Winds-Studio/Leaf/issues)"); // Leaf - Rebrand - // Gale end - branding changes } + private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { diff --git a/leaf-server/paper-patches/features/0001-Rebrand.patch b/leaf-server/paper-patches/features/0001-Rebrand.patch index 9a49e32a..6ecaf4af 100644 --- a/leaf-server/paper-patches/features/0001-Rebrand.patch +++ b/leaf-server/paper-patches/features/0001-Rebrand.patch @@ -3,84 +3,410 @@ From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Date: Thu, 16 Sep 2021 20:39:45 -0400 Subject: [PATCH] Rebrand +This patch is referring to the following patch: +"Gale branding changes" +By: Martijn Muijsers +As part of: GaleMC (https://github.com/GaleMC/Gale) +Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 3d8ed4ff9a5a30d123508aeb485250271b528a6e..49ac2b52fc134bfa77a108bf58de3e81be38c683 100644 ---- a/src/main/java/com/destroystokyo/paper/Metrics.java -+++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -592,7 +592,7 @@ public class Metrics { - boolean logFailedRequests = config.getBoolean("logFailedRequests", false); - // Only start Metrics, if it's enabled in the config - if (config.getBoolean("enabled", true)) { -- Metrics metrics = new Metrics("Gale", serverUUID, logFailedRequests, Bukkit.getLogger()); // Gale - branding changes - metrics -+ Metrics metrics = new Metrics("Leaf", serverUUID, logFailedRequests, Bukkit.getLogger()); // Gale - branding changes - metrics // Leaf - Rebrand +diff --git a/LGPL.txt b/LGPL.txt +deleted file mode 100644 +index 65c5ca88a67c30becee01c5a8816d964b03862f9..0000000000000000000000000000000000000000 +--- a/LGPL.txt ++++ /dev/null +@@ -1,165 +0,0 @@ +- GNU LESSER GENERAL PUBLIC LICENSE +- Version 3, 29 June 2007 +- +- Copyright (C) 2007 Free Software Foundation, Inc. +- Everyone is permitted to copy and distribute verbatim copies +- of this license document, but changing it is not allowed. +- +- +- This version of the GNU Lesser General Public License incorporates +-the terms and conditions of version 3 of the GNU General Public +-License, supplemented by the additional permissions listed below. +- +- 0. Additional Definitions. +- +- As used herein, "this License" refers to version 3 of the GNU Lesser +-General Public License, and the "GNU GPL" refers to version 3 of the GNU +-General Public License. +- +- "The Library" refers to a covered work governed by this License, +-other than an Application or a Combined Work as defined below. +- +- An "Application" is any work that makes use of an interface provided +-by the Library, but which is not otherwise based on the Library. +-Defining a subclass of a class defined by the Library is deemed a mode +-of using an interface provided by the Library. +- +- A "Combined Work" is a work produced by combining or linking an +-Application with the Library. The particular version of the Library +-with which the Combined Work was made is also called the "Linked +-Version". +- +- The "Minimal Corresponding Source" for a Combined Work means the +-Corresponding Source for the Combined Work, excluding any source code +-for portions of the Combined Work that, considered in isolation, are +-based on the Application, and not on the Linked Version. +- +- The "Corresponding Application Code" for a Combined Work means the +-object code and/or source code for the Application, including any data +-and utility programs needed for reproducing the Combined Work from the +-Application, but excluding the System Libraries of the Combined Work. +- +- 1. Exception to Section 3 of the GNU GPL. +- +- You may convey a covered work under sections 3 and 4 of this License +-without being bound by section 3 of the GNU GPL. +- +- 2. Conveying Modified Versions. +- +- If you modify a copy of the Library, and, in your modifications, a +-facility refers to a function or data to be supplied by an Application +-that uses the facility (other than as an argument passed when the +-facility is invoked), then you may convey a copy of the modified +-version: +- +- a) under this License, provided that you make a good faith effort to +- ensure that, in the event an Application does not supply the +- function or data, the facility still operates, and performs +- whatever part of its purpose remains meaningful, or +- +- b) under the GNU GPL, with none of the additional permissions of +- this License applicable to that copy. +- +- 3. Object Code Incorporating Material from Library Header Files. +- +- The object code form of an Application may incorporate material from +-a header file that is part of the Library. You may convey such object +-code under terms of your choice, provided that, if the incorporated +-material is not limited to numerical parameters, data structure +-layouts and accessors, or small macros, inline functions and templates +-(ten or fewer lines in length), you do both of the following: +- +- a) Give prominent notice with each copy of the object code that the +- Library is used in it and that the Library and its use are +- covered by this License. +- +- b) Accompany the object code with a copy of the GNU GPL and this license +- document. +- +- 4. Combined Works. +- +- You may convey a Combined Work under terms of your choice that, +-taken together, effectively do not restrict modification of the +-portions of the Library contained in the Combined Work and reverse +-engineering for debugging such modifications, if you also do each of +-the following: +- +- a) Give prominent notice with each copy of the Combined Work that +- the Library is used in it and that the Library and its use are +- covered by this License. +- +- b) Accompany the Combined Work with a copy of the GNU GPL and this license +- document. +- +- c) For a Combined Work that displays copyright notices during +- execution, include the copyright notice for the Library among +- these notices, as well as a reference directing the user to the +- copies of the GNU GPL and this license document. +- +- d) Do one of the following: +- +- 0) Convey the Minimal Corresponding Source under the terms of this +- License, and the Corresponding Application Code in a form +- suitable for, and under terms that permit, the user to +- recombine or relink the Application with a modified version of +- the Linked Version to produce a modified Combined Work, in the +- manner specified by section 6 of the GNU GPL for conveying +- Corresponding Source. +- +- 1) Use a suitable shared library mechanism for linking with the +- Library. A suitable mechanism is one that (a) uses at run time +- a copy of the Library already present on the user's computer +- system, and (b) will operate properly with a modified version +- of the Library that is interface-compatible with the Linked +- Version. +- +- e) Provide Installation Information, but only if you would otherwise +- be required to provide such information under section 6 of the +- GNU GPL, and only to the extent that such information is +- necessary to install and execute a modified version of the +- Combined Work produced by recombining or relinking the +- Application with a modified version of the Linked Version. (If +- you use option 4d0, the Installation Information must accompany +- the Minimal Corresponding Source and Corresponding Application +- Code. If you use option 4d1, you must provide the Installation +- Information in the manner specified by section 6 of the GNU GPL +- for conveying Corresponding Source.) +- +- 5. Combined Libraries. +- +- You may place library facilities that are a work based on the +-Library side by side in a single library together with other library +-facilities that are not Applications and are not covered by this +-License, and convey such a combined library under terms of your +-choice, if you do both of the following: +- +- a) Accompany the combined library with a copy of the same work based +- on the Library, uncombined with any other library facilities, +- conveyed under the terms of this License. +- +- b) Give prominent notice with the combined library that part of it +- is a work based on the Library, and explaining where to find the +- accompanying uncombined form of the same work. +- +- 6. Revised Versions of the GNU Lesser General Public License. +- +- The Free Software Foundation may publish revised and/or new versions +-of the GNU Lesser General Public License from time to time. Such new +-versions will be similar in spirit to the present version, but may +-differ in detail to address new problems or concerns. +- +- Each version is given a distinguishing version number. If the +-Library as you received it specifies that a certain numbered version +-of the GNU Lesser General Public License "or any later version" +-applies to it, you have the option of following the terms and +-conditions either of that published version or of any later version +-published by the Free Software Foundation. If the Library as you +-received it does not specify a version number of the GNU Lesser +-General Public License, you may choose any version of the GNU Lesser +-General Public License ever published by the Free Software Foundation. +- +- If the Library as you received it specifies that a proxy can decide +-whether future versions of the GNU Lesser General Public License shall +-apply, that proxy's public statement of acceptance of any version is +-permanent authorization for you to choose that version for the +-Library. +diff --git a/LICENCE.txt b/LICENSE.txt +similarity index 99% +rename from LICENCE.txt +rename to LICENSE.txt +index 94a9ed024d3859793618152ea559a168bbcbb5e2..e60008693e017bec1b4eb49c84be3898e26fcf2a 100644 +--- a/LICENCE.txt ++++ b/LICENSE.txt +@@ -1,7 +1,7 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 - metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { - String minecraftVersion = Bukkit.getVersion(); -@@ -602,15 +602,15 @@ public class Metrics { +- Copyright (C) 2007 Free Software Foundation, Inc. ++ Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. - metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); - metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : "offline")); -- final String galeVersion; // Gale - branding changes - metrics -+ final String leafVersion; // Gale - branding changes - metrics // Leaf - Rebrand - final String implVersion = org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion(); - if (implVersion != null) { - final String buildOrHash = implVersion.substring(implVersion.lastIndexOf('-') + 1); -- galeVersion = "git-Gale-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash); // Gale - branding changes - metrics -+ leafVersion = "git-Leaf-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash); // Gale - branding changes - metrics // Leaf - Rebrand - } else { -- galeVersion = "unknown"; // Gale - branding changes - metrics -+ leafVersion = "unknown"; // Gale - branding changes - metrics // Leaf - Rebrand - } -- metrics.addCustomChart(new Metrics.SimplePie("gale_version", () -> galeVersion)); // Gale - branding changes - metrics -+ metrics.addCustomChart(new Metrics.SimplePie("leaf_version", () -> leafVersion)); // Gale - branding changes - metrics // Leaf - Rebrand +@@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found. + GNU General Public License for more details. - metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { - Map> map = new HashMap<>(2); // Gale - metrics - reduce HashMap capacity + You should have received a copy of the GNU General Public License +- along with this program. If not, see . ++ along with this program. If not, see . + + Also add information on how to contact you by electronic and paper mail. + +@@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box". + You should also get your employer (if you work as a programmer) or school, + if any, to sign a "copyright disclaimer" for the program, if necessary. + For more information on this, and how to apply and follow the GNU GPL, see +-. ++. + + The GNU General Public License does not permit incorporating your program + into proprietary programs. If your program is a subroutine library, you + may consider it more useful to permit linking proprietary applications with + the library. If this is what you want to do, use the GNU Lesser General + Public License instead of this License. But first, please read +-. ++. +diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +index bad941054349efe53756d6ab53ba7f6872de8e6f..8f42fba5615c7e1bda4c27334e39a8e3e434db81 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java ++++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +@@ -9,6 +9,7 @@ import com.google.gson.JsonObject; + import com.google.gson.JsonSyntaxException; + import com.mojang.logging.LogUtils; + import io.papermc.paper.ServerBuildInfo; ++ + import java.io.BufferedReader; + import java.io.IOException; + import java.io.InputStreamReader; +@@ -18,6 +19,7 @@ import java.nio.charset.StandardCharsets; + import java.util.Optional; + import java.util.OptionalInt; + import java.util.stream.StreamSupport; ++ + import net.kyori.adventure.text.Component; + import net.kyori.adventure.text.event.ClickEvent; + import net.kyori.adventure.text.format.NamedTextColor; +@@ -30,58 +32,35 @@ import org.slf4j.Logger; + import static net.kyori.adventure.text.Component.text; + import static net.kyori.adventure.text.format.TextColor.color; + ++// Gale start - branding changes - version fetcher ++/** ++ * The original version fetcher for Paper. Most of the original content of this class has been moved to ++ * {@link org.galemc.gale.version.AbstractPaperVersionFetcher}. ++ */ + @DefaultQualifier(NonNull.class) +-public class PaperVersionFetcher implements VersionFetcher { +- private static final Logger LOGGER = LogUtils.getClassLogger(); +- private static final int DISTANCE_ERROR = -1; +- private static final int DISTANCE_UNKNOWN = -2; +- private static final String DOWNLOAD_PAGE = "https://papermc.io/downloads/paper"; ++public class PaperVersionFetcher extends org.galemc.gale.version.AbstractPaperVersionFetcher { + +- @Override +- public long getCacheTime() { +- return 720000; ++ public PaperVersionFetcher() { ++ super( ++ "main", ++ "https://papermc.io/downloads/paper", ++ "PaperMC", ++ "Paper", ++ "PaperMC", ++ "Paper" ++ ); + } + + @Override +- public Component getVersionMessage(final String serverVersion) { +- final Component updateMessage; +- final ServerBuildInfo build = ServerBuildInfo.buildInfo(); +- if (build.buildNumber().isEmpty() && build.gitCommit().isEmpty()) { +- updateMessage = text("You are running a development version without access to version information", color(0xFF5300)); +- } else { +- updateMessage = getUpdateStatusMessage("PaperMC/Paper", build); +- } +- final @Nullable Component history = this.getHistory(); +- +- return history != null ? Component.textOfChildren(updateMessage, Component.newline(), history) : updateMessage; ++ protected boolean canFetchDistanceFromSiteApi() { ++ return true; + } + +- private static Component getUpdateStatusMessage(final String repo, final ServerBuildInfo build) { +- int distance = DISTANCE_ERROR; +- +- final OptionalInt buildNumber = build.buildNumber(); +- if (buildNumber.isPresent()) { +- distance = fetchDistanceFromSiteApi(build, buildNumber.getAsInt()); +- } else { +- final Optional gitBranch = build.gitBranch(); +- final Optional gitCommit = build.gitCommit(); +- if (gitBranch.isPresent() && gitCommit.isPresent()) { +- distance = fetchDistanceFromGitHub(repo, gitBranch.get(), gitCommit.get()); +- } +- } +- +- return switch (distance) { +- case DISTANCE_ERROR -> text("Error obtaining version information", NamedTextColor.YELLOW); +- case 0 -> text("You are running the latest version", NamedTextColor.GREEN); +- case DISTANCE_UNKNOWN -> text("Unknown version", NamedTextColor.YELLOW); +- default -> text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW) +- .append(Component.newline()) +- .append(text("Download the new version at: ") +- .append(text(DOWNLOAD_PAGE, NamedTextColor.GOLD) +- .hoverEvent(text("Click to open", NamedTextColor.WHITE)) +- .clickEvent(ClickEvent.openUrl(DOWNLOAD_PAGE)))); +- }; ++ @Override ++ protected int fetchDistanceFromSiteApi(int jenkinsBuild) { ++ return fetchDistanceFromSiteApi(ServerBuildInfo.buildInfo(), jenkinsBuild); + } ++ // Gale end - branding changes - version fetcher + + private static int fetchDistanceFromSiteApi(final ServerBuildInfo build, final int jenkinsBuild) { + try { +@@ -105,42 +84,4 @@ public class PaperVersionFetcher implements VersionFetcher { + return DISTANCE_ERROR; + } + } +- +- // Contributed by Techcable in GH-65 +- private static int fetchDistanceFromGitHub(final String repo, final String branch, final String hash) { +- try { +- final HttpURLConnection connection = (HttpURLConnection) URI.create("https://api.github.com/repos/%s/compare/%s...%s".formatted(repo, branch, hash)).toURL().openConnection(); +- connection.connect(); +- if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return DISTANCE_UNKNOWN; // Unknown commit +- try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { +- final JsonObject obj = new Gson().fromJson(reader, JsonObject.class); +- final String status = obj.get("status").getAsString(); +- return switch (status) { +- case "identical" -> 0; +- case "behind" -> obj.get("behind_by").getAsInt(); +- default -> DISTANCE_ERROR; +- }; +- } catch (final JsonSyntaxException | NumberFormatException e) { +- LOGGER.error("Error parsing json from GitHub's API", e); +- return DISTANCE_ERROR; +- } +- } catch (final IOException e) { +- LOGGER.error("Error while parsing version", e); +- return DISTANCE_ERROR; +- } +- } +- +- private @Nullable Component getHistory() { +- final VersionHistoryManager.@Nullable VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); +- if (data == null) { +- return null; +- } +- +- final @Nullable String oldVersion = data.getOldVersion(); +- if (oldVersion == null) { +- return null; +- } +- +- return text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); +- } + } diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -index b78828e83d8128eace986aeb73213da3b3f905e4..f59879ae7d3c73cd4c4233d30667988bf22f12f1 100644 +index 6ee39b534b8d992655bc0cef3c299d12cbae0034..f59879ae7d3c73cd4c4233d30667988bf22f12f1 100644 --- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java @@ -20,7 +20,7 @@ public final class PaperConsole extends SimpleTerminalConsole { @Override protected LineReader buildReader(LineReaderBuilder builder) { builder -- .appName("Gale") // Gale - branding changes +- .appName("Paper") + .appName("Leaf") // Gale - branding changes // Leaf - Rebrand .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) .completer(new ConsoleCommandCompleter(this.server)) .option(LineReader.Option.COMPLETE_IN_WORD, true); diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java -index 2596e0ee4df5b96f181e28a742ef345981fc97e3..5b844d2fea387f2cb655169f458ec0ca627f1c65 100644 +index 790bad0494454ca12ee152e3de6da3da634d9b20..5b844d2fea387f2cb655169f458ec0ca627f1c65 100644 --- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java +++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java -@@ -32,6 +32,9 @@ public record ServerBuildInfoImpl( +@@ -31,6 +31,10 @@ public record ServerBuildInfoImpl( + private static final String ATTRIBUTE_GIT_COMMIT = "Git-Commit"; private static final String BRAND_PAPER_NAME = "Paper"; - private static final String BRAND_GALE_NAME = "Gale"; // Gale - branding changes ++ private static final String BRAND_GALE_NAME = "Gale"; // Gale - branding changes + // Leaf start - Rebrand + private static final String BRAND_LEAF_NAME = "Leaf"; + // Leaf end - Rebrand private static final String BUILD_DEV = "DEV"; -@@ -43,9 +46,9 @@ public record ServerBuildInfoImpl( +@@ -42,9 +46,9 @@ public record ServerBuildInfoImpl( this( getManifestAttribute(manifest, ATTRIBUTE_BRAND_ID) .map(Key::key) -- .orElse(BRAND_GALE_ID), // Gale - branding changes +- .orElse(BRAND_PAPER_ID), + .orElse(BRAND_LEAF_ID), // Gale - branding changes // Leaf - Rebrand getManifestAttribute(manifest, ATTRIBUTE_BRAND_NAME) -- .orElse(BRAND_GALE_NAME), // Gale - branding changes +- .orElse(BRAND_PAPER_NAME), + .orElse(BRAND_LEAF_NAME), // Gale - branding changes // Leaf - Rebrand SharedConstants.getCurrentVersion().getId(), SharedConstants.getCurrentVersion().getName(), getManifestAttribute(manifest, ATTRIBUTE_BUILD_NUMBER) -@@ -62,7 +65,11 @@ public record ServerBuildInfoImpl( +@@ -61,7 +65,11 @@ public record ServerBuildInfoImpl( @Override public boolean isBrandCompatible(final @NotNull Key brandId) { -- return brandId.equals(this.brandId) || brandId.equals(BRAND_PAPER_ID); // Gale - branding changes +- return brandId.equals(this.brandId); + // Leaf start - Rebrand + return brandId.equals(this.brandId) + || brandId.equals(BRAND_PAPER_ID) @@ -90,46 +416,46 @@ index 2596e0ee4df5b96f181e28a742ef345981fc97e3..5b844d2fea387f2cb655169f458ec0ca @Override diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index f6bc955c3496b52cda1a20aabd78769803ef471f..f6f787db016f4d1ac14648ebf2b8e162a3e85962 100644 +index 1354ccfbf525e5e64483ac5f443cc2325ba63850..f6f787db016f4d1ac14648ebf2b8e162a3e85962 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -491,7 +491,7 @@ public class CraftScheduler implements BukkitScheduler { this.parsePending(); } else { // this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(this.currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper -- task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Gale"); // Paper // Gale - branding changes +- task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper + task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Leaf"); // Paper // Gale - branding changes // Leaf - Rebrand // We don't need to parse pending // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index ebe1136e2487d0d13e5a924a644f2237900a86a6..bef2ae29856a72344d3d755926f1b2dce4907df1 100644 +index 41b2026c87dea247d39c73b0e3eae892fb729cd5..498a642d243925eefa11d5997dc999bb9aa2fcda 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -508,7 +508,7 @@ public final class CraftMagicNumbers implements UnsafeValues { - // Paper start +@@ -481,7 +481,7 @@ public final class CraftMagicNumbers implements UnsafeValues { + @Override public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -- return new org.galemc.gale.version.GaleVersionFetcher(); // Gale - branding changes - version fetcher -+ return new org.dreeam.leaf.version.LeafVersionFetcher(); // Gale - branding changes - version fetcher // Leaf - Rebrand +- return new com.destroystokyo.paper.PaperVersionFetcher(); ++ return new org.dreeam.leaf.version.LeafVersionFetcher(); // Leaf - Rebrand } @Override diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 0b5979723bb30f9011ac64c36d894aa41713ec9b..c3d45e60e262b8e34d76f0425f6bef79f034e8ab 100644 +index 774556a62eb240da42e84db4502e2ed43495be17..c3d45e60e262b8e34d76f0425f6bef79f034e8ab 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/org.galemc.gale/gale-api/pom.properties"); // Gale - branding changes +- 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/cn.dreeam.leaf/leaf-api/pom.properties"); // Gale - branding changes // Leaf - Rebrand 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 349f8207d8a9bc4b2c6be9e64b4325a7a406e706..e45d5da04428c26fc6aa97fba974bde3573d7950 100644 +index 471941a5bf691d4c31b2eb5ef4a11dc91499f674..56f920067d9bdd6f239741d699f0746bbe54a3f5 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java @@ -25,7 +25,7 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre @@ -140,53 +466,69 @@ index 349f8207d8a9bc4b2c6be9e64b4325a7a406e706..e45d5da04428c26fc6aa97fba974bde3 + super("Watchdog Thread"); // Leaf - Rebrand - Purpur - use a generic name this.timeoutTime = timeoutTime; this.restart = restart; - this.earlyWarningEvery = Math.min(GlobalConfiguration.get().watchdog.earlyWarningEvery, timeoutTime); // Paper -@@ -82,15 +82,15 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre - We do not want people to report thread issues to Paper, - but we do want people to report thread issues to Gale. - */ -- logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug. This could be a Gale bug."); // Paper + this.earlyWarningEvery = Math.min(GlobalConfiguration.get().watchdog.earlyWarningEvery, timeoutTime); +@@ -75,14 +75,20 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre + this.lastEarlyWarning = currentTime; + if (isLongTimeout) { + logger.log(Level.SEVERE, "------------------------------"); +- logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug."); // Paper ++ // Gale start - branding changes ++ /* ++ We do not want people to report thread issues to Paper, ++ but we do want people to report thread issues to Gale. ++ */ + logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug. This could be a Leaf bug."); // Paper // Leaf - Rebrand - // Gale end - branding changes ++ // Gale end - branding changes logger.log(Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author"); logger.log(Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring"); logger.log(Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once"); logger.log(Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes"); -- logger.log(Level.SEVERE, "If you are unsure or think this is a Gale bug, please report this to https://github.com/GaleMC/Gale/issues - and if you think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues"); // Gale - branding changes +- logger.log(Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues"); + logger.log(Level.SEVERE, "If you are unsure or think this is a Leaf bug, please report this to https://github.com/Winds-Studio/Leaf/issues - and if you think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues"); // Gale - branding changes // Leaf - Rebrand logger.log(Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports"); -- logger.log(Level.SEVERE, "Gale version: " + Bukkit.getServer().getVersion()); // Gale - branding changes +- logger.log(Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion()); + logger.log(Level.SEVERE, "Leaf version: " + Bukkit.getServer().getVersion()); // Gale - branding changes // Leaf - Rebrand if (net.minecraft.world.level.Level.lastPhysicsProblem != null) { logger.log(Level.SEVERE, "------------------------------"); -@@ -115,13 +115,13 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre - We do not want people to report thread issues to Paper, - but we do want people to report thread issues to Gale. - */ -- logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - If you think this is a Gale bug, please report it at https://github.com/GaleMC/Gale/issues - THIS IS NOT A PAPER BUG OR CRASH - " + Bukkit.getServer().getVersion() + " ---"); +@@ -102,12 +108,18 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre + } + // Paper end + } else { +- logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); ++ // Gale start - branding changes ++ /* ++ We do not want people to report thread issues to Paper, ++ but we do want people to report thread issues to Gale. ++ */ + logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - If you think this is a Leaf bug, please report it at https://github.com/Winds-Studio/Leaf/issues - THIS IS NOT A PAPER BUG OR CRASH - " + Bukkit.getServer().getVersion() + " ---"); // Leaf - Rebrand - // Gale end - branding changes ++ // Gale end - branding changes logger.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); } // 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 Gale!):"); // Paper // Gale - branding changes +- logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):"); // Paper + logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Leaf!):"); // Paper // Gale - branding changes // Leaf - Rebrand 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, "------------------------------"); -@@ -139,7 +139,7 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre - We do not want people to report thread issues to Paper, - but we do want people to report thread issues to Gale. - */ -- logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - If you think this is a Gale bug, please report it at https://github.com/GaleMC/Gale/issues - THIS IS NOT A PAPER BUG OR CRASH ---"); +@@ -120,7 +132,13 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre + WatchdogThread.dumpThread(thread, logger); + } + } else { +- logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); ++ // Gale start - branding changes ++ /* ++ We do not want people to report thread issues to Paper, ++ but we do want people to report thread issues to Gale. ++ */ + logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - If you think this is a Leaf bug, please report it at https://github.com/Winds-Studio/Leaf/issues - THIS IS NOT A PAPER BUG OR CRASH ---"); // Leaf - Rebrand - // Gale end - branding changes ++ // Gale end - branding changes } + logger.log(Level.SEVERE, "------------------------------"); diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png -index e7e9fd9a6077535b89c6c9d7b0164e8b87c54bed..9e698edad90ebcd641fc59ade84643556b427070 100644 +index 8b924977b7886df9ab8790b1e4ff9b1c04a2af45..9e698edad90ebcd641fc59ade84643556b427070 100644 GIT binary patch literal 19657 zcmbTdWmFtZ)HOPTyE}sf_W;42;I4zaI|TP2!QI{6-EDvbm!QEJf;&Nj=JLGvd)Ie= @@ -567,164 +909,328 @@ zH}!7f0CJ(J|3VWt=oIcH9X`onoOiXPB|TE;k+u)Aq$MqsmH=7Ol6q(fkR>gthn4_Y z(vo^;36Lc%sfU&TS<;evXbF%dEvbi=09n$KdT0rdB`v9kmH=7Ol6vU>2aPAsPCpqk Qng9R*07*qoM6N<$g0t|Fy8r+H -literal 8324 -zcma)CWl&sAu)T{c4!b~b!Xm+46P&Pk(BKXmEVw5SED%`S0>P6I65QQggS)!~celq^ -z_1^#YV{TXV?VjqMxwmKLoC#G^k;B8Lzy<&SPeC58@g#fxYnb4tXQ6IU#*@HulGk$u -z0Mw2D8mK`@;_69B?k1z__SVtT&C|@q0`T7*W32VHtpOsLDw{jRK+%dU4Hf8PDP(tEaY -zVb;TO?zg>+y0e^=)H~9ck{1xzJJsKD<2QMWE<<4w$ku+?Nz~ -z?sw*04{Ntj2t(m?vGNT6Z&4?~J_DA=4@RZ|Hy|?L2baGw-~xOA-T`VLCt&4+Es7dJ -z3rqB1K#)Ht -zM;a6WNe+K~@E)jy^0nkG4{!%88+0X^_i_yf#-MD!UOnz)0W6pOg`AvCsp#J@n!d~L -zCVJ83uVFsD4tN05H1Ti{d&m(pugW$|17?Hwda!DnL8l=`_8ey*(%(4BM7^w__ -z29jw+qAw%K`BPELftPW%&SF96Iq -z_h)d~d@n?_dd(h4B}06FF_)p)nqY@o2W0}0k!fDPNE=n60)9Z1ad$Q2*UaJYIWokv -z-YS-7Pdx#2eP~Ya<+J1YRpR69RWsr44_urWbIB`C{fwD97K&lSNUb+huWn><5yoYB -zJfUnktJt254fv(LN1LG_v8d+K$*{JMVsT|C=wGYwMq)%b#mJ%{U3S -z3eOditQ%g>1&0d*gJeo>(pn)%r<8<&V=*Y6MZ|vjseW!0G4f*AyoOjh^n**XNNygpr52-!$+5s79~Rz!atG0AJ~ -zaLfL^_!UEf*!wv|>{tUMEVChL@bJ7VVyP{&`32M_;g)srdhGDfd*c_n>)Eu<6%~5 -zXz4zr{*Ya1{haF#(VA;Dlz!_!w!vA}mSI?pFpKT}D5t6tuIgcFQ^&`ihd_avR-x

@y(HdF(KVXFH}bp|wUaw6&QXCUa*zVm->M@=&FCKVp97YM|kve_3*VCW46 -zv!#8UFWTMyY4J+6m;I<#=$7m -zvIxO0NZyc8eys_L$J5|l<8aShl<6-W9Ux5Aw;1X-A*d|~znVkzbk~W9NS>&l06W&r -z81yNRW4XxCw4Q;`80-AJ0^JHD+(Ld}1M>T0KVc9A%jak_H8K+KT&aIL$9Yj{OwBsL -zi2A95!ZqP=dZaZjR5`2~3(lW{1Vhz*b*AYMF=(OA6b`(1Ehoh!e(1-&%>?^8@^6A5 -z{;YtsV$bNqlh-7LCkxfTnr1`I0`dcMIZD$kxbZku8$`3YrKX5Uk(spqYh -zz_N=sHsL;;DZ@TN>NwJZ2}p`Ul{vd;|ID)}R50=*NyUdB^$XQk88m|MZmkHOfep#< -zzpW_boa0-TB|CQC=plYSmJNqQ$Q=9@3P7a4zeOQ{L0(gfdR_i*D4RJ}5#WFvhZr#f -zpXZ0^);*ZmA%T458)_hcfwjJ0md)%R6*(R)!cKk-p_wl0EUYhkMtkW6apETFb28WQ -z4Mr#(QduSc1>s5h0i;rz#fJT4`6?ZjPm_lwr{!mvh!p@w7-I%Z_x=86oCm?^|4<)8 -z=$={{fGneBRf<}8)D3UL@M`bMg{F5AwQ4@5G3#t45l==axYJ4x9G47q)($$J@=@VI -z-Y!i+)Uo`F$q=Q3XBA3T_D`PpsL>6Mx4o-;&M{QBLJK6f;^0Rs9W?w@U_H8UL4 -zC<<6>UoFr6a8`MftsZLN7PJe>FpW^b?mA=9bI_jUn!2_yOZ)|xt7s4cHEZ;mY&G&={=sV`v1dU>v(H>0l%EsXcuV*0XE_*?nG -zwAp1c&4Q4%zq04fe%pX0p*k30Hxp~jLW>&P`{whYJ -zzJkFrrGP>Fd{IB8M&J0sk-7EX_Al~AhU4m{BiC-N8e+EFzQE6fx~9#Xf4W -zTRkXFzM{UunB;+Os7PyK|1qdU?R#%myF?+&G(?q&(NroYmBe0wlhR*;mu+A9q3JlL -zCpSCOmC%GJA@7BvKd`Y=s>FS}ixpv(yR$(^u#@RKn_nK} -z>R!=gxS9R?c(a{+!Il+}5&fj$ubAFFpQ}FY8!o@1KFW -zgd#)3#sg)MA-L41dVrsku5bKRmnOzp`GB^EO}3v{9=z{$K;nKL;e}0IQO*28T3TAe -zLoIq^SG`zr6}x1jkj)m}_Qt#{T!{>kA|@qV2g6Y{C;imh<|m$IL$T6>&JZ=XF~(#I -ze$g&Ik%OmSei6-t%`oS8 -z!RzV810Fzdj(4EGfU`l(E9NZg=liA9sdUi;C{pZ1WO&eu8fsKqA$nu2S-r{6F&Nnr -z6}kJoajWZ8Vv;TvpNZyjo3F+F@bu7F++{E8X(N`1D^$Kv@M#m-Ur&ZOoGnwcCJRP1 -zlg4uR==108HF-X4sCF*Na?O&4)YJB7GgIJIWOn3c!WF+a9qN2ra6aFYNrz$p{DPA^ -z)%WY;exJ@RoBMSTBR<;GMA|k%Ty3fhyyaGBm}r5mxQXdja#Mt<+-?hxgXPipb$NES -zxNY84ES)}*GUXnb$wpzf>U2Lj2_O1|TnOPxe5y_)HG19%K -zX8AWbA=>wR(RNYW=oYXGnFc#$)pdBy4>m%aN24jHjQv(GH$(&rK2D#NsQwC24&&)3 -zAuxBs-+rw@L#I()e1C9B(BJH)a7Rm>xjYZe#c~>J&zJ9cyblyII+M9GK$S$tCtg3m -zE!8fjMr(0i8rt-|tA3Us(c9O{=ek<*tL)2nyKoGiw>a8WMK*P2SIzfMt%aAyJcnaf -zbFz?U&!hE&duRl@QUCy1%oxkXPamf -z6-b#Z< -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 -ziumNvw(uoEt?aYT -z^=6lWI(cfI3ocV8i}suxydCuBrc6}0vmoX^RlL-jY?|e%%K#@`zRcD_w9?gY@;Dti -zQ;7WgCz9e>^G}WdWEfz0wRq7}(g^a&BBwOV5g0IOgn1Gx3P+NhdJ84%{oI6KZ6zM1 -z<@smeE%VaxHhObCA2ZB#Sr;!AbPCYB9WU|YTP1JH{Y)(H^+TqL%fQlO%2@aJ{4R-r -zQLf7e!0fCuL1;11?e0+d;9wH6LBdIP@nZHW1kbBoQo&0tb%|brxN5jU#;hhe}L^ -z8{yrF((CTOab2hx#9%q^;kJ2tdpjbZnq~&Ib#nPQz3ORi&y{W(48CqN2i4425serF -zT0jc0XW~8tQp1c@7o{@4<#^fRaGhmyLAueWS7K_#N^q;g_B-DIrt$AB*s2UK#x3d1 -zrrRxVw8)wwx8+T+9rDQ6(J}H(k9&Dt=)LFwuy7>iS@q9WREzNN{k)7~E(e^)&j&mNH)~|l=aEqnT}X9JnpM;f -zC?Fp>HMZ&od}VsTSL8-0@C>%y2?1p850Y`EwNc&^cQQCh;39YXD8?|x_D>NAf -zR>Uqk{l2<96$2)9pfPeMj{EO^{i48!J1YO$czewd*y{V4lY08Y#af;R`DgITuCM=< -ztdai+%WaWFFKX281E;fB7ltTQ3YYkD@8O0E^_zZlT*l`zcbAx;oYIv;1o_kFs)R}R -z+}TFrlV)$2+`}^SbAeQ{QwAeUdjYy4oq|TLllcvr?tLL(FVat0@97^T{Y;iZ3^MiV -z&7SDtG~B1+_hls84daz~0{ufG)Bhf7;D5lEByLuj`8nbHWKM}kS6d7K5oL}I!FlZN -z`02c%X&FrlmlQw^$wHyu>G(kD<-zQD-+?ePsOPJk%BcrI7>FvzCUv1Z*?CN&*s8O8 -z@oUF&db`Q3@mZw7L&Q#Gq1YD!I&M{*ER5~vL2D+iAV5DTVxrjoM}L|{!Bx$Olh=)B -zu0Wnfmr%p0?fC}Vl1xd_IXFiam@s-DuJGh#ObjB6kY3d3o)}8sqxyI=6dNltGMT?S -zBBoh>u62K&DlVIKJiJ^Fl2n{%*um6*EkuhVS;Imi@zcIZ2t-CEIn%n_45A<=)7(`$ -zpg09emChaZ44Y8%OIGmoMF62&F?Gb#;1;%z{V;cluC1sU!a}woOM9%MUS7(kcH2=(5?M -zxX6|{0vM8?MzJ!47}i@^TZx21biBA`K -gx-fwL-(3LIPg|59oc((uo)mzBj0(Kywdv>o0sO6>y#N3J +literal 16900 +zcmaicV|1Ng^k&Q(Hn!T>_Kj`Zc4OO48rwD-Gw*(Xv_UIGaL4*?7e3`t5-R2lSh^xqd84Cs4}W^FDQn9zijsF13M{zVR~<`0dB +z;hww3Rk_uLO*yyZ^N(arMN#SjFcHEi60E_fZug`IjtJ^LVtno=lKj+Jze{_WszRIN1X*HUTCH>C_wc;+D)6YYT +z*RWmTUi`Puu_Uwkj6-qwu_Ue*kO&$%=o%J?6*rej_Ock3znkGIb6 +zWm&yS2Z9LS7slFgUx+?ilDgQBdj7`ruw|IVzJ@wV{&tD)G@SPTMW@9Wl5lcsuU~6` +z7raw|%Or|@Pnlh`7!!rA1H$`p;zz}+92Tp2bFmKDAL`nrC>)<{qBHso +zvJ6|o^vMxL?frh4XZ`3WdH7s_NI0p@{EElbnX*!yp;Vtx&K&w$&to`sW +z79>enm;xWhu;ZKKIN}-h!eBKZM6j$9~*Q(SlE*i_bHS0o#tPY +z5-j+ww|x>h9%`RLUixM!e%f0qVAe5GH83X6?!#^_j-M@lO@*-aD%NMF2;Hg^Wgh@}elrPA3o_&(- +zeNyws4es~%;K1o+pfG(Z!G-nFWzl7)ejRNxY?M~uI=I&MYuz@4>GLH*ptjlQJ`LYr +z*KIIVzBhKHIDwe`X2hc@gsdjzXxX%b<_#kc$vIHFi2)-XM1=fs(`g?0)M{lcJXwp< +zBgIdDXM&n-=+_%;1a?sE$oeN{r%w=8tFfAlQopAk +z%wrVN=r>)oZ0w7^M~Xi~qp6lEaABgF(ck7V3Un;@cg|ODuD7@fw~OZ;^TQV +z$&4AiUj}-4;o`6JV$Y4C2G +z8hVweUdzl78hWzD|&J_)oRr2JdJP +zA&lca);^P(q@hQb9-kqNXVo9An7Q3NoAtyRQw-@JUDD$oluryjE +z3{zzbZhStP-K;xw@Yxf-B=4h(p=4f`k8p2DH$>qQLPR!szD!2|vJ}J`C6=EoRwG^+ +z;`ZDv1SGVO+?IqSxpxSM^_V~@2E+~dZQdl+oz;TP1MX+XXwugMy?Z5AoZ7#R33Y@T +zM)w4;9L0szO3>6i#4fV3q49@wu&`zcvQ!d8!m*dpn&7pp0Y=;QbiyOzhC7)Ki7tDt +zXaIqysWqx53ZgHlO)|YRDG**$7&F{0a8VEECY`3;yx)F>2;4Xr&gC;Iqiqx;orWkF +z8xk0Ty-mK&z`^~Fbs#S;;Qd@1ZFJh4R`+H>Wx$xgn>^oka;w9~QfR>rS7lYHG?D#o +z6Jo`Qg_-DP +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 +zw1mJ8tVoSO-(}absB6M8b$Zqe)Ok0$OkaA#I +z48@e8TAlv;PmB6dbP|{7<%qt@Ea>I;PRL4)=M`_G!A40Y$Xy1Mum)I0#!3<77H4)u +zI6c{)TUsy&o^*@2H9Bp>QJA#S8$`zN?+@z^IIQL|VxYEQfVw~Oc}Wq!FS`G2T=aDu +z-DMYe(1$x=331oN(i#yV%?Q)lcY`}FpGRp*74@@$fX%pE+dAGOh5QRhJ&mcaXOhk4 +zLi_pirw^Zws;d9n^#IE8T1ypZDX|crNABquU?iL2;Ql%4Vg5cNBt}OJdbLKnEi|`g2q%v70%eM&7 +z5gdFefu8Ix3n54MC +zW40SGT11ajrrm5AI24T?-2$|VMsU%VX}AMmt>Pr~B}#An{>%QG>_1FQYV^)CExzx2 +z&7E_9c!fpiCLci|F3H*eM2DQQRtQp4>V2RP=KX3ZVw#OXuFxj$VDmM&HQD{*dc7301976VQyI69%EFvxxn>qC&Lo-`%ImvM +zCv>AXKPcD26Z_;m`1pw)uF6Mp=RnShU^yM81!?jbl!v#-kSa#RLhSOG0?yp1YB6Jr +zW=GrO|0zIRSHiH?DYiO+$EpdMkwz#4I6V(J12-W0+dAo4J*?nDQrFI<*}a92Y%1bU +z`RC_4tyg7>R(8{ +zA8*g?PWv##WoF+p0bJe>whg#+(1_+A+)9HS$|n?k;(r=Le*vR;57rn)2& +zEkD8KBSZm#3Drt?t!*#s#>0+yUNysIKRg=t`KSOcSHieiUP0z8F_$tZ(ciPnq_o~@ +z%-{zhbs{i7 +zt~8q8%WO|MF(FE_ye*bl_-@NcA!S9$IMb6x0`e_oNF!hy5a)H^H)5)t(}ek4a1Nc~FF4@f;5aO%aB&3O%B8NuMWWCzYb`d> +zQ-&3)G|5M|pzcLy>pA(p=?3&XKn+v0^`HNsS?M0eb+60BxF|&Y{?>MI^x``)Vp}1V +z;<0N$BUc(0=p=y>zD3k_I~ +zMC>T|rn!T!wN%lqT@ +z&Afsj|04$m&CH2M?F|6yeqb+e`&JWTP^~~z(;c>5;z6RuFKe)%3j|YzeZB9c)5E08 +zvX9?L9%?PT7Vu(RAIXR}s*=I*@Qp<*vA{&7B2uwdBH$_I`33U5di9weG|3 +zx-Iy`1L`R>G-q<+w-{f5qc<7ls}^cT4Y^Qi+meHXFIDgqkt0wpdBZGY?LB+q9&o`T +zd18L5%R+44Ml^UNbEw58BXP#{+I#J1$;VGO`#6Grd<=RWgP+T+ktE6H^>C;%(}szj +zK;wt^oW!yG4Fz=zm4zKw@$Wdo`VJm=879kp$F&$uMP_qiKSB4L@SV)g55F9Rb=3ocrK>iqIRR9n!X0Do*Ldi{9M&^sg&T_TZz~>`tbXc$p%%BI% +z#MahUA?U0t#2ZA4_41*w&52#TXU^_G4)$#uGOnpIb{Gs?Bge_xP|beH;cUSBec^gk +zu;a`And#3j5LZ)LALL9lQ0{$A?tzx&K6M(;#M))7n&`7KTkT>KvjI7O4?mTa;X`81yn7WAir6 +z^Dv#2{~#3{X=5gyP*2v`3yoLJl)--n2rC2}*3n8(L~4ohHzT6QbyEu{!K3q#&p9Lp +z?3#RrZR0JWoh5V%Au%m2?uSB&RO!i99khjDd#7P;NaxJ<_f>mYXQOtXqBZifoWn1d5WC&hmG;&Gv(>!l)|)selJ-m-pz9Og@*rA +z%Xl~n+gHI_Rjy513U_dEaq-~ZLm%H7RpVbREoW=Zu*D?n%JFyy6(v}{RCOy +z>_wu--o5bv-4rRuWG0oN3a2+(f)C6nR0%>9HdI1mB`d{jE6Q4vSf>>{@~N-bGMc6~ +zn=1MB2?XIjZuOC!s@-pN5{60UUw-L4f1L-3Ohud?4)I$4Y&#w^A*ij(1$$3|Vskv} +z#YKCOBnHKh5QN8fd|k)wI{^HZj_1!`{L&>R(m@P^tYk*J)5>eCrio9{j>kWLDCGrM +z*O<)utCbjQiH>aHzD!~>SNyzV|B?uyizaR*!v`(g6N5ks=aSqWHk#wzbQOx2Ehc(>s +zfl`oSK+EzLOKDeK?n#pu;5qF1g-8bXyN##%K`x2R14CxOh8w&P-kz4U}>3Q=A& +zwAa>sCXe?|fR^Y+S9_jW;=!_GK`1Bc2HY6Y)*s}A##+#}239~LV&Q~wL&4n_6^@vW +z;nGUYJ$5-C#kJr2EtD&Ty$t-H)#GyT->}39LWB1gdo%LwqR8{YbRBL*-FCEc5iY{; +z#TpZ~y8yolNKuWi&enqz%<*)Y)j#ff)9q1ezkI|N7|zr3b=T|b>+m?)d% +zKJ;1@L~w8ZQn0MxZS*{ew-;Ohn^Jl!+U{m|QvgB~tai**t#d>0E=CMjN*SZ+36QnO +z4NrSN!Cd>9SLf?=!Hjh+ek}c}ND_U`vvi9(MS>7nGZ*lPm%4(7(bhfuTHod8y%;N{YO_KMV}N<7D)x5snD;XG +zzCOH#WK2$4mAvQWFCCZW#F8TRInJ+=$6eR`V~dES6+!6-=6lkVCHyCW^Bb-$@=b%3 +zi%hxQwAp^EOp|zR61~UikJsM89qE@P3@X5J>+K)hO6K`Z$80UqhLV&|mVt3wQ#G4H +zi4>T}s*jr9pkN+B@=LbuMW8^kzEFQde*yOdnXiUws9u#OD8dYzm?0F`qCm7pBCNNz +zOJB@PR!5?2&9Zw_Jg~i=TwmStKiYq1_@$ +zZKB*^u}y2o({7rV#Nl+8$2T5 +zthMF3X`+*;4Q-~&-*4NzrU=7>#}h=jB}<^tsAch7Ac~Vq;V7 +ziknpCHOP}_P8F&VE%6e`WG~EVa?$ra`knKZrYWbIZ_w@4vO+{B!(Pb&!YhY8pCfe= +zjxF8x>Zh3;#gw`fu})grVJcf=Ohg_Xc9m?(57$!NXQ#N%;Q{V}EjtmA$m<@Ie2(h2j9T2Xq=0<2R#daW&$ +z85=lCIqjn+?h$SF4u|?#DOOKg9>2c{9GSdlh{<(WR;Mb+bxH>u95roevUiqSmcdG* +zEL`{Qv+mA#hjLxuC*l?ROBgDsPYkDNU%;m09$2^ni=SVA=kS_) +z_h->URCbhQr89T-a-Gg9Dk?P`CT8-=f%@A28AYMmma&Ks#DNDsr^|eI%nHBQ0Nps* +z<{@u^G-9krSD|^{Vm?_nRkW_T!;E*n95To#4sxn;9FH2W%&T043S^Vg_Bk^^&J9*H +z=-^Zd6GYUG(CMkA?hy<&4Tc5fn4$3ys+ZiGw!07qHH1zPDzAJY;{8Oj#B1-LTAZ>D +zKqX)c%j0#o|H%z2zdkxYKaV6<&nEMgP`q%2&v+2dsa++rFeWoOnf$VkCAY6|8|kw{ +zdwe(maC?oeGlx#HVClH?)W&QZ`+=l3PIeQ%9cb~nWxJ9)YD|MPt`v?0-3bMcbZ<2Z +zG7xSnH{QoOr#C@?R{C$168|JMfCxcPAVuEhewgQpYO@AfbP3Fw+|Vi7h~L@$6ydj5 +zyf7_h9Rp$0Gii0mkT9xddqw>hIVCXV203~$D~swIj_)TV=zX)@-tK6Hb66mM;EywH +zsMV;{!i^8fvae3b)iz7_f6$4yU2i-b%Bh|o@eU2$RD^G(AtWlyl0^8dxd<9 +zCi_xU0%&wFugtmc%-uOk=xMY?lR%{7BQRZ~b8}1<=DQI)v2*#3|70VNVV*?SK4O}0 +z-HEICfCoyTwy@{F=Ac>4KISQEgQLDcj|>j}hzn(*RSn +zZw&u6!^Z2~7ae&u`+{IHYm_vxJJ@RRZ!LoCjQ2ecK6E;AqeyJZxfuAC +zaFBgBIQO4DawgA~vN)BCS%`;S38kn@9kWOTMq)$V$+z&4nDQvH*{(1#N58$C)v2#; +zJW|ch#FaXRBNNj6mX)HNV{_ScADWB7#Jn(Th}B15lvrI|-2fj-=SL1AY +zQrI&y#`tyxRIyenc$G7)m}|d;5&h;8q8?ap1~7v{vEXIAhojO|^XI$6=K!f+>;5yx +zJJXiq*Z?mW;Ak{?4<=)9$$a@6Q*=1_%}Nx&bGA3oqS%{I)k3y{#DALAzrPw)h(FU +zj}8a8Xte($dBpT +z_ZLeg50aO#zhmy?M*+dS#c4NyP>CZSyS+OOi>@2;)lr;&A$)(OEO;kV+bz6O57by +zyW>9>Ij2^Du|A83(r~$46%S7?Ancv(6R +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 +LFIp>X81%mY^Bg|U diff --git a/leaf-server/src/main/java/me/titaniumtown/ArrayConstants.java b/leaf-server/src/main/java/me/titaniumtown/ArrayConstants.java new file mode 100644 index 00000000..211c5b08 --- /dev/null +++ b/leaf-server/src/main/java/me/titaniumtown/ArrayConstants.java @@ -0,0 +1,19 @@ +// Gale - JettPack - reduce array allocations + +package me.titaniumtown; + +public final class ArrayConstants { + + private ArrayConstants() {} + + public static final Object[] emptyObjectArray = new Object[0]; + public static final short[] emptyShortArray = new short[0]; + public static final int[] emptyIntArray = new int[0]; + public static final int[] zeroSingletonIntArray = new int[]{0}; + public static final byte[] emptyByteArray = new byte[0]; + public static final String[] emptyStringArray = new String[0]; + public static final long[] emptyLongArray = new long[0]; + public static final org.bukkit.entity.Entity[] emptyBukkitEntityArray = new org.bukkit.entity.Entity[0]; + public static final net.minecraft.world.entity.Entity[] emptyEntityArray = new net.minecraft.world.entity.Entity[0]; + //public static final net.minecraft.server.level.ServerLevel[] emptyServerLevelArray = new net.minecraft.server.level.ServerLevel[0]; +} diff --git a/leaf-server/src/main/java/net/caffeinemc/mods/lithium/common/world/chunk/LithiumHashPalette.java b/leaf-server/src/main/java/net/caffeinemc/mods/lithium/common/world/chunk/LithiumHashPalette.java new file mode 100644 index 00000000..dc63c275 --- /dev/null +++ b/leaf-server/src/main/java/net/caffeinemc/mods/lithium/common/world/chunk/LithiumHashPalette.java @@ -0,0 +1,209 @@ +// Gale - Lithium - faster chunk serialization + +package net.caffeinemc.mods.lithium.common.world.chunk; + +import it.unimi.dsi.fastutil.HashCommon; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; +import net.minecraft.CrashReport; +import net.minecraft.CrashReportCategory; +import net.minecraft.ReportedException; +import net.minecraft.core.IdMap; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.VarInt; +import net.minecraft.world.level.chunk.MissingPaletteEntryException; +import net.minecraft.world.level.chunk.Palette; +import net.minecraft.world.level.chunk.PaletteResize; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Predicate; + +import static it.unimi.dsi.fastutil.Hash.FAST_LOAD_FACTOR; + +/** + * Generally provides better performance over the vanilla {@link net.minecraft.world.level.chunk.HashMapPalette} when calling + * {@link LithiumHashPalette#idFor(Object)} through using a faster backing map and reducing pointer chasing. + */ +public class LithiumHashPalette implements Palette { + private static final int ABSENT_VALUE = -1; + + private final IdMap idList; + private final PaletteResize resizeHandler; + private final int indexBits; + + private final Reference2IntOpenHashMap table; + private T[] entries; + private int size = 0; + + private LithiumHashPalette(IdMap idList, PaletteResize resizeHandler, int indexBits, T[] entries, Reference2IntOpenHashMap table, int size) { + this.idList = idList; + this.resizeHandler = resizeHandler; + this.indexBits = indexBits; + this.entries = entries; + this.table = table; + this.size = size; + } + + public LithiumHashPalette(IdMap idList, int bits, PaletteResize resizeHandler, List list) { + this(idList, bits, resizeHandler); + + for (T t : list) { + this.addEntry(t); + } + } + + @SuppressWarnings("unchecked") + public LithiumHashPalette(IdMap idList, int bits, PaletteResize resizeHandler) { + this.idList = idList; + this.indexBits = bits; + this.resizeHandler = resizeHandler; + + int capacity = 1 << bits; + + this.entries = (T[]) new Object[capacity]; + this.table = new Reference2IntOpenHashMap<>(capacity, FAST_LOAD_FACTOR); + this.table.defaultReturnValue(ABSENT_VALUE); + } + + @Override + public int idFor(@NotNull T obj) { + int id = this.table.getInt(obj); + + if (id == ABSENT_VALUE) { + id = this.computeEntry(obj); + } + + return id; + } + + @Override + public boolean maybeHas(@NotNull Predicate predicate) { + for (int i = 0; i < this.size; ++i) { + if (predicate.test(this.entries[i])) { + return true; + } + } + + return false; + } + + private int computeEntry(T obj) { + int id = this.addEntry(obj); + + if (id >= 1 << this.indexBits) { + if (this.resizeHandler == null) { + throw new IllegalStateException("Cannot grow"); + } else { + id = this.resizeHandler.onResize(this.indexBits + 1, obj); + } + } + + return id; + } + + private int addEntry(T obj) { + int nextId = this.size; + + if (nextId >= this.entries.length) { + this.resize(this.size); + } + + this.table.put(obj, nextId); + this.entries[nextId] = obj; + + this.size++; + + return nextId; + } + + private void resize(int neededCapacity) { + this.entries = Arrays.copyOf(this.entries, HashCommon.nextPowerOfTwo(neededCapacity + 1)); + } + + @Override + public @NotNull T valueFor(int id) { + T[] entries = this.entries; + + T entry = null; + if (id >= 0 && id < entries.length) { + entry = entries[id]; + } + + if (entry != null) { + return entry; + } else { + throw this.missingPaletteEntryCrash(id); + } + } + + private ReportedException missingPaletteEntryCrash(int id) { + try { + throw new MissingPaletteEntryException(id); + } catch (MissingPaletteEntryException e) { + CrashReport crashReport = CrashReport.forThrowable(e, "[Lithium] Getting Palette Entry"); + CrashReportCategory crashReportCategory = crashReport.addCategory("Chunk section"); + crashReportCategory.setDetail("IndexBits", this.indexBits); + crashReportCategory.setDetail("Entries", this.entries.length + " Elements: " + Arrays.toString(this.entries)); + crashReportCategory.setDetail("Table", this.table.size() + " Elements: " + this.table); + return new ReportedException(crashReport); + } + } + + @Override + public void read(FriendlyByteBuf buf) { + this.clear(); + + int entryCount = buf.readVarInt(); + + for (int i = 0; i < entryCount; ++i) { + this.addEntry(this.idList.byIdOrThrow(buf.readVarInt())); + } + } + + @Override + public void write(FriendlyByteBuf buf) { + int size = this.size; + buf.writeVarInt(size); + + for (int i = 0; i < size; ++i) { + buf.writeVarInt(this.idList.getId(this.valueFor(i))); + } + } + + @Override + public int getSerializedSize() { + int size = VarInt.getByteSize(this.size); + + for (int i = 0; i < this.size; ++i) { + size += VarInt.getByteSize(this.idList.getId(this.valueFor(i))); + } + + return size; + } + + @Override + public int getSize() { + return this.size; + } + + @Override + public @NotNull Palette copy(@NotNull PaletteResize resizeHandler) { + return new LithiumHashPalette<>(this.idList, resizeHandler, this.indexBits, this.entries.clone(), this.table.clone(), this.size); + } + + private void clear() { + Arrays.fill(this.entries, null); + this.table.clear(); + this.size = 0; + } + + public List getElements() { + T[] copy = Arrays.copyOf(this.entries, this.size); + return Arrays.asList(copy); + } + + public static Palette create(int bits, IdMap idList, PaletteResize listener, List list) { + return new LithiumHashPalette<>(idList, bits, listener, list); + } +} diff --git a/leaf-server/src/main/java/org/galemc/gale/command/GaleCommand.java b/leaf-server/src/main/java/org/galemc/gale/command/GaleCommand.java new file mode 100644 index 00000000..c2000206 --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/command/GaleCommand.java @@ -0,0 +1,179 @@ +// Gale - Gale commands - /gale command + +package org.galemc.gale.command; + +import io.papermc.paper.command.CommandUtil; +import it.unimi.dsi.fastutil.Pair; +import net.minecraft.Util; +import org.galemc.gale.command.subcommands.InfoCommand; +import org.galemc.gale.command.subcommands.ReloadCommand; +import org.galemc.gale.command.subcommands.VersionCommand; +import org.jetbrains.annotations.Nullable; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionDefault; +import org.bukkit.plugin.PluginManager; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static net.kyori.adventure.text.Component.newline; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.RED; + +public final class GaleCommand extends Command { + public static final String COMMAND_LABEL = "gale"; + public static final String BASE_PERM = GaleCommands.COMMAND_BASE_PERM + "." + COMMAND_LABEL; + private static final Permission basePermission = new Permission(BASE_PERM, PermissionDefault.TRUE); + // subcommand label -> subcommand + private static final GaleSubcommand RELOAD_SUBCOMMAND = new ReloadCommand(); + private static final GaleSubcommand VERSION_SUBCOMMAND = new VersionCommand(); + private static final GaleSubcommand INFO_SUBCOMMAND = new InfoCommand(); + private static final Map SUBCOMMANDS = Util.make(() -> { + final Map, GaleSubcommand> commands = new HashMap<>(); + + commands.put(Set.of(ReloadCommand.LITERAL_ARGUMENT), RELOAD_SUBCOMMAND); + commands.put(Set.of(VersionCommand.LITERAL_ARGUMENT), VERSION_SUBCOMMAND); + commands.put(Set.of(InfoCommand.LITERAL_ARGUMENT), INFO_SUBCOMMAND); + + return commands.entrySet().stream() + .flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue()))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + }); + // alias -> subcommand label + private static final Map ALIASES = Util.make(() -> { + final Map> aliases = new HashMap<>(); + + aliases.put(VersionCommand.LITERAL_ARGUMENT, Set.of("ver")); + aliases.put(InfoCommand.LITERAL_ARGUMENT, Set.of("about")); + + return aliases.entrySet().stream() + .flatMap(entry -> entry.getValue().stream().map(s -> Map.entry(s, entry.getKey()))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + }); + + private String createUsageMessage(Collection arguments) { + return "/" + COMMAND_LABEL + " [" + String.join(" | ", arguments) + "]"; + } + + public GaleCommand() { + super(COMMAND_LABEL); + this.description = "Gale related commands"; + this.usageMessage = this.createUsageMessage(SUBCOMMANDS.keySet()); + final List permissions = SUBCOMMANDS.values().stream().map(GaleSubcommand::getPermission).filter(Objects::nonNull).toList(); + this.setPermission(BASE_PERM); + final PluginManager pluginManager = Bukkit.getServer().getPluginManager(); + pluginManager.addPermission(basePermission); + for (final Permission permission : permissions) { + pluginManager.addPermission(permission); + } + } + + @Override + public List tabComplete( + final CommandSender sender, + final String alias, + final String[] args, + final @Nullable Location location + ) throws IllegalArgumentException { + if (args.length <= 1) { + List subCommandArguments = new ArrayList<>(SUBCOMMANDS.size()); + for (Map.Entry subCommandEntry : SUBCOMMANDS.entrySet()) { + if (subCommandEntry.getValue().testPermission(sender)) { + subCommandArguments.add(subCommandEntry.getKey()); + } + } + return CommandUtil.getListMatchingLast(sender, args, subCommandArguments); + } + + final @Nullable Pair subCommand = resolveCommand(args[0]); + if (subCommand != null && subCommand.second().testPermission(sender)) { + return subCommand.second().tabComplete(sender, subCommand.first(), Arrays.copyOfRange(args, 1, args.length)); + } + + return Collections.emptyList(); + } + + private boolean testHasOnePermission(CommandSender sender) { + for (Map.Entry subCommandEntry : SUBCOMMANDS.entrySet()) { + if (subCommandEntry.getValue().testPermission(sender)) { + return true; + } + } + return false; + } + + @Override + public boolean execute( + final CommandSender sender, + final String commandLabel, + final String[] args + ) { + + // Check if the sender has the base permission and at least one specific permission + if (!sender.hasPermission(basePermission) || !this.testHasOnePermission(sender)) { + sender.sendMessage(Bukkit.permissionMessage()); + return true; + } + + // Determine the usage message with the subcommands they can perform + List subCommandArguments = new ArrayList<>(SUBCOMMANDS.size()); + for (Map.Entry subCommandEntry : SUBCOMMANDS.entrySet()) { + if (subCommandEntry.getValue().testPermission(sender)) { + subCommandArguments.add(subCommandEntry.getKey()); + } + } + String specificUsageMessage = this.createUsageMessage(subCommandArguments); + + // If they did not give a subcommand + if (args.length == 0) { + INFO_SUBCOMMAND.execute(sender, InfoCommand.LITERAL_ARGUMENT, me.titaniumtown.ArrayConstants.emptyStringArray); // Gale - JettPack - reduce array allocations + sender.sendMessage(newline().append(text("Command usage: " + specificUsageMessage, GRAY))); + return false; + } + + // If they do not have permission for the subcommand they gave, or the argument is not a valid subcommand + final @Nullable Pair subCommand = resolveCommand(args[0]); + if (subCommand == null || !subCommand.second().testPermission(sender)) { + sender.sendMessage(text("Usage: " + specificUsageMessage, RED)); + return false; + } + + // Execute the subcommand + final String[] choppedArgs = Arrays.copyOfRange(args, 1, args.length); + return subCommand.second().execute(sender, subCommand.first(), choppedArgs); + + } + + private static @Nullable Pair resolveCommand(String label) { + label = label.toLowerCase(Locale.ENGLISH); + @Nullable GaleSubcommand subCommand = SUBCOMMANDS.get(label); + if (subCommand == null) { + final @Nullable String command = ALIASES.get(label); + if (command != null) { + label = command; + subCommand = SUBCOMMANDS.get(command); + } + } + + if (subCommand != null) { + return Pair.of(label, subCommand); + } + + return null; + } + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/command/GaleCommands.java b/leaf-server/src/main/java/org/galemc/gale/command/GaleCommands.java new file mode 100644 index 00000000..fbbc6f6a --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/command/GaleCommands.java @@ -0,0 +1,33 @@ +// Gale - Gale commands + +package org.galemc.gale.command; + +import net.minecraft.server.MinecraftServer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.bukkit.command.Command; +import org.bukkit.craftbukkit.util.permissions.CraftDefaultPermissions; + +import java.util.HashMap; +import java.util.Map; + +@DefaultQualifier(NonNull.class) +public final class GaleCommands { + + public static final String COMMAND_BASE_PERM = CraftDefaultPermissions.GALE_ROOT + ".command"; + + private GaleCommands() { + } + + private static final Map COMMANDS = new HashMap<>(); + + static { + COMMANDS.put(GaleCommand.COMMAND_LABEL, new GaleCommand()); + } + + public static void registerCommands(final MinecraftServer server) { + COMMANDS.forEach((s, command) -> + server.server.getCommandMap().register(s, "Gale", command) + ); + } +} diff --git a/leaf-server/src/main/java/org/galemc/gale/command/GaleSubcommand.java b/leaf-server/src/main/java/org/galemc/gale/command/GaleSubcommand.java new file mode 100644 index 00000000..d2b32a4d --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/command/GaleSubcommand.java @@ -0,0 +1,27 @@ +// Gale - Gale commands + +package org.galemc.gale.command; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.jetbrains.annotations.Nullable; +import org.bukkit.command.CommandSender; +import org.bukkit.permissions.Permission; + +import java.util.Collections; +import java.util.List; + +@DefaultQualifier(NonNull.class) +public interface GaleSubcommand { + + boolean execute(CommandSender sender, String subCommand, String[] args); + + default List tabComplete(final CommandSender sender, final String subCommand, final String[] args) { + return Collections.emptyList(); + } + + boolean testPermission(CommandSender sender); + + @Nullable Permission getPermission(); + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/command/PermissionedGaleSubcommand.java b/leaf-server/src/main/java/org/galemc/gale/command/PermissionedGaleSubcommand.java new file mode 100644 index 00000000..40d84d0d --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/command/PermissionedGaleSubcommand.java @@ -0,0 +1,32 @@ +// Gale - Gale commands + +package org.galemc.gale.command; + +import org.jetbrains.annotations.Nullable; +import org.bukkit.command.CommandSender; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionDefault; + +public abstract class PermissionedGaleSubcommand implements GaleSubcommand { + + public final Permission permission; + + protected PermissionedGaleSubcommand(Permission permission) { + this.permission = permission; + } + + protected PermissionedGaleSubcommand(String permission, PermissionDefault permissionDefault) { + this(new Permission(permission, permissionDefault)); + } + + @Override + public boolean testPermission(CommandSender sender) { + return sender.hasPermission(this.permission); + } + + @Override + public @Nullable Permission getPermission() { + return this.permission; + } + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/command/subcommands/InfoCommand.java b/leaf-server/src/main/java/org/galemc/gale/command/subcommands/InfoCommand.java new file mode 100644 index 00000000..268ab2d6 --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/command/subcommands/InfoCommand.java @@ -0,0 +1,42 @@ +// Gale - Gale commands - /gale info command + +package org.galemc.gale.command.subcommands; + +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.TextDecoration; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.galemc.gale.command.GaleSubcommand; +import org.jetbrains.annotations.Nullable; +import org.bukkit.command.CommandSender; +import org.bukkit.permissions.Permission; + +import static net.kyori.adventure.text.Component.text; + +@DefaultQualifier(NonNull.class) +public final class InfoCommand implements GaleSubcommand { + + public final static String LITERAL_ARGUMENT = "info"; + + @Override + public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { + sender.sendMessage( + text("Gale is a performant Minecraft server system. Find us on: ") + .append(text("https://github.com/GaleMC/Gale") + .decorate(TextDecoration.UNDERLINED) + .clickEvent(ClickEvent.openUrl("https://github.com/GaleMC/Gale"))) + ); + return true; + } + + @Override + public boolean testPermission(CommandSender sender) { + return true; + } + + @Override + public @Nullable Permission getPermission() { + return null; + } + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/command/subcommands/ReloadCommand.java b/leaf-server/src/main/java/org/galemc/gale/command/subcommands/ReloadCommand.java new file mode 100644 index 00000000..94f39d5b --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/command/subcommands/ReloadCommand.java @@ -0,0 +1,46 @@ +// Gale - Gale commands - /gale reload command + +package org.galemc.gale.command.subcommands; + +import net.minecraft.server.MinecraftServer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.galemc.gale.command.GaleCommand; +import org.galemc.gale.command.PermissionedGaleSubcommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.permissions.PermissionDefault; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; + +@DefaultQualifier(NonNull.class) +public final class ReloadCommand extends PermissionedGaleSubcommand { + + public final static String LITERAL_ARGUMENT = "reload"; + public static final String PERM = GaleCommand.BASE_PERM + "." + LITERAL_ARGUMENT; + + public ReloadCommand() { + super(PERM, PermissionDefault.OP); + } + + @Override + public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { + this.doReload(sender); + return true; + } + + private void doReload(final CommandSender sender) { + Command.broadcastCommandMessage(sender, text("Please note that this command is not supported and may cause issues.", RED)); + Command.broadcastCommandMessage(sender, text("If you encounter any issues please use the /stop command to restart your server.", RED)); + + MinecraftServer server = ((CraftServer) sender.getServer()).getServer(); + server.galeConfigurations.reloadConfigs(server); + server.server.reloadCount++; + + Command.broadcastCommandMessage(sender, text("Gale config reload complete.", GREEN)); + } + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/command/subcommands/VersionCommand.java b/leaf-server/src/main/java/org/galemc/gale/command/subcommands/VersionCommand.java new file mode 100644 index 00000000..38c49703 --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/command/subcommands/VersionCommand.java @@ -0,0 +1,39 @@ +// Gale - Gale commands - /gale version command + +package org.galemc.gale.command.subcommands; + +import net.minecraft.server.MinecraftServer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.galemc.gale.command.GaleCommand; +import org.galemc.gale.command.PermissionedGaleSubcommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.permissions.PermissionDefault; + +@DefaultQualifier(NonNull.class) +public final class VersionCommand extends PermissionedGaleSubcommand { + + public final static String LITERAL_ARGUMENT = "version"; + public static final String PERM = GaleCommand.BASE_PERM + "." + LITERAL_ARGUMENT; + + public VersionCommand() { + super(PERM, PermissionDefault.TRUE); + } + + @Override + public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { + final @Nullable Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version"); + if (ver != null) { + ver.execute(sender, GaleCommand.COMMAND_LABEL, me.titaniumtown.ArrayConstants.emptyStringArray); // Gale - JettPack - reduce array allocations + } + return true; + } + + @Override + public boolean testPermission(CommandSender sender) { + return super.testPermission(sender) && sender.hasPermission("bukkit.command.version"); + } + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/configuration/GaleConfigurations.java b/leaf-server/src/main/java/org/galemc/gale/configuration/GaleConfigurations.java new file mode 100644 index 00000000..4e17c833 --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/configuration/GaleConfigurations.java @@ -0,0 +1,305 @@ +// Gale - Gale configuration + +package org.galemc.gale.configuration; + +import com.google.common.collect.Table; +import com.mojang.logging.LogUtils; +import io.leangen.geantyref.TypeToken; +import io.papermc.paper.configuration.Configuration; +import io.papermc.paper.configuration.ConfigurationPart; +import io.papermc.paper.configuration.Configurations; +import io.papermc.paper.configuration.NestedSetting; +import io.papermc.paper.configuration.PaperConfigurations; +import io.papermc.paper.configuration.legacy.RequiresSpigotInitialization; +import io.papermc.paper.configuration.mapping.InnerClassFieldDiscoverer; +import io.papermc.paper.configuration.serializer.ComponentSerializer; +import io.papermc.paper.configuration.serializer.EnumValueSerializer; +import io.papermc.paper.configuration.serializer.PacketClassSerializer; +import io.papermc.paper.configuration.serializer.StringRepresentableSerializer; +import io.papermc.paper.configuration.serializer.collections.FastutilMapSerializer; +import io.papermc.paper.configuration.serializer.collections.MapSerializer; +import io.papermc.paper.configuration.serializer.collections.TableSerializer; +import io.papermc.paper.configuration.serializer.registry.RegistryHolderSerializer; +import io.papermc.paper.configuration.serializer.registry.RegistryValueSerializer; +import io.papermc.paper.configuration.transformation.Transformations; +import io.papermc.paper.configuration.type.BooleanOrDefault; +import io.papermc.paper.configuration.type.Duration; +import io.papermc.paper.configuration.type.EngineMode; +import io.papermc.paper.configuration.type.fallback.FallbackValueSerializer; +import io.papermc.paper.configuration.type.number.DoubleOr; +import io.papermc.paper.configuration.type.number.IntOr; +import it.unimi.dsi.fastutil.objects.Reference2IntMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2LongMap; +import it.unimi.dsi.fastutil.objects.Reference2LongOpenHashMap; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.registries.Registries; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.spongepowered.configurate.ConfigurateException; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.ConfigurationOptions; +import org.spongepowered.configurate.NodePath; +import org.spongepowered.configurate.objectmapping.ObjectMapper; +import org.spongepowered.configurate.transformation.ConfigurationTransformation; +import org.spongepowered.configurate.transformation.TransformAction; +import org.spongepowered.configurate.yaml.YamlConfigurationLoader; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +import static io.leangen.geantyref.GenericTypeReflector.erase; + +@SuppressWarnings("Convert2Diamond") +public class GaleConfigurations extends Configurations { + + private static final Logger LOGGER = LogUtils.getLogger(); + static final String GLOBAL_CONFIG_FILE_NAME = "gale-global.yml"; + static final String WORLD_DEFAULTS_CONFIG_FILE_NAME = "gale-world-defaults.yml"; + static final String WORLD_CONFIG_FILE_NAME = "gale-world.yml"; + public static final String CONFIG_DIR = "config"; + + private static final String GLOBAL_HEADER = String.format(""" + This is the global configuration file for Gale. + As you can see, there's a lot to configure. Some options may impact gameplay, so use + with caution, and make sure you know what each option does before configuring. + + If you need help with the configuration or have any questions related to Gale, + join us in our Discord, or check the GitHub Wiki pages. + + The world configuration options are inside + their respective world folder. The files are named %s + + Wiki: https://github.com/GaleMC/Gale/wiki + Discord: https://discord.gg/gwezNT8c24""", WORLD_CONFIG_FILE_NAME); + + private static final String WORLD_DEFAULTS_HEADER = """ + This is the world defaults configuration file for Gale. + As you can see, there's a lot to configure. Some options may impact gameplay, so use + with caution, and make sure you know what each option does before configuring. + + If you need help with the configuration or have any questions related to Gale, + join us in our Discord, or check the GitHub Wiki pages. + + Configuration options here apply to all worlds, unless you specify overrides inside + the world-specific config file inside each world folder. + + Wiki: https://github.com/GaleMC/Gale/wiki + Discord: https://discord.gg/gwezNT8c24"""; + + private static final Function WORLD_HEADER = map -> String.format(""" + This is a world configuration file for Gale. + This file may start empty but can be filled with settings to override ones in the %s/%s + + World: %s (%s)""", + CONFIG_DIR, + WORLD_DEFAULTS_CONFIG_FILE_NAME, + map.require(WORLD_NAME), + map.require(WORLD_KEY) + ); + + private static final String MOVED_NOTICE = """ + The global and world default configuration files have moved to %s + and the world-specific configuration file has been moved inside + the respective world folder. + + See https://github.com/GaleMC/Gale/wiki for more information. + """; + + public GaleConfigurations(final Path globalFolder) { + super(globalFolder, GaleGlobalConfiguration.class, GaleWorldConfiguration.class, GLOBAL_CONFIG_FILE_NAME, WORLD_DEFAULTS_CONFIG_FILE_NAME, WORLD_CONFIG_FILE_NAME); + } + + @Override + protected YamlConfigurationLoader.Builder createLoaderBuilder() { + return super.createLoaderBuilder() + .defaultOptions(GaleConfigurations::defaultOptions); + } + + private static ConfigurationOptions defaultOptions(ConfigurationOptions options) { + return options.serializers(builder -> builder + .register(MapSerializer.TYPE, new MapSerializer(false)) + .register(new EnumValueSerializer()) + .register(new ComponentSerializer()) + ); + } + + @Override + protected ObjectMapper.Factory.Builder createGlobalObjectMapperFactoryBuilder() { + return defaultGlobalFactoryBuilder(super.createGlobalObjectMapperFactoryBuilder()); + } + + private static ObjectMapper.Factory.Builder defaultGlobalFactoryBuilder(ObjectMapper.Factory.Builder builder) { + return builder.addDiscoverer(InnerClassFieldDiscoverer.globalConfig()); + } + + @Override + protected YamlConfigurationLoader.Builder createGlobalLoaderBuilder(RegistryAccess registryAccess) { + return super.createGlobalLoaderBuilder(registryAccess) + .defaultOptions((options) -> defaultGlobalOptions(registryAccess, options)); + } + + private static ConfigurationOptions defaultGlobalOptions(RegistryAccess registryAccess, ConfigurationOptions options) { + return options + .header(GLOBAL_HEADER) + .serializers(builder -> builder.register(new PacketClassSerializer()) + .register(new RegistryValueSerializer<>(new TypeToken>() {}, registryAccess, Registries.DATA_COMPONENT_TYPE, false)) + ); + } + + @Override + public GaleGlobalConfiguration initializeGlobalConfiguration(final RegistryAccess registryAccess) throws ConfigurateException { + GaleGlobalConfiguration configuration = super.initializeGlobalConfiguration(registryAccess); + GaleGlobalConfiguration.set(configuration); + return configuration; + } + + @Override + protected ContextMap.Builder createDefaultContextMap(final RegistryAccess registryAccess) { + return super.createDefaultContextMap(registryAccess) + .put(PaperConfigurations.SPIGOT_WORLD_CONFIG_CONTEXT_KEY, PaperConfigurations.SPIGOT_WORLD_DEFAULTS); + } + + @Override + protected ObjectMapper.Factory.Builder createWorldObjectMapperFactoryBuilder(final ContextMap contextMap) { + return super.createWorldObjectMapperFactoryBuilder(contextMap) + .addNodeResolver(new RequiresSpigotInitialization.Factory(contextMap.require(PaperConfigurations.SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get())) + .addNodeResolver(new NestedSetting.Factory()) + .addDiscoverer(InnerClassFieldDiscoverer.galeWorldConfig(contextMap)); + } + + @Override + protected YamlConfigurationLoader.Builder createWorldConfigLoaderBuilder(final ContextMap contextMap) { + final RegistryAccess access = contextMap.require(REGISTRY_ACCESS); + return super.createWorldConfigLoaderBuilder(contextMap) + .defaultOptions(options -> options + .header(contextMap.require(WORLD_NAME).equals(WORLD_DEFAULTS) ? WORLD_DEFAULTS_HEADER : WORLD_HEADER.apply(contextMap)) + .serializers(serializers -> serializers + .register(new TypeToken>() {}, new FastutilMapSerializer.SomethingToPrimitive>(Reference2IntOpenHashMap::new, Integer.TYPE)) + .register(new TypeToken>() {}, new FastutilMapSerializer.SomethingToPrimitive>(Reference2LongOpenHashMap::new, Long.TYPE)) + .register(new TypeToken>() {}, new TableSerializer()) + .register(new StringRepresentableSerializer()) + .register(IntOr.Default.SERIALIZER) + .register(IntOr.Disabled.SERIALIZER) + .register(DoubleOr.Default.SERIALIZER) + .register(BooleanOrDefault.SERIALIZER) + .register(Duration.SERIALIZER) + .register(EngineMode.SERIALIZER) + .register(FallbackValueSerializer.create(contextMap.require(PaperConfigurations.SPIGOT_WORLD_CONFIG_CONTEXT_KEY).get(), MinecraftServer::getServer)) + .register(new RegistryValueSerializer<>(new TypeToken>() {}, access, Registries.ENTITY_TYPE, true)) + .register(new RegistryValueSerializer<>(Item.class, access, Registries.ITEM, true)) + .register(new RegistryHolderSerializer<>(new TypeToken>() {}, access, Registries.CONFIGURED_FEATURE, false)) + .register(new RegistryHolderSerializer<>(Item.class, access, Registries.ITEM, true)) + ) + ); + } + + @Override + protected void applyWorldConfigTransformations(final ContextMap contextMap, final ConfigurationNode node, final @Nullable ConfigurationNode defaultsNode) throws ConfigurateException { + final ConfigurationNode version = node.node(Configuration.VERSION_FIELD); + final String world = contextMap.require(WORLD_NAME); + if (version.virtual()) { + LOGGER.warn("The Gale world config file for {} didn't have a version set, assuming latest", world); + version.raw(GaleWorldConfiguration.CURRENT_VERSION); + } + if (GaleRemovedConfigurations.REMOVED_WORLD_PATHS.length > 0) { + ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder(); + for (NodePath path : GaleRemovedConfigurations.REMOVED_WORLD_PATHS) { + builder.addAction(path, TransformAction.remove()); + } + builder.build().apply(node); + } + // ADD FUTURE TRANSFORMS HERE + } + + @Override + protected void applyGlobalConfigTransformations(ConfigurationNode node) throws ConfigurateException { + if (GaleRemovedConfigurations.REMOVED_GLOBAL_PATHS.length > 0) { + ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder(); + for (NodePath path : GaleRemovedConfigurations.REMOVED_GLOBAL_PATHS) { + builder.addAction(path, TransformAction.remove()); + } + builder.build().apply(node); + } + // ADD FUTURE TRANSFORMS HERE + } + + private static final List DEFAULT_AWARE_TRANSFORMATIONS = Collections.emptyList(); + + @Override + protected void applyDefaultsAwareWorldConfigTransformations(final ContextMap contextMap, final ConfigurationNode worldNode, final ConfigurationNode defaultsNode) throws ConfigurateException { + final ConfigurationTransformation.Builder builder = ConfigurationTransformation.builder(); + // ADD FUTURE TRANSFORMS HERE (these transforms run after the defaults have been merged into the node) + DEFAULT_AWARE_TRANSFORMATIONS.forEach(transform -> transform.apply(builder, contextMap, defaultsNode)); + + ConfigurationTransformation transformation; + try { + transformation = builder.build(); // build throws IAE if no actions were provided (bad zml) + } catch (IllegalArgumentException ignored) { + return; + } + transformation.apply(worldNode); + } + + @Override + public GaleWorldConfiguration createWorldConfig(final ContextMap contextMap) { + final String levelName = contextMap.require(WORLD_NAME); + try { + return super.createWorldConfig(contextMap); + } catch (IOException exception) { + throw new RuntimeException("Could not create Gale world config for " + levelName, exception); + } + } + + @Override + protected boolean isConfigType(final Type type) { + return ConfigurationPart.class.isAssignableFrom(erase(type)); + } + + public void reloadConfigs(MinecraftServer server) { + try { + this.initializeGlobalConfiguration(server.registryAccess(), reloader(this.globalConfigClass, GaleGlobalConfiguration.get())); + this.initializeWorldDefaultsConfiguration(server.registryAccess()); + for (ServerLevel level : server.getAllLevels()) { + this.createWorldConfig(PaperConfigurations.createWorldContextMap(level), reloader(this.worldConfigClass, level.galeConfig())); + } + } catch (Exception ex) { + throw new RuntimeException("Could not reload Gale configuration files", ex); + } + } + + public static GaleConfigurations setup(final Path configDir) throws Exception { + try { + PaperConfigurations.createDirectoriesSymlinkAware(configDir); + return new GaleConfigurations(configDir); + } catch (final IOException ex) { + throw new RuntimeException("Could not setup GaleConfigurations", ex); + } + } + + @Override + protected int globalConfigVersion() { + return GaleGlobalConfiguration.CURRENT_VERSION; + } + + @Override + protected int worldConfigVersion() { + return getWorldConfigurationCurrentVersion(); + } + + @Override + public int getWorldConfigurationCurrentVersion() { + return GaleWorldConfiguration.CURRENT_VERSION; + } + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java b/leaf-server/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java new file mode 100644 index 00000000..bba8ca8f --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/configuration/GaleGlobalConfiguration.java @@ -0,0 +1,139 @@ +// Gale - Gale configuration + +package org.galemc.gale.configuration; + +import io.papermc.paper.configuration.Configuration; +import io.papermc.paper.configuration.ConfigurationPart; +import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece; +import org.spongepowered.configurate.objectmapping.meta.PostProcess; +import org.spongepowered.configurate.objectmapping.meta.Setting; +import org.bukkit.plugin.java.JavaPluginLoader; + +import java.util.Locale; +import java.util.function.Consumer; + +@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal", "FieldMayBeFinal", "InnerClassMayBeStatic"}) +public class GaleGlobalConfiguration extends ConfigurationPart { + static final int CURRENT_VERSION = 1; + private static GaleGlobalConfiguration instance; + + public static GaleGlobalConfiguration get() { + return instance; + } + + static void set(GaleGlobalConfiguration instance) { + GaleGlobalConfiguration.instance = instance; + } + + @Setting(Configuration.VERSION_FIELD) + public int version = CURRENT_VERSION; + + public SmallOptimizations smallOptimizations; + + public class SmallOptimizations extends ConfigurationPart { + + public ReducedIntervals reducedIntervals; + + public class ReducedIntervals extends ConfigurationPart { + + public int increaseTimeStatistics = 20; // Gale - Hydrinity - increase time statistics in intervals + public int updateEntityLineOfSight = 4; // Gale - Petal - reduce line of sight updates + + @PostProcess + public void postProcess() { + net.minecraft.world.entity.player.Player.increaseTimeStatisticsInterval = Math.max(1, increaseTimeStatistics); // Gale - Hydrinity - increase time statistics in intervals - store as static field for fast access + } + + } + + } + + public GameplayMechanics gameplayMechanics; + + public class GameplayMechanics extends ConfigurationPart { + + public boolean enableBookWriting = true; // Gale - Pufferfish - make book writing configurable + + } + + public Misc misc; + + public class Misc extends ConfigurationPart { + + public boolean verifyChatOrder = true; // Gale - Pufferfish - make chat order verification configurable + public int premiumAccountSlowLoginTimeout = -1; // Gale - make slow login timeout configurable + public boolean ignoreNullLegacyStructureData = false; // Gale - MultiPaper - ignore null legacy structure data + + public Keepalive keepalive; + + public class Keepalive extends ConfigurationPart { + public boolean sendMultiple = true; // Gale - Purpur - send multiple keep-alive packets + } + + // Gale start - YAPFA - last tick time - in TPS command + public LastTickTimeInTpsCommand lastTickTimeInTpsCommand; + + public class LastTickTimeInTpsCommand extends ConfigurationPart { + public boolean enabled = false; + public boolean addOversleep = false; + } + // Gale end - YAPFA - last tick time - in TPS command + + } + + public LogToConsole logToConsole; + + public class LogToConsole extends ConfigurationPart { // Gale - EMC - softly log invalid pool element errors + + public boolean invalidStatistics = true; // Gale - EMC - do not log invalid statistics + public boolean ignoredAdvancements = true; // Gale - Purpur - do not log ignored advancements + public boolean setBlockInFarChunk = true; // Gale - Purpur - do not log setBlock in far chunks + public boolean unrecognizedRecipes = false; // Gale - Purpur - do not log unrecognized recipes + public boolean legacyMaterialInitialization = false; // Gale - Purpur - do not log legacy Material initialization + public boolean nullIdDisconnections = true; // Gale - Pufferfish - do not log disconnections with null id + public boolean playerLoginLocations = true; // Gale - JettPack - make logging login location configurable + + public Chat chat; + + public class Chat extends ConfigurationPart { + public boolean emptyMessageWarning = false; // Gale - do not log empty message warnings + public boolean expiredMessageWarning = false; // Gale - do not log expired message warnings + public boolean notSecureMarker = true; // Gale - do not log Not Secure marker + } + + // Gale start - Purpur - do not log plugin library loads + public PluginLibraryLoader pluginLibraryLoader; + + public class PluginLibraryLoader extends ConfigurationPart { + + public boolean downloads = true; + public boolean startLoadLibrariesForPlugin = true; + public boolean libraryLoaded = true; + + @PostProcess + public void postProcess() { + JavaPluginLoader.logDownloads = this.downloads; + JavaPluginLoader.logStartLoadLibrariesForPlugin = this.startLoadLibrariesForPlugin; + JavaPluginLoader.logLibraryLoaded = this.libraryLoaded; + } + + } + // Gale end - Purpur - do not log plugin library loads + + // Gale start - EMC - softly log invalid pool element errors + public String invalidPoolElementErrorLogLevel = "info"; + public transient Consumer invalidPoolElementErrorStringConsumer; + + @PostProcess + public void postProcess() { + this.invalidPoolElementErrorStringConsumer = switch (this.invalidPoolElementErrorLogLevel.toLowerCase(Locale.ROOT)) { + case "none" -> $ -> {}; + case "info", "log" -> PoolElementStructurePiece.LOGGER::info; + case "warn", "warning" -> PoolElementStructurePiece.LOGGER::warn; + default -> PoolElementStructurePiece.LOGGER::error; + }; + } + // Gale end - EMC - softly log invalid pool element errors + + } +} diff --git a/leaf-server/src/main/java/org/galemc/gale/configuration/GaleRemovedConfigurations.java b/leaf-server/src/main/java/org/galemc/gale/configuration/GaleRemovedConfigurations.java new file mode 100644 index 00000000..9db32210 --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/configuration/GaleRemovedConfigurations.java @@ -0,0 +1,13 @@ +// Gale - Gale configuration + +package org.galemc.gale.configuration; + +import org.spongepowered.configurate.NodePath; + +interface GaleRemovedConfigurations { + + NodePath[] REMOVED_WORLD_PATHS = {}; + + NodePath[] REMOVED_GLOBAL_PATHS = {}; + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/configuration/GaleWorldConfiguration.java b/leaf-server/src/main/java/org/galemc/gale/configuration/GaleWorldConfiguration.java new file mode 100644 index 00000000..34cccb19 --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/configuration/GaleWorldConfiguration.java @@ -0,0 +1,143 @@ +// Gale - Gale configuration + +package org.galemc.gale.configuration; + +import com.mojang.logging.LogUtils; +import io.papermc.paper.configuration.Configuration; +import io.papermc.paper.configuration.ConfigurationPart; +import io.papermc.paper.configuration.PaperConfigurations; +import net.minecraft.resources.ResourceLocation; +import org.slf4j.Logger; +import org.spigotmc.SpigotWorldConfig; +import org.spongepowered.configurate.objectmapping.meta.Setting; + +@SuppressWarnings({"FieldCanBeLocal", "FieldMayBeFinal", "InnerClassMayBeStatic"}) +public class GaleWorldConfiguration extends ConfigurationPart { + private static final Logger LOGGER = LogUtils.getLogger(); + public static final int CURRENT_VERSION = 1; + + private transient final SpigotWorldConfig spigotConfig; + private transient final ResourceLocation worldKey; + + public GaleWorldConfiguration(SpigotWorldConfig spigotConfig, ResourceLocation worldKey) { + this.spigotConfig = spigotConfig; + this.worldKey = worldKey; + } + + public boolean isDefault() { + return this.worldKey.equals(PaperConfigurations.WORLD_DEFAULTS_KEY); + } + + @Setting(Configuration.VERSION_FIELD) + public int version = CURRENT_VERSION; + + public SmallOptimizations smallOptimizations; + + public class SmallOptimizations extends ConfigurationPart { + + public boolean saveFireworks = true; // Gale - EMC - make saving fireworks configurable + public boolean useOptimizedSheepOffspringColor = true; // Gale - carpet-fixes - optimize sheep offspring color + + // Gale start - Airplane - reduce projectile chunk loading + public MaxProjectileChunkLoads maxProjectileChunkLoads; + + public class MaxProjectileChunkLoads extends ConfigurationPart { + + public int perTick = 10; + + public PerProjectile perProjectile; + + public class PerProjectile extends ConfigurationPart { + public int max = 10; + public boolean resetMovementAfterReachLimit = false; + public boolean removeFromWorldAfterReachLimit = false; + } + + } + // Gale end - Airplane - reduce projectile chunk loading + + public ReducedIntervals reducedIntervals; + + public class ReducedIntervals extends ConfigurationPart { + + public int acquirePoiForStuckEntity = 60; // Gale - Airplane - reduce acquire POI for stuck entities + public int checkStuckInWall = 10; // Gale - Pufferfish - reduce in wall checks + public int villagerItemRepickup = 100; // Gale - EMC - reduce villager item re-pickup + + public CheckNearbyItem checkNearbyItem; + + public class CheckNearbyItem extends ConfigurationPart { + + // Gale start - EMC - reduce hopper item checks + public Hopper hopper; + + public class Hopper extends ConfigurationPart { + + public int interval = 1; + + public Minecart minecart; + + public class Minecart extends ConfigurationPart { + + public int interval = 1; + + public TemporaryImmunity temporaryImmunity; + + public class TemporaryImmunity extends ConfigurationPart { + public int duration = 100; + public int nearbyItemMaxAge = 1200; + public int checkForMinecartNearItemInterval = 20; + public boolean checkForMinecartNearItemWhileInactive = true; + public double maxItemHorizontalDistance = 24.0; + public double maxItemVerticalDistance = 4.0; + } + + } + + } + // Gale end - EMC - reduce hopper item checks + + } + + } + + public LoadChunks loadChunks; + + public class LoadChunks extends ConfigurationPart { + public boolean toSpawnPhantoms = false; // Gale - MultiPaper - don't load chunks to spawn phantoms + public boolean toActivateClimbingEntities = false; // Gale - don't load chunks to activate climbing entities + } + + } + + public GameplayMechanics gameplayMechanics; + + public class GameplayMechanics extends ConfigurationPart { + + public Fixes fixes; + + public class Fixes extends ConfigurationPart { + + public boolean broadcastCritAnimationsAsTheEntityBeingCritted = false; // Gale - MultiPaper - broadcast crit animations as the entity being critted + + // Gale start - Purpur - fix MC-238526 + @Setting("mc-238526") + public boolean mc238526 = false; + // Gale end - Purpur - fix MC-238526 + + // Gale start - Purpur - fix MC-121706 + @Setting("mc-121706") + public boolean mc121706 = false; + // Gale end - Purpur - fix MC-121706 + + } + + public boolean arrowMovementResetsDespawnCounter = true; // Gale - Purpur - make arrow movement resetting despawn counter configurable + public boolean entitiesCanRandomStrollIntoNonTickingChunks = true; // Gale - MultiPaper - prevent entities random strolling into non-ticking chunks + public double entityWakeUpDurationRatioStandardDeviation = 0.2; // Gale - variable entity wake-up duration + public boolean hideFlamesOnEntitiesWithFireResistance = false; // Gale - Slice - hide flames on entities with fire resistance + public boolean tryRespawnEnderDragonAfterEndCrystalPlace = true; // Gale - Pufferfish - make ender dragon respawn attempt after placing end crystals configurable + + } + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/version/AbstractPaperVersionFetcher.java b/leaf-server/src/main/java/org/galemc/gale/version/AbstractPaperVersionFetcher.java new file mode 100644 index 00000000..38ecc4a0 --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/version/AbstractPaperVersionFetcher.java @@ -0,0 +1,154 @@ +// Gale - branding changes - version fetcher + +package org.galemc.gale.version; + +import com.destroystokyo.paper.PaperVersionFetcher; +import com.destroystokyo.paper.VersionHistoryManager; +import com.destroystokyo.paper.util.VersionFetcher; +import com.google.common.base.Charsets; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import com.mojang.logging.LogUtils; +import io.papermc.paper.ServerBuildInfo; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; + +import javax.annotation.Nullable; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URI; +import java.util.Optional; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.TextColor.color; + +/** + * An abstract version fetcher, derived from {@link PaperVersionFetcher}. + * This class was then made to be a superclass of both {@link PaperVersionFetcher} + * and {@link GaleVersionFetcher}. + *
+ * Changes to {@link PaperVersionFetcher} are indicated by Gale marker comments. + */ +public abstract class AbstractPaperVersionFetcher implements VersionFetcher { + protected static final Logger LOGGER = LogUtils.getClassLogger(); + protected static final int DISTANCE_ERROR = -1; + protected static final int DISTANCE_UNKNOWN = -2; + protected static final ServerBuildInfo BUILD_INFO = ServerBuildInfo.buildInfo(); + + // Gale start - branding changes - version fetcher + protected final String gitHubBranchName; + protected final String downloadPage; + protected final String organizationDisplayName; + protected final String projectDisplayName; + protected final String gitHubOrganizationName; + protected final String gitHubRepoName; + + protected AbstractPaperVersionFetcher(String githubBranchName, String downloadPage, String organizationDisplayName, String projectDisplayName, String gitHubOrganizationName, String gitHubRepoName) { + this.gitHubBranchName = githubBranchName; + this.downloadPage = downloadPage; + this.organizationDisplayName = organizationDisplayName; + this.projectDisplayName = projectDisplayName; + this.gitHubOrganizationName = gitHubOrganizationName; + this.gitHubRepoName = gitHubRepoName; + } + // Gale end - branding changes - version fetcher + + @Override + public long getCacheTime() { + return 720000; + } + + @Override + public @NotNull Component getVersionMessage(final @NotNull String serverVersion) { + final Component updateMessage; + final ServerBuildInfo build = ServerBuildInfo.buildInfo(); + if (build.buildNumber().isEmpty() && build.gitCommit().isEmpty()) { + updateMessage = text("You are running a development version without access to version information", color(0xFF5300)); + } else { + updateMessage = getUpdateStatusMessage(this.gitHubOrganizationName + "/" + this.gitHubRepoName, build); // Gale - branding changes - version fetcher + } + final @Nullable Component history = this.getHistory(); + + return history != null ? Component.textOfChildren(updateMessage, Component.newline(), history) : updateMessage; + } + + // Gale start - branding changes - version fetcher + protected boolean canFetchDistanceFromSiteApi() { + return false; + } + + protected int fetchDistanceFromSiteApi(int jenkinsBuild) { + return -1; + } + // Gale end - branding changes - version fetcher + + private Component getUpdateStatusMessage(final String repo, final ServerBuildInfo build) { + int distance = DISTANCE_ERROR; + + // Gale start - branding changes - version fetcher + final Optional gitBranch = build.gitBranch(); + final Optional gitCommit = build.gitCommit(); + if (gitBranch.isPresent() && gitCommit.isPresent()) { + distance = fetchDistanceFromGitHub(repo, gitBranch.get(), gitCommit.get()); + } + // Gale end - branding changes - version fetcher + + return switch (distance) { + case DISTANCE_ERROR -> text("Error obtaining version information", NamedTextColor.YELLOW); + case 0 -> text("You are running the latest version", NamedTextColor.GREEN); + case DISTANCE_UNKNOWN -> text("Unknown version", NamedTextColor.YELLOW); + default -> text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW) + .append(Component.newline()) + .append(text("Download the new version at: ") + .append(text(this.downloadPage, NamedTextColor.GOLD) // Gale - branding changes - version fetcher + .hoverEvent(text("Click to open", NamedTextColor.WHITE)) + .clickEvent(ClickEvent.openUrl(this.downloadPage)))); // Gale - branding changes - version fetcher + }; + } + + // Contributed by Techcable in GH-65 + private static int fetchDistanceFromGitHub(final String repo, final String branch, final String hash) { + try { + final HttpURLConnection connection = (HttpURLConnection) URI.create("https://api.github.com/repos/%s/compare/%s...%s".formatted(repo, branch, hash)).toURL().openConnection(); + connection.connect(); + if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) + return DISTANCE_UNKNOWN; // Unknown commit + try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) { + final JsonObject obj = new Gson().fromJson(reader, JsonObject.class); + final String status = obj.get("status").getAsString(); + return switch (status) { + case "identical" -> 0; + case "behind" -> obj.get("behind_by").getAsInt(); + default -> DISTANCE_ERROR; + }; + } catch (final JsonSyntaxException | NumberFormatException e) { + LOGGER.error("Error parsing json from GitHub's API", e); + return DISTANCE_ERROR; + } + } catch (final IOException e) { + LOGGER.error("Error while parsing version", e); + return DISTANCE_ERROR; + } + } + + private @Nullable Component getHistory() { + final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); + if (data == null) { + return null; + } + + final @Nullable String oldVersion = data.getOldVersion(); + if (oldVersion == null) { + return null; + } + + return text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); + } +} diff --git a/leaf-server/src/main/java/org/galemc/gale/version/GaleSemanticVersion.java b/leaf-server/src/main/java/org/galemc/gale/version/GaleSemanticVersion.java new file mode 100644 index 00000000..768bcc50 --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/version/GaleSemanticVersion.java @@ -0,0 +1,38 @@ +// Gale - semantic version + +package org.galemc.gale.version; + +import org.jetbrains.annotations.NotNull; + +/** + * A holder for the Gale semantic version. + */ +public final class GaleSemanticVersion { + + private GaleSemanticVersion() { + throw new RuntimeException(); + } + + /** + * A semantic version in the format "major.minor.patch", for example "1.5.1". + * The major version is incremented when a large and overarching set of features, with a large + * and overarching common goal or effect, has been added compared to the first release with that major version. + * The minor version is incremented for each build that has a different intended feature set + * (for example, some features or part of them were added or removed). + * The patch version is incremented for small changes that do not affect the goal of any feature, + * such as bug fixes, performance improvements or changes in wording. + */ + public static final @NotNull String version = "0.6.15"; + + /** + * The "major.minor" portion of the {@link #version}. + */ + public static final @NotNull String majorMinorVersion; + + static { + int firstDotIndex = version.indexOf('.'); + int secondDotIndex = version.indexOf('.', firstDotIndex + 1); + majorMinorVersion = version.substring(0, secondDotIndex); + } + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/version/GaleVersionFetcher.java b/leaf-server/src/main/java/org/galemc/gale/version/GaleVersionFetcher.java new file mode 100644 index 00000000..13de2359 --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/version/GaleVersionFetcher.java @@ -0,0 +1,17 @@ +// Gale - branding changes - version fetcher + +package org.galemc.gale.version; + +public class GaleVersionFetcher extends AbstractPaperVersionFetcher { + + public GaleVersionFetcher() { + super( + "ver/1.21.4", + "https://github.com/Dreeam-qwq/Gale", + "GaleMC", + "Gale", + "GaleMC", + "Gale"); + } + +} diff --git a/leaf-server/src/main/java/org/galemc/gale/virtualthread/DirectVirtualThreadService.java b/leaf-server/src/main/java/org/galemc/gale/virtualthread/DirectVirtualThreadService.java new file mode 100644 index 00000000..9c08506a --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/virtualthread/DirectVirtualThreadService.java @@ -0,0 +1,50 @@ +// Gale - virtual thread support + +package org.galemc.gale.virtualthread; + +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.concurrent.ThreadFactory; + +/** + * An implementation of {@link VirtualThreadService} that can create virtual threads directly. + * + * @author Martijn Muijsers + */ +final class DirectVirtualThreadService extends VirtualThreadService { + + private DirectVirtualThreadService() { + super(); + } + + @Override + public @NotNull ThreadFactory createFactory() { + // Disabled until Minecraft requires servers to have a Java version that can read class files compiled with functionality from Java 19+ on preview / Java 21+ on stable + //throw new UnsupportedOperationException(); + return Thread.ofVirtual().factory(); + } + + @Override + public @NotNull Thread start(@NotNull Runnable task) { + // Disabled until Minecraft requires servers to have a Java version that can read class files compiled with functionality from Java 19+ on preview / Java 21+ on stable + //throw new UnsupportedOperationException(); + Objects.requireNonNull(task, "The task to start a virtual thread cannot be null"); + return Thread.ofVirtual().start(task); + } + + /** + * @return A functional {@link DirectVirtualThreadService}. + * @throws Throwable If creating virtual threads directly is not supported by the current runtime. + * This could be any {@link Throwable}, including an {@link Exception} or an {@link Error}. + */ + static @NotNull DirectVirtualThreadService create() throws Throwable { + // Disabled until Minecraft requires servers to have a Java version that can read class files compiled with functionality from Java 19+ on preview / Java 21+ on stable + //throw new UnsupportedOperationException(); + var service = new DirectVirtualThreadService(); + // Run some tests to verify + service.runTest(); + // If we end up here, it works + return service; + } +} diff --git a/leaf-server/src/main/java/org/galemc/gale/virtualthread/ReflectionVirtualThreadService.java b/leaf-server/src/main/java/org/galemc/gale/virtualthread/ReflectionVirtualThreadService.java new file mode 100644 index 00000000..ed29e01b --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/virtualthread/ReflectionVirtualThreadService.java @@ -0,0 +1,75 @@ +// Gale - virtual thread support + +package org.galemc.gale.virtualthread; + +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Method; +import java.util.Objects; +import java.util.concurrent.ThreadFactory; + +/** + * An implementation of {@link VirtualThreadService} that can create virtual threads using Java reflection. + * + * @author Martijn Muijsers + */ +final class ReflectionVirtualThreadService extends VirtualThreadService { + + /** + * The {@link Thread}#ofVirtual() method. + */ + private final @NotNull Method Thread_ofVirtual_method; + + /** + * The {@link Thread}.Builder#factory() method. + */ + private final @NotNull Method Thread_Builder_factory_method; + + /** + * The {@link Thread}.Builder#start(Runnable) method. + */ + private final @NotNull Method Thread_Builder_start_method; + + private ReflectionVirtualThreadService() throws Throwable { + this.Thread_ofVirtual_method = Objects.requireNonNull(Thread.class.getMethod("ofVirtual")); + // The Thread.Builder class + var Thread_Builder_class = Objects.requireNonNull(Class.forName("java.lang.Thread$Builder")); + this.Thread_Builder_factory_method = Objects.requireNonNull(Thread_Builder_class.getMethod("factory")); + this.Thread_Builder_start_method = Objects.requireNonNull(Thread_Builder_class.getMethod("start", Runnable.class)); + } + + @Override + public @NotNull ThreadFactory createFactory() { + try { + return (ThreadFactory) this.Thread_Builder_factory_method.invoke(this.Thread_ofVirtual_method.invoke(null)); + } catch (Exception e) { + // This should not be possible because it was tested in create() + throw new RuntimeException(e); + } + } + + @Override + public @NotNull Thread start(@NotNull Runnable task) { + Objects.requireNonNull(task, "The task to start a virtual thread cannot be null"); + try { + return (Thread) this.Thread_Builder_start_method.invoke(this.Thread_ofVirtual_method.invoke(null), task); + } catch (Exception e) { + // This should not be possible because it was tested in create() + throw new RuntimeException(e); + } + } + + /** + * @return A functional {@link ReflectionVirtualThreadService}. + * @throws Throwable If creating virtual threads via reflection is not supported by the current runtime. + * This could be any {@link Throwable}, including an {@link Exception} or an {@link Error}. + */ + static @NotNull ReflectionVirtualThreadService create() throws Throwable { + // This will already throw something if the reflection fails + var service = new ReflectionVirtualThreadService(); + // Run some tests to verify + service.runTest(); + // If we end up here, it works + return service; + } +} diff --git a/leaf-server/src/main/java/org/galemc/gale/virtualthread/VirtualThreadService.java b/leaf-server/src/main/java/org/galemc/gale/virtualthread/VirtualThreadService.java new file mode 100644 index 00000000..1814ee73 --- /dev/null +++ b/leaf-server/src/main/java/org/galemc/gale/virtualthread/VirtualThreadService.java @@ -0,0 +1,104 @@ +// Gale - virtual thread support + +package org.galemc.gale.virtualthread; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.concurrent.ThreadFactory; + +/** + * An abstract service to create virtual threads. + * + * @author Martijn Muijsers + */ +public sealed abstract class VirtualThreadService permits ReflectionVirtualThreadService, DirectVirtualThreadService { + + /** + * @return A {@link ThreadFactory} that produces virtual threads. + */ + public abstract @NotNull ThreadFactory createFactory(); + + /** + * @param task The runnable for the thread to execute. + * @return A virtual thread that has been started with the given task. + */ + public abstract @NotNull Thread start(Runnable task); + + /** + * Runs a test on the {@link #createFactory} and {@link #start} methods, + * which certainly throws some {@link Throwable} if something goes wrong. + */ + protected void runTest() throws Throwable { + // This will definitely throw something if it doesn't work + try { + this.start(() -> {}).join(); + } catch (InterruptedException ignored) {} // Except InterruptedException, we don't care about that one + try { + var thread = this.createFactory().newThread(() -> {}); + thread.start(); + thread.join(); + } catch (InterruptedException ignored) {} // Except InterruptedException, we don't care about that one + // If we end up here, it works + } + + private static boolean initialized = false; + + /** + * The {@link VirtualThreadService} for the current runtime, + * or null if virtual threads are not supported, or if not {@link #initialized} yet. + */ + private static @Nullable VirtualThreadService implementation; + + /** + * @return Whether virtual threads are supported on the current runtime. + */ + public static boolean isSupported() { + return get() != null; + } + + /** + * @return The {@link VirtualThreadService} for the current runtime, + * or null if virtual threads are not {@linkplain #isSupported() supported}. + *

+ * This method is thread-safe only after the first time it has been fully run. + */ + public static @Nullable VirtualThreadService get() { + if (!initialized) { + initialized = true; + try { + implementation = DirectVirtualThreadService.create(); + } catch (Throwable ignored) { + try { + implementation = ReflectionVirtualThreadService.create(); + } catch (Throwable ignored2) {} + } + } + return implementation; + } + + /** + * The minimum major version of Java that is known to support using virtual threads + * (although possibly behind a feature preview flag). + */ + public static final int minimumJavaMajorVersionWithFeaturePreview = 19; + + /** + * The minimum major version of Java that is known to support using virtual threads + * even without any feature preview flags. + */ + public static final int minimumJavaMajorVersionWithoutFeaturePreview = 21; + + public static int getJavaMajorVersion() { + var version = System.getProperty("java.version"); + if (version.startsWith("1.")) { + return version.charAt(2) - '0'; + } + if (version.contains("-")) { + version = version.substring(0, version.indexOf("-")); + } + + int dotIndex = version.indexOf("."); + return Integer.parseInt(dotIndex == -1 ? version : version.substring(0, dotIndex)); + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 7b78271a..4fdb2d6a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -38,5 +38,4 @@ rootProject.name = "leaf" for (name in listOf("leaf-api", "leaf-server")) { val projName = name.lowercase(Locale.ENGLISH) include(projName) - findProject(":$projName")!!.projectDir = file(name) }