├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── en_bug_report.yml │ ├── en_feature_request.yml │ ├── zh_bug_report.yml │ └── zh_feature_request.yml └── workflows │ ├── auto-update.yml │ ├── build-1214.yml │ ├── build-pr.yml │ └── publish-api.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── build-data ├── dev-imports.txt └── leaf.at ├── build.gradle.kts ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── leaf-api ├── build.gradle.kts.patch ├── paper-patches │ └── features │ │ ├── 0001-Rebrand.patch │ │ ├── 0002-Leaf-config.patch │ │ ├── 0003-Pufferfish-Sentry.patch │ │ ├── 0004-Purpur-API-Changes.patch │ │ ├── 0005-Remove-Timings.patch │ │ ├── 0006-KeYi-Player-Skull-API.patch │ │ ├── 0007-Slice-Smooth-Teleports.patch │ │ ├── 0008-Configurable-LibraryLoader-maven-repos.patch │ │ ├── 0009-Leaves-Replay-Mod-API.patch │ │ ├── 0010-Async-structure-locate-api.patch │ │ ├── 0011-PlayerInventoryOverflowEvent.patch │ │ └── 0012-Raytrace-AntiXray-SDK-integration.patch └── src │ └── main │ └── java │ └── org │ └── dreeam │ └── leaf │ └── event │ └── BlockExplosionHitEvent.java ├── leaf-archived-patches ├── removed │ ├── hardfork │ │ └── server │ │ │ ├── 0002-Decompile-fix.patch │ │ │ ├── 0025-Leaves-Disable-moved-wrongly-threshold.patch │ │ │ ├── 0044-Faster-Natural-Spawning.patch │ │ │ ├── 0049-PaperPR-Rewrite-framed-map-tracker-ticking.patch │ │ │ ├── 0061-Moonrise-Optimize-nearby-players-for-spawning-iterat.patch │ │ │ ├── 0074-Airplane-Remove-stream-in-PoiCompetitorScan.patch │ │ │ ├── 0098-Fix-MC-177381.patch │ │ │ ├── 0099-Fix-MC-150224.patch │ │ │ ├── 0103-Hide-specified-item-components-to-clients.patch │ │ │ ├── 0111-Change-max-stack-count.patch │ │ │ ├── 0112-Reduce-object-complexity-to-make-block-isValid-calls.patch │ │ │ ├── 0120-Replace-criterion-listener-map-with-optimized-collec.patch │ │ │ ├── 0124-ShreddedPaper-Don-t-block-main-thread-in-Connection-.patch │ │ │ ├── 0127-Lithium-HashedList.patch │ │ │ ├── 0143-Fix-wrong-entity-behavior-in-fluid-caused-by-inconsi.patch │ │ │ ├── 0146-Validate-recipe-display-index-before-retrieving-it.patch │ │ │ └── 0166-Save-world-async-properly.patch │ └── legacy │ │ ├── api │ │ ├── 0007-KTP-Allow-unknown-event-thread-execution.patch │ │ └── 0010-Paper-PR-Optimise-color-distance-check-in-MapPalette.patch │ │ └── server │ │ ├── 0002-Leaf-Config-v1.patch │ │ ├── 0003-Leaf-Config-v2.patch │ │ ├── 0004-Leaf-Config-legacy-converter.patch │ │ ├── 0010-Pufferfish-Entity-TTL.patch │ │ ├── 0020-KTP-Allow-unknown-event-thread-execution.patch │ │ ├── 0036-Fix-Make-log4j-compatible-with-future-release.patch │ │ ├── 0038-Leaves-Fix-vehicle-teleport-by-end-gateway.patch │ │ ├── 0039-NachoSpigot-Async-Explosion.patch │ │ ├── 0041-Petal-Multithreaded-Tracker.patch │ │ ├── 0048-Fix-keepalive-kicked-name.patch │ │ ├── 0048-PandaSpigot-Configurable-knockback.patch │ │ ├── 0051-Fix-MC-26678.patch │ │ ├── 0051-Fix-TerminalConsoleAppender-NPE-error-on-server-clos.patch │ │ ├── 0053-LinearPurpur-Add-Linear-region-format.patch │ │ ├── 0054-LinearPurpur-Just-remove-all-locks-on-region-files.patch │ │ ├── 0056-Fix-MC-2025.patch │ │ ├── 0057-SparklyPaper-Cache-coordinate-key-used-for-nearby-pl.patch │ │ ├── 0060-Moonrise-Bitstorage-optimisations.patch │ │ ├── 0062-Moonrise-block-counting-optimisations.patch │ │ ├── 0063-Moonrise-Optimise-BiomeManager-getFiddle.patch │ │ ├── 0063-Redirect-to-Gale-s-method-to-fix-plugin-incompatibil.patch │ │ ├── 0064-Moonrise-Do-not-send-chunk-radius-packet-from-Player.patch │ │ ├── 0065-Fix-MC-249136-lag-when-attempting-to-locate-a-buried.patch │ │ ├── 0065-Moonrise-Add-direct-lookup-by-chunk-for-NearbyPlayer.patch │ │ ├── 0066-Moonrise-Optimise-checkInsideBlocks.patch │ │ ├── 0067-Moonrise-Avoid-streams-for-block-retrieval-in-Entity.patch │ │ ├── 0068-Block-log4j-rce-exploit-in-chat.patch │ │ ├── 0068-Fix-MC-172047.patch │ │ ├── 0068-Moonrise-Optimise-countEntries-for-low-size-SimpleBi.patch │ │ ├── 0069-Fix-NPE-during-creating-GUI-graph.patch │ │ ├── 0069-Moonrise-fluid-method-optimisations.patch │ │ ├── 0070-Configurable-bamboo-collision.patch │ │ ├── 0070-Moonrise-optimise-palette-reads.patch │ │ ├── 0075-Use-a-shadow-fork-that-supports-Java-21.patch │ │ ├── 0081-Implement-Noisium.patch │ │ ├── 0083-Ignore-terminal-provider-warning.patch │ │ ├── 0083-Tracking-Optimize-Reduce-expensive-iteration.patch │ │ ├── 0084-Fix-console-freeze-above-JAVA-22.patch │ │ ├── 0085-Fix-console-output-display-on-Pterodactyl-panel.patch │ │ ├── 0090-Remove-stream-in-RecipeManager-getRecipeFor.patch │ │ ├── 0093-Optimize-check-nearby-fire-or-lava-on-entity-move.patch │ │ ├── 0094-Fix-Nova-compatibility.patch │ │ ├── 0102-Remove-stream-in-PlacedFeature.patch │ │ ├── 0110-Fix-MC-183518.patch │ │ ├── 0121-Paper-PR-Reduce-work-done-in-CraftMapCanvas.drawImag.patch │ │ ├── 0125-Paper-Improve-performance-of-RecipeManager-removeRec.patch │ │ ├── 0126-Paper-Fix-move-to-jline-terminal-ffm-on-java-22-and-.patch │ │ ├── 0150-Use-MCUtil.asyncExecutor-for-MAIN_WORKER_EXECUTOR.patch │ │ └── 0151-Better-inline-world-height.patch ├── ver │ └── README.md └── work │ └── server │ ├── 0042-Optimize-Minecart-collisions.patch │ └── 0110-Cache-ItemStack-max-stack-size.patch ├── leaf-server ├── build.gradle.kts.patch ├── gale-patches │ └── features │ │ ├── 0001-Rebrand.patch │ │ ├── 0002-Leaf-Commands.patch │ │ ├── 0003-Fix-Pufferfish-and-Purpur-patches.patch │ │ ├── 0004-KeYi-Disable-arrow-despawn-counter-by-default.patch │ │ └── 0005-Reduce-active-items-finding-hopper-nearby-check.patch ├── minecraft-patches │ └── features │ │ ├── 0001-Rebrand.patch │ │ ├── 0002-Leaf-config.patch │ │ ├── 0003-Leaf-Commands.patch │ │ ├── 0004-Pufferfish-Optimize-mob-spawning.patch │ │ ├── 0005-Pufferfish-Dynamic-Activation-of-Brain.patch │ │ ├── 0006-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch │ │ ├── 0007-Purpur-Server-Minecraft-Changes.patch │ │ ├── 0008-Fix-Pufferfish-and-Purpur-patches.patch │ │ ├── 0009-Purpur-Configurable-server-mod-name.patch │ │ ├── 0010-Configurable-server-GUI-name.patch │ │ ├── 0011-Remove-vanilla-username-check.patch │ │ ├── 0012-Remove-Spigot-check-for-broken-BungeeCord-configurat.patch │ │ ├── 0013-Remove-UseItemOnPacket-Too-Far-check.patch │ │ ├── 0014-Remove-change-non-editable-sign-warning.patch │ │ ├── 0015-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch │ │ ├── 0016-Carpet-Fixes-Optimized-getBiome-method.patch │ │ ├── 0017-Carpet-Fixes-Use-optimized-RecipeManager.patch │ │ ├── 0018-Akarin-Save-Json-list-asynchronously.patch │ │ ├── 0019-Slice-Smooth-Teleports.patch │ │ ├── 0020-Parchment-Make-FixLight-use-action-bar.patch │ │ ├── 0021-Leaves-Protocol-Core.patch │ │ ├── 0022-Leaves-Jade-Protocol.patch │ │ ├── 0023-Leaves-Xaero-Map-Protocol.patch │ │ ├── 0024-Leaves-Syncmatica-Protocol.patch │ │ ├── 0025-Leaves-Replay-Mod-API.patch │ │ ├── 0026-Petal-Async-Pathfinding.patch │ │ ├── 0027-Petal-reduce-work-done-by-game-event-system.patch │ │ ├── 0028-Reduce-canSee-work.patch │ │ ├── 0029-Fix-sprint-glitch.patch │ │ ├── 0030-Configurable-movement-speed-of-more-entities.patch │ │ ├── 0031-Faster-sequencing-of-futures-for-chunk-structure-gen.patch │ │ ├── 0032-Reduce-active-items-finding-hopper-nearby-check.patch │ │ ├── 0033-Linear-region-file-format.patch │ │ ├── 0034-Plazma-Add-some-missing-Pufferfish-configurations.patch │ │ ├── 0035-Plazma-Add-missing-purpur-configuration-options.patch │ │ ├── 0036-SparklyPaper-Skip-distanceToSqr-call-in-ServerEntity.patch │ │ ├── 0037-SparklyPaper-Skip-MapItem-update-if-the-map-does-not.patch │ │ ├── 0038-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch │ │ ├── 0039-SparklyPaper-Optimize-canSee-checks.patch │ │ ├── 0040-SparklyPaper-Allow-throttling-hopper-checks-if-the-t.patch │ │ ├── 0041-Polpot-Make-egg-and-snowball-can-knockback-player.patch │ │ ├── 0042-Redirect-vanilla-getProfiler-to-inactive-in-PathNavi.patch │ │ ├── 0043-Remove-useless-creating-stats-json-bases-on-player-n.patch │ │ ├── 0044-Improve-Purpur-AFK-system.patch │ │ ├── 0045-Virtual-thread-for-chat-executor.patch │ │ ├── 0046-Virtual-thread-for-user-authenticator.patch │ │ ├── 0047-Mirai-Configurable-chat-message-signatures.patch │ │ ├── 0048-Cache-player-profileResult.patch │ │ ├── 0049-Matter-Secure-Seed.patch │ │ ├── 0050-Matter-Secure-Seed-command.patch │ │ ├── 0051-Faster-random-generator.patch │ │ ├── 0052-Don-t-save-primed-tnt-entity.patch │ │ ├── 0053-Don-t-save-falling-block-entity.patch │ │ ├── 0054-Configurable-connection-message.patch │ │ ├── 0055-Configurable-unknown-command-message.patch │ │ ├── 0056-Remove-stream-in-BlockBehaviour-cache-blockstate.patch │ │ ├── 0057-Remove-stream-in-entity-visible-effects-filter.patch │ │ ├── 0058-Remove-stream-and-double-iteration-in-enough-deep-sl.patch │ │ ├── 0059-Remove-stream-in-trial-spawner-ticking.patch │ │ ├── 0060-Remove-stream-in-Brain.patch │ │ ├── 0061-Remove-stream-in-BehaviorUtils.patch │ │ ├── 0062-Remove-stream-in-YieldJobSite.patch │ │ ├── 0063-Remove-stream-in-PlayerSensor.patch │ │ ├── 0064-Remove-stream-in-GolemSensor.patch │ │ ├── 0065-Remove-stream-in-GateBehavior.patch │ │ ├── 0066-Remove-stream-in-updateFluidOnEyes.patch │ │ ├── 0067-Remove-stream-in-matchingSlot.patch │ │ ├── 0068-Replace-Entity-active-effects-map-with-optimized-col.patch │ │ ├── 0069-Replace-criterion-map-with-optimized-collection.patch │ │ ├── 0070-Replace-brain-maps-with-optimized-collection.patch │ │ ├── 0071-Reduce-worldgen-allocations.patch │ │ ├── 0072-Use-caffeine-cache-for-kickPermission-instead-of-usi.patch │ │ ├── 0073-Do-not-place-player-if-the-server-is-full.patch │ │ ├── 0074-Fix-MC-65198.patch │ │ ├── 0075-Fix-MC-200418.patch │ │ ├── 0076-Fix-MC-119417.patch │ │ ├── 0077-Fix-MC-223153.patch │ │ ├── 0078-Configurable-player-knockback-zombie.patch │ │ ├── 0079-Hide-specified-item-components.patch │ │ ├── 0080-Paper-PR-Skip-AI-during-inactive-ticks-for-non-aware.patch │ │ ├── 0081-Paper-PR-Prevent-zombie-reinforcements-loading-chunk.patch │ │ ├── 0082-PaperPR-Fix-some-beacon-event-issues.patch │ │ ├── 0083-Dont-send-useless-entity-packets.patch │ │ ├── 0084-Don-t-spawn-if-lastSpawnState-is-null.patch │ │ ├── 0085-Multithreaded-Tracker.patch │ │ ├── 0086-Nitori-Async-playerdata-saving.patch │ │ ├── 0087-Optimize-nearby-alive-players-for-spawning.patch │ │ ├── 0088-Cache-blockstate-cache-array.patch │ │ ├── 0089-Asynchronous-locator.patch │ │ ├── 0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch │ │ ├── 0091-Further-reduce-memory-footprint-of-CompoundTag.patch │ │ ├── 0092-Optimize-Entity-distanceToSqr.patch │ │ ├── 0093-EMC-Don-t-use-snapshots-for-TileEntity-getOwner.patch │ │ ├── 0094-Cache-tile-entity-position.patch │ │ ├── 0095-TT20-Lag-compensation.patch │ │ ├── 0096-C2ME-Reduce-Allocations.patch │ │ ├── 0097-Lithium-Skip-unnecessary-calculations-if-player-is-n.patch │ │ ├── 0098-Lithium-fast-util.patch │ │ ├── 0099-Lithium-cached-iterate-outwards.patch │ │ ├── 0100-Smooth-teleport-config.patch │ │ ├── 0101-Use-faster-and-thread-safe-ban-list-date-format-pars.patch │ │ ├── 0102-Collect-then-startEachNonRunningBehavior-in-Brain.patch │ │ ├── 0103-Lithium-equipment-tracking.patch │ │ ├── 0104-C2ME-Optimize-world-gen-math.patch │ │ ├── 0105-Cache-chunk-key.patch │ │ ├── 0106-Cache-random-tick-block-status.patch │ │ ├── 0107-Cache-part-of-canHoldFluid-result.patch │ │ ├── 0108-Configurable-tripwire-dupe.patch │ │ ├── 0109-PaperPR-Fix-MC-117075-Block-Entities-Unload-Lag-Spik.patch │ │ ├── 0110-Sepals-Rearrange-the-attackable-conditions.patch │ │ ├── 0111-SparklyPaper-Skip-dirty-stats-copy-when-requesting-p.patch │ │ ├── 0112-SparklyPaper-Reset-dirty-flag-when-loading-maps-from.patch │ │ ├── 0113-Optimize-checking-nearby-players-for-spawning.patch │ │ ├── 0114-Cache-supporting-block-check.patch │ │ ├── 0115-Avoid-useless-deque-clear-on-LevelTicks-cleanupAfter.patch │ │ ├── 0116-Replace-brain-activity-maps-with-optimized-collectio.patch │ │ ├── 0117-Remove-stream-in-villagers.patch │ │ ├── 0118-Optimize-baby-villager-sensor.patch │ │ ├── 0119-Only-player-pushable.patch │ │ ├── 0120-Remove-iterators-from-Inventory-contains.patch │ │ ├── 0121-Alternative-Brain-Behaviour.patch │ │ ├── 0122-Cache-eligible-players-for-despawn-checks.patch │ │ ├── 0123-Slightly-optimise-getNearestPlayer.patch │ │ ├── 0124-Use-ensureCapacity-to-pre-populate-the-size-of-ticki.patch │ │ ├── 0125-Directly-use-the-pre-filtered-ticking-chunks-list-as.patch │ │ ├── 0126-Bulk-writes-to-writeLongArray-during-chunk-loading.patch │ │ ├── 0127-Improve-sorting-in-SortedArraySet.patch │ │ ├── 0128-Make-removeIf-slightly-faster.patch │ │ ├── 0129-Optimize-LinearPalette.patch │ │ ├── 0130-Slightly-optimized-VarInt-write.patch │ │ ├── 0131-Rewrite-ClientboundLightUpdatePacketData.patch │ │ ├── 0132-Async-chunk-send.patch │ │ ├── 0133-Spawner-Configurations.patch │ │ ├── 0134-SparklyPaper-Parallel-world-ticking.patch │ │ ├── 0135-SparklyPaper-Track-each-world-MSPT.patch │ │ ├── 0136-PaperPR-Fix-cancelled-Projectile-Events-still-consum.patch │ │ ├── 0137-Optimize-SetLookAndInteract-and-NearestVisibleLiving.patch │ │ ├── 0138-Remove-streams-on-InsideBrownianWalk.patch │ │ ├── 0139-Use-BFS-on-getSlopeDistance.patch │ │ ├── 0140-Paper-PR-Throttle-failed-spawn-attempts.patch │ │ ├── 0141-Improve-BlockEntity-ticking-isRemoved-check.patch │ │ ├── 0142-Raytrace-AntiXray-SDK-integration.patch │ │ ├── 0143-Optimize-addOrUpdateTransientModifier.patch │ │ ├── 0144-Optimize-ContextMap.create.patch │ │ ├── 0145-Micro-optimizations-for-random-tick.patch │ │ ├── 0146-Remove-streams-on-updateConnectedPlayersWithinRange.patch │ │ ├── 0147-Remove-streams-on-PlayerDetector.patch │ │ ├── 0148-Use-direct-iteration-on-Sensing.tick.patch │ │ ├── 0149-Optimise-non-flush-packet-sending.patch │ │ ├── 0150-Prevent-double-chunk-retrieving-in-entity-fluid-push.patch │ │ ├── 0151-Null-handling-on-MultifaceSpreader.patch │ │ ├── 0152-More-virtual-threads.patch │ │ ├── 0153-Async-target-finding.patch │ │ ├── 0154-Optimize-ThreadedTicketLevelPropagator.patch │ │ ├── 0155-Optimise-MobEffectUtil-getDigSpeedAmplification.patch │ │ ├── 0156-Optimise-chunkUnloads.patch │ │ ├── 0157-Optimize-BlockEntityType-isValid.patch │ │ ├── 0158-PaperPR-Add-ticket-on-player-join-to-avoid-chunk-loa.patch │ │ ├── 0159-PaperPR-Fix-save-load-NaN-Entity-Motion.patch │ │ ├── 0160-PaperPR-Fix-unnecessary-map-data-saves.patch │ │ ├── 0161-Sakura-Optimise-check-inside-blocks-and-traverse-blo.patch │ │ ├── 0162-Sakura-copy-EntityList-implementation-to-BasicEntity.patch │ │ ├── 0163-Protocol-Core.patch │ │ ├── 0164-Reduce-PlayerChunk-Updates.patch │ │ ├── 0165-Async-switch-connection-state.patch │ │ ├── 0166-Optimise-BlockEntities-tickersInLevel.patch │ │ ├── 0167-Pluto-Check-if-the-cactus-can-even-survive-being-pla.patch │ │ ├── 0168-Flush-location-while-knockback.patch │ │ ├── 0169-Only-tick-items-at-hand.patch │ │ ├── 0170-Smart-sort-items-in-NearestItemSensor.patch │ │ ├── 0171-Optimise-player-movement-checks.patch │ │ ├── 0172-Remove-streams-in-MobSensor.patch │ │ ├── 0173-Remove-streams-in-TemptingSensor.patch │ │ ├── 0174-Use-HashedList-on-WeightedRandomList.patch │ │ ├── 0175-Add-configurable-death-item-drop-knockback-settings.patch │ │ ├── 0176-Optimize-getScaledTrackingDistance.patch │ │ ├── 0177-Optimize-SynchedEntityData-packDirty.patch │ │ ├── 0178-Optimize-isEyeInFluid.patch │ │ ├── 0179-Paw-optimization.patch │ │ ├── 0180-Cache-block-path-type.patch │ │ ├── 0181-optimize-getEntityStatus.patch │ │ ├── 0182-Rail-Optimization-optimized-PoweredRailBlock-logic.patch │ │ ├── 0183-optimise-ChunkGenerator-getMobsAt.patch │ │ ├── 0184-optimise-getBiome.patch │ │ ├── 0185-optimize-mob-spawning.patch │ │ ├── 0186-optimize-structure-map.patch │ │ ├── 0187-throttle-mob-spawning.patch │ │ ├── 0188-preload-mob-spawning-position.patch │ │ ├── 0189-Add-BlockExplosionHitEvent.patch │ │ └── 0190-Old-Blast-Protection-explosion-knockback.patch ├── paper-patches │ └── features │ │ ├── 0001-Rebrand.patch │ │ ├── 0002-Leaf-Bootstrap.patch │ │ ├── 0003-Leaf-Commands.patch │ │ ├── 0004-Pufferfish-Optimize-mob-spawning.patch │ │ ├── 0005-Purpur-Server-Paper-Changes.patch │ │ ├── 0006-Fix-Pufferfish-and-Purpur-patches.patch │ │ ├── 0007-Remove-Timings.patch │ │ ├── 0008-KeYi-Player-Skull-API.patch │ │ ├── 0009-Slice-Smooth-Teleports.patch │ │ ├── 0010-Leaves-Protocol-Core.patch │ │ ├── 0011-Leaves-Replay-Mod-API.patch │ │ ├── 0012-Skip-event-if-no-listeners.patch │ │ ├── 0013-SparklyPaper-Skip-EntityScheduler-s-executeTick-chec.patch │ │ ├── 0014-SparklyPaper-Optimize-canSee-checks.patch │ │ ├── 0015-Including-5s-in-getTPS.patch │ │ ├── 0016-Don-t-throw-exception-on-missing-ResourceKey-value.patch │ │ ├── 0017-Virtual-Thread-for-async-scheduler.patch │ │ ├── 0018-Mirai-Configurable-chat-message-signatures.patch │ │ ├── 0019-Matter-Secure-Seed.patch │ │ ├── 0020-Faster-random-generator.patch │ │ ├── 0021-Configurable-unknown-command-message.patch │ │ ├── 0022-Replace-world-map-with-optimized-collection.patch │ │ ├── 0023-Cache-CraftEntityType-minecraftToBukkit-convert.patch │ │ ├── 0024-Multithreaded-Tracker.patch │ │ ├── 0025-Asynchronous-locator.patch │ │ ├── 0026-EMC-Don-t-use-snapshots-for-acquiring-blockstate.patch │ │ ├── 0027-Faster-CraftServer-getworlds-list-creation.patch │ │ ├── 0028-Cache-chunk-key.patch │ │ ├── 0029-Async-structure-locate-api.patch │ │ ├── 0030-PlayerInventoryOverflowEvent.patch │ │ ├── 0031-SparklyPaper-Parallel-world-ticking.patch │ │ ├── 0032-Paper-PR-Throttle-failed-spawn-attempts.patch │ │ ├── 0033-Async-playerdata-saving.patch │ │ ├── 0034-PaperPR-Fix-save-load-NaN-Entity-Motion.patch │ │ ├── 0035-PaperPR-Fix-unnecessary-map-data-saves.patch │ │ ├── 0036-Async-chunk-send.patch │ │ ├── 0037-Optimise-player-movement-checks.patch │ │ ├── 0038-Paw-optimization.patch │ │ ├── 0039-optimise-ReferenceList.patch │ │ ├── 0040-cache-getBiome.patch │ │ └── 0041-Paper-Optimise-CraftWorld-getLoadedChunks.patch └── src │ └── main │ └── java │ ├── gg │ └── pufferfish │ │ └── pufferfish │ │ ├── sentry │ │ ├── PufferfishSentryAppender.java │ │ └── SentryManager.java │ │ └── util │ │ ├── AsyncExecutor.java │ │ └── IterableWrapper.java │ ├── net │ └── caffeinemc │ │ └── mods │ │ └── lithium │ │ └── common │ │ ├── entity │ │ └── EquipmentEntity.java │ │ └── util │ │ └── change_tracking │ │ ├── ChangePublisher.java │ │ └── ChangeSubscriber.java │ ├── org │ ├── dreeam │ │ └── leaf │ │ │ ├── LeafBootstrap.java │ │ │ ├── async │ │ │ ├── AsyncPlayerDataSaving.java │ │ │ ├── ShutdownExecutors.java │ │ │ ├── ai │ │ │ │ ├── AsyncGoalExecutor.java │ │ │ │ ├── AsyncGoalThread.java │ │ │ │ ├── VWaker.java │ │ │ │ └── Waker.java │ │ │ ├── chunk │ │ │ │ ├── AsyncChunkSend.java │ │ │ │ └── AsyncChunkSendThread.java │ │ │ ├── locate │ │ │ │ └── AsyncLocator.java │ │ │ ├── path │ │ │ │ ├── AsyncPath.java │ │ │ │ ├── AsyncPathProcessor.java │ │ │ │ ├── NodeEvaluatorCache.java │ │ │ │ ├── NodeEvaluatorFeatures.java │ │ │ │ ├── NodeEvaluatorGenerator.java │ │ │ │ ├── NodeEvaluatorType.java │ │ │ │ ├── PathProcessState.java │ │ │ │ └── PathfindTaskRejectPolicy.java │ │ │ ├── tracker │ │ │ │ └── MultithreadedTracker.java │ │ │ └── world │ │ │ │ ├── PWTEventScheduler.java │ │ │ │ ├── ReadOperationType.java │ │ │ │ ├── SparklyPaperServerLevelTickExecutorThreadFactory.java │ │ │ │ └── WorldReadRequest.java │ │ │ ├── command │ │ │ ├── LeafCommand.java │ │ │ ├── LeafCommands.java │ │ │ ├── LeafSubcommand.java │ │ │ ├── PermissionedLeafSubcommand.java │ │ │ └── subcommands │ │ │ │ ├── MSPTCommand.java │ │ │ │ ├── ReloadCommand.java │ │ │ │ └── VersionCommand.java │ │ │ ├── config │ │ │ ├── ConfigModules.java │ │ │ ├── EnumConfigCategory.java │ │ │ ├── LeafConfig.java │ │ │ ├── LeafGlobalConfig.java │ │ │ ├── annotations │ │ │ │ ├── DoNotLoad.java │ │ │ │ ├── Experimental.java │ │ │ │ └── HotReloadUnsupported.java │ │ │ └── modules │ │ │ │ ├── async │ │ │ │ ├── AsyncChunkSend.java │ │ │ │ ├── AsyncLocator.java │ │ │ │ ├── AsyncMobSpawning.java │ │ │ │ ├── AsyncPathfinding.java │ │ │ │ ├── AsyncPlayerDataSave.java │ │ │ │ ├── AsyncTargetFinding.java │ │ │ │ ├── MultithreadedTracker.java │ │ │ │ └── SparklyPaperParallelWorldTicking.java │ │ │ │ ├── fixes │ │ │ │ └── DontPlacePlayerIfFull.java │ │ │ │ ├── gameplay │ │ │ │ ├── AfkCommand.java │ │ │ │ ├── ConfigurableInventoryOverflowEvent.java │ │ │ │ ├── ConfigurableMaxUseItemDistance.java │ │ │ │ ├── ConfigurableTripWireDupe.java │ │ │ │ ├── DeathItemDropKnockback.java │ │ │ │ ├── HideItemComponent.java │ │ │ │ ├── Knockback.java │ │ │ │ ├── OnlyPlayerPushable.java │ │ │ │ ├── SmoothTeleport.java │ │ │ │ ├── SpawnerSettings.java │ │ │ │ └── UseSpigotItemMergingMech.java │ │ │ │ ├── misc │ │ │ │ ├── Cache.java │ │ │ │ ├── ConnectionMessage.java │ │ │ │ ├── Including5sIngetTPS.java │ │ │ │ ├── LagCompensation.java │ │ │ │ ├── RegionFormatConfig.java │ │ │ │ ├── RemoveChangeNonEditableSignWarning.java │ │ │ │ ├── RemoveSpigotCheckBungee.java │ │ │ │ ├── RemoveVanillaUsernameCheck.java │ │ │ │ ├── SecureSeed.java │ │ │ │ ├── SentryDSN.java │ │ │ │ ├── ServerBrand.java │ │ │ │ └── UnknownCommandMessage.java │ │ │ │ ├── network │ │ │ │ ├── AlternativeJoin.java │ │ │ │ ├── ChatMessageSignature.java │ │ │ │ ├── OptimizeNonFlushPacketSending.java │ │ │ │ └── ProtocolSupport.java │ │ │ │ └── opt │ │ │ │ ├── BrainRunningBehaviorCacheUpdate.java │ │ │ │ ├── CheckSurvivalBeforeGrowth.java │ │ │ │ ├── DontSaveEntity.java │ │ │ │ ├── DynamicActivationofBrain.java │ │ │ │ ├── EnableCachedMTBEntityTypeConvert.java │ │ │ │ ├── EyeFluidCache.java │ │ │ │ ├── FastRNG.java │ │ │ │ ├── FasterStructureGenFutureSequencing.java │ │ │ │ ├── OptimiseBlockEntities.java │ │ │ │ ├── OptimizeBiome.java │ │ │ │ ├── OptimizeItemTicking.java │ │ │ │ ├── OptimizePlayerMovementProcessing.java │ │ │ │ ├── OptimizedPoweredRails.java │ │ │ │ ├── PreloadNaturalMobSpawning.java │ │ │ │ ├── ReduceChunkSourceUpdates.java │ │ │ │ ├── ReduceUselessPackets.java │ │ │ │ ├── SkipAIForNonAwareMob.java │ │ │ │ ├── SkipMapItemDataUpdates.java │ │ │ │ ├── ThrottleHopperWhenFull.java │ │ │ │ ├── ThrottleInactiveGoalSelectorTick.java │ │ │ │ ├── ThrottleNaturalMobSpawning.java │ │ │ │ ├── TileEntitySnapshotCreation.java │ │ │ │ ├── VT4BukkitScheduler.java │ │ │ │ ├── VT4ChatExecutor.java │ │ │ │ ├── VT4DownloadPool.java │ │ │ │ ├── VT4ProfileExecutor.java │ │ │ │ └── VT4UserAuthenticator.java │ │ │ ├── misc │ │ │ └── LagCompensation.java │ │ │ ├── protocol │ │ │ ├── DoABarrelRollPackets.java │ │ │ ├── DoABarrelRollProtocol.java │ │ │ ├── LeafCustomPayload.java │ │ │ ├── Protocol.java │ │ │ └── Protocols.java │ │ │ ├── util │ │ │ ├── FastBitRadixSort.java │ │ │ ├── cache │ │ │ │ ├── CachedOrNewBitsGetter.java │ │ │ │ ├── IterateOutwardsCache.java │ │ │ │ └── LongList2BlockPosMutableIterable.java │ │ │ ├── item │ │ │ │ └── ItemStackStripper.java │ │ │ ├── list │ │ │ │ ├── BlockEntityTickersList.java │ │ │ │ └── HashedReferenceList.java │ │ │ ├── map │ │ │ │ ├── AttributeInstanceArrayMap.java │ │ │ │ ├── AttributeInstanceSet.java │ │ │ │ ├── BlockPosIterator.java │ │ │ │ ├── ConcurrentLongHashSet.java │ │ │ │ └── StringCanonizingOpenHashMap.java │ │ │ ├── math │ │ │ │ └── random │ │ │ │ │ └── FasterRandomSource.java │ │ │ └── queue │ │ │ │ └── SpscIntQueue.java │ │ │ ├── version │ │ │ └── LeafVersionFetcher.java │ │ │ └── world │ │ │ ├── biome │ │ │ └── PositionalBiomeGetter.java │ │ │ └── block │ │ │ └── OptimizedPoweredRails.java │ ├── leavesmc │ │ └── leaves │ │ │ ├── LeavesLogger.java │ │ │ ├── bot │ │ │ └── BotStatsCounter.java │ │ │ ├── entity │ │ │ ├── CraftPhotographer.java │ │ │ └── CraftPhotographerManager.java │ │ │ ├── protocol │ │ │ ├── AppleSkinProtocol.java │ │ │ ├── AsteorBarProtocol.java │ │ │ ├── ChatImageProtocol.java │ │ │ ├── XaeroMapProtocol.java │ │ │ ├── chatimage │ │ │ │ └── ChatImageIndex.java │ │ │ ├── core │ │ │ │ ├── LeavesCustomPayload.java │ │ │ │ ├── LeavesProtocol.java │ │ │ │ ├── LeavesProtocolManager.java │ │ │ │ ├── ProtocolHandler.java │ │ │ │ └── ProtocolUtils.java │ │ │ ├── jade │ │ │ │ ├── JadeProtocol.java │ │ │ │ ├── accessor │ │ │ │ │ ├── Accessor.java │ │ │ │ │ ├── AccessorImpl.java │ │ │ │ │ ├── BlockAccessor.java │ │ │ │ │ ├── BlockAccessorImpl.java │ │ │ │ │ ├── EntityAccessor.java │ │ │ │ │ └── EntityAccessorImpl.java │ │ │ │ ├── payload │ │ │ │ │ ├── ClientHandshakePayload.java │ │ │ │ │ ├── ReceiveDataPayload.java │ │ │ │ │ ├── RequestBlockPayload.java │ │ │ │ │ ├── RequestEntityPayload.java │ │ │ │ │ └── ServerHandshakePayload.java │ │ │ │ ├── provider │ │ │ │ │ ├── IJadeProvider.java │ │ │ │ │ ├── IServerDataProvider.java │ │ │ │ │ ├── IServerExtensionProvider.java │ │ │ │ │ ├── ItemStorageExtensionProvider.java │ │ │ │ │ ├── ItemStorageProvider.java │ │ │ │ │ ├── StreamServerDataProvider.java │ │ │ │ │ ├── block │ │ │ │ │ │ ├── BeehiveProvider.java │ │ │ │ │ │ ├── BrewingStandProvider.java │ │ │ │ │ │ ├── CampfireProvider.java │ │ │ │ │ │ ├── ChiseledBookshelfProvider.java │ │ │ │ │ │ ├── CommandBlockProvider.java │ │ │ │ │ │ ├── FurnaceProvider.java │ │ │ │ │ │ ├── HopperLockProvider.java │ │ │ │ │ │ ├── JukeboxProvider.java │ │ │ │ │ │ ├── LecternProvider.java │ │ │ │ │ │ ├── MobSpawnerCooldownProvider.java │ │ │ │ │ │ ├── ObjectNameProvider.java │ │ │ │ │ │ └── RedstoneProvider.java │ │ │ │ │ └── entity │ │ │ │ │ │ ├── AnimalOwnerProvider.java │ │ │ │ │ │ ├── MobBreedingProvider.java │ │ │ │ │ │ ├── MobGrowthProvider.java │ │ │ │ │ │ ├── NextEntityDropProvider.java │ │ │ │ │ │ ├── PetArmorProvider.java │ │ │ │ │ │ ├── StatusEffectsProvider.java │ │ │ │ │ │ └── ZombieVillagerProvider.java │ │ │ │ ├── tool │ │ │ │ │ ├── ShearsToolHandler.java │ │ │ │ │ ├── SimpleToolHandler.java │ │ │ │ │ └── ToolHandler.java │ │ │ │ └── util │ │ │ │ │ ├── CommonUtil.java │ │ │ │ │ ├── HierarchyLookup.java │ │ │ │ │ ├── IHierarchyLookup.java │ │ │ │ │ ├── ItemCollector.java │ │ │ │ │ ├── ItemIterator.java │ │ │ │ │ ├── JadeCodec.java │ │ │ │ │ ├── LootTableMineableCollector.java │ │ │ │ │ ├── PairHierarchyLookup.java │ │ │ │ │ ├── PriorityStore.java │ │ │ │ │ ├── ViewGroup.java │ │ │ │ │ └── WrappedHierarchyLookup.java │ │ │ └── syncmatica │ │ │ │ ├── CommunicationManager.java │ │ │ │ ├── Feature.java │ │ │ │ ├── FeatureSet.java │ │ │ │ ├── FileStorage.java │ │ │ │ ├── LocalLitematicState.java │ │ │ │ ├── MessageType.java │ │ │ │ ├── PacketType.java │ │ │ │ ├── PlayerIdentifier.java │ │ │ │ ├── PlayerIdentifierProvider.java │ │ │ │ ├── ServerPlacement.java │ │ │ │ ├── ServerPosition.java │ │ │ │ ├── SubRegionData.java │ │ │ │ ├── SubRegionPlacementModification.java │ │ │ │ ├── SyncmaticManager.java │ │ │ │ ├── SyncmaticaPayload.java │ │ │ │ ├── SyncmaticaProtocol.java │ │ │ │ └── exchange │ │ │ │ ├── AbstractExchange.java │ │ │ │ ├── DownloadExchange.java │ │ │ │ ├── Exchange.java │ │ │ │ ├── ExchangeTarget.java │ │ │ │ ├── FeatureExchange.java │ │ │ │ ├── ModifyExchangeServer.java │ │ │ │ ├── UploadExchange.java │ │ │ │ └── VersionHandshakeServer.java │ │ │ ├── replay │ │ │ ├── DigestOutputStream.java │ │ │ ├── RecordMetaData.java │ │ │ ├── Recorder.java │ │ │ ├── RecorderOption.java │ │ │ ├── ReplayFile.java │ │ │ ├── ReplayMarker.java │ │ │ ├── ServerPhotographer.java │ │ │ └── ServerPhotographerGameMode.java │ │ │ └── util │ │ │ └── UUIDSerializer.java │ ├── purpurmc │ │ └── purpur │ │ │ └── command │ │ │ └── AFKCommand.java │ └── stupidcraft │ │ └── linearpaper │ │ └── region │ │ ├── EnumRegionFileExtension.java │ │ ├── IRegionFile.java │ │ ├── IRegionFileFactory.java │ │ └── LinearRegionFile.java │ └── su │ └── plo │ └── matter │ ├── Globals.java │ ├── Hashing.java │ └── WorldgenCryptoRandom.java ├── licenses ├── AGPL-3.0.txt ├── GPL-3.0.txt ├── LGPL-3.0.txt └── MIT.txt ├── public └── image │ ├── JiankeServer.jpg │ ├── leaf_banner.png │ └── leaf_logo.png ├── scripts ├── prepareRelease.sh └── upstreamCommit.sh └── settings.gradle.kts /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.java] 2 | charset=utf-8 3 | end_of_line=lf 4 | insert_final_newline=true 5 | indent_style=space 6 | indent_size=4 7 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # Set the default behavior, in case people don't have core.autocrlf set. 5 | * text=auto 6 | 7 | # Linux start script should use lf 8 | /gradlew text eol=lf 9 | 10 | # These are Windows script files and should use crlf 11 | *.bat text eol=crlf 12 | 13 | # Binary files should be left untouched 14 | *.jar binary 15 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | open_collective: Winds-Studio 2 | custom: ["https://afdian.com/a/Dreeam"] 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Discord 4 | url: https://discord.com/invite/gfgAwdSEuM 5 | about: 在 Discord 上联系我们 | Contact us on Discord 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/en_feature_request.yml: -------------------------------------------------------------------------------- 1 | name: EN | Feature request 2 | description: Suggest an idea to improve Leaf 3 | labels: ["enhancement"] 4 | 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thank you for taking the time to fill out this feature request for Leaf! Please fill out the following form to help us make sure your feature request will actually improve Leaf! 10 | - type: textarea 11 | attributes: 12 | label: What feature do you want to see added? 13 | description: A clear and concise description of your feature request. 14 | validations: 15 | required: true 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/zh_feature_request.yml: -------------------------------------------------------------------------------- 1 | name: CN | 功能建议 2 | description: 想要一个新功能或给 Leaf 提建议? 3 | labels: ["enhancement"] 4 | 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | 感谢您抽出宝贵的时间为 Leaf 提交功能请求!请尽您所能填写以下表格, 以帮助我们理解您的功能请求, 并大大提高其被添加的机会。 10 | 11 | - type: textarea 12 | attributes: 13 | label: 你想加入什么功能? 14 | description: 用几句话尽可能清晰, 详细的描述你所需要的功能或者建议。 15 | validations: 16 | required: true 17 | -------------------------------------------------------------------------------- /.github/workflows/build-pr.yml: -------------------------------------------------------------------------------- 1 | name: Build Pull Request 2 | 3 | on: 4 | pull_request: 5 | branches: [ "ver/1.21.4" ] 6 | 7 | jobs: 8 | build: 9 | runs-on: blacksmith-8vcpu-ubuntu-2204 10 | env: 11 | GRAALVM_ARGS: "-Dgraal.CompilerConfiguration=enterprise -Dgraal.UsePriorityInlining=true -Dgraal.Vectorization=true -Dgraal.OptDuplication=true --add-modules jdk.incubator.vector" 12 | 13 | steps: 14 | - name: Checkout repository 15 | uses: actions/checkout@main 16 | 17 | - name: Setup java 18 | uses: useblacksmith/setup-java@v5 19 | with: 20 | distribution: 'temurin' 21 | java-version: '21' 22 | 23 | - name: Grant execute permission for gradlew 24 | run: chmod +x gradlew 25 | - name: Configure Git 26 | run: | 27 | git config --global user.email "no-reply@github.com" 28 | git config --global user.name "Github Actions" 29 | 30 | - name: Apply patches 31 | run: ./gradlew -Dorg.gradle.jvmargs="${{ env.GRAALVM_ARGS }}" applyAllPatches --stacktrace --no-daemon 32 | - name: Create MojmapPaperclipJar 33 | run: ./gradlew -Dorg.gradle.jvmargs="${{ env.GRAALVM_ARGS }}" createMojmapPaperclipJar --stacktrace --no-daemon 34 | 35 | - name: Rename Paperclip JARs 36 | run: | 37 | mv leaf-server/build/libs/leaf-paperclip-1.21.4-R0.1-SNAPSHOT-mojmap.jar ./leaf-1.21.4.jar 38 | - name: Upload Leaf as build artifact 39 | uses: actions/upload-artifact@main 40 | with: 41 | name: Leaf 1.21.4 42 | path: ./leaf-1.21.4.jar 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac filesystem dust 2 | .DS_Store/ 3 | .DS_Store 4 | 5 | # Linux temp files 6 | *~ 7 | 8 | # vim 9 | .*.sw[a-p] 10 | 11 | # IntelliJ 12 | *.iml 13 | .idea 14 | 15 | # Gradle 16 | !gradle/wrapper/gradle-wrapper.jar 17 | .gradle 18 | build 19 | 20 | # Leaf 21 | build-data/dev-imports.txt 22 | patches/todo 23 | run 24 | 25 | leaf-api/build.gradle.kts 26 | leaf-server/build.gradle.kts 27 | leaf-server/src/minecraft 28 | gale-api 29 | gale-server 30 | paper-api 31 | paper-server 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Leaf license 2 | 3 | Paperweight files are licensed under [MIT](https://opensource.org/licenses/MIT) (included in `license/MIT.txt`). 4 | Patches are licensed under MIT, unless indicated differently in their header (some patches are licensed under [GPL-3.0](https://www.gnu.org/licenses/gpl-3.0.html) (included in `license/GPL-3.0.txt`) or [LGPL-3.0](https://www.gnu.org/licenses/lgpl-3.0.html) (included in `license/LGPL-3.0.txt`)). 5 | Binaries are licensed under GPL-3.0. 6 | -------------------------------------------------------------------------------- /build-data/dev-imports.txt: -------------------------------------------------------------------------------- 1 | # You can use this file to import files from minecraft libraries into the project 2 | # format: 3 | # 4 | # both fully qualified and a file based syntax are accepted for : 5 | # authlib com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java 6 | # datafixerupper com.mojang.datafixers.DataFixerBuilder 7 | # datafixerupper com/mojang/datafixers/util/Either.java 8 | # To import classes from the vanilla Minecraft jar use `minecraft` as the artifactId: 9 | # minecraft net.minecraft.world.level.entity.LevelEntityGetterAdapter 10 | # minecraft net/minecraft/world/level/entity/LevelEntityGetter.java 11 | # To import minecraft data files, like the default chat type, use `mc_data` as the prefix: 12 | # mc_data chat_type/chat.json 13 | # mc_data dimension_type/overworld.json 14 | # 15 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | group=cn.dreeam.leaf 2 | mcVersion=1.21.4 3 | version=1.21.4-R0.1-SNAPSHOT 4 | 5 | galeCommit=8468427637dc4f8cc50b03ea117aad3d9cad3e73 6 | 7 | org.gradle.configuration-cache=true 8 | org.gradle.caching=true 9 | org.gradle.parallel=true 10 | org.gradle.vfs.watch=false 11 | leaf.patcher.repo-cache=enabled 12 | leaf.patcher.patch-cache=enabled 13 | leaf.patcher.fast-update=true 14 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Winds-Studio/Leaf/b70aaa04505e2cad4862321bc5b03e71c670ed93/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /leaf-api/paper-patches/features/0002-Leaf-config.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Thu, 11 Aug 2022 04:13:27 +0800 4 | Subject: [PATCH] Leaf config 5 | 6 | 7 | diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java 8 | index 45dc5c9775c0a70452f91c401acbbe91168875c7..7edf19de268b061a5bf69b69043fddd820cbb591 100644 9 | --- a/src/main/java/org/bukkit/Server.java 10 | +++ b/src/main/java/org/bukkit/Server.java 11 | @@ -2414,6 +2414,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi 12 | 13 | // Paper end 14 | 15 | + // Leaf start - Leaf config - API 16 | + @NotNull 17 | + public org.bukkit.configuration.file.YamlConfiguration getLeafConfig() 18 | + { 19 | + throw new UnsupportedOperationException("Not supported yet."); 20 | + } 21 | + // Leaf end - Leaf config - API 22 | + 23 | /** 24 | * Sends the component to the player 25 | * 26 | -------------------------------------------------------------------------------- /leaf-api/paper-patches/features/0006-KeYi-Player-Skull-API.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: nostalgic853 3 | Date: Sun, 20 Nov 2022 00:20:01 +0800 4 | Subject: [PATCH] KeYi: Player Skull API 5 | 6 | Original license: MIT 7 | Original project: https://github.com/KeYiMC/KeYi 8 | 9 | diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java 10 | index c806e63b5fc44e9e75035346591cbcea9fc12ca2..69f7a2fa54b667f2bb97454d6be9f6322a9aa43d 100644 11 | --- a/src/main/java/org/bukkit/entity/Player.java 12 | +++ b/src/main/java/org/bukkit/entity/Player.java 13 | @@ -4047,4 +4047,23 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM 14 | sendDeathScreen(message); 15 | } 16 | // Purpur end 17 | + 18 | + // Leaf start - KeYi - Player Skull API 19 | + /** 20 | + * Get a skull item of a player. 21 | + * This method runs on main thread, which may freeze the server. 22 | + * 23 | + * @return A skull ItemStack of the player 24 | + */ 25 | + ItemStack getSkull(); 26 | + 27 | + /** 28 | + * Get a skull item of a player. 29 | + * This method runs on main thread, which may freeze the server. 30 | + * 31 | + * @return A CompletableFuture of the skull ItemStack of the player 32 | + */ 33 | + @Deprecated(forRemoval = true) 34 | + CompletableFuture getSkullAsynchronously(); 35 | + // Leaf end - KeYi - Player Skull API 36 | } 37 | -------------------------------------------------------------------------------- /leaf-archived-patches/removed/hardfork/server/0098-Fix-MC-177381.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> 3 | Date: Wed, 23 Oct 2024 20:20:16 +0800 4 | Subject: [PATCH] Fix MC-177381 5 | 6 | Removed since Paper 1.21.4, thanks Doritos 7 | 8 | Related MC issue: https://bugs.mojang.com/browse/MC-177381 9 | 10 | diff --git a/src/main/java/net/minecraft/server/commands/LocateCommand.java b/src/main/java/net/minecraft/server/commands/LocateCommand.java 11 | index 2972f041eea95b92b37c2ab869f9f8ed3d142a27..dcdde4cd7f15d34eabba4b3802971db20e6ae9d2 100644 12 | --- a/src/main/java/net/minecraft/server/commands/LocateCommand.java 13 | +++ b/src/main/java/net/minecraft/server/commands/LocateCommand.java 14 | @@ -196,8 +196,10 @@ public class LocateCommand { 15 | } 16 | 17 | private static float dist(int x1, int y1, int x2, int y2) { 18 | - int i = x2 - x1; 19 | - int j = y2 - y1; 20 | - return Mth.sqrt((float)(i * i + j * j)); 21 | + // Leaf start - Fix distance overflow MC-177381 22 | + double i = x2 - x1; 23 | + double j = y2 - y1; 24 | + return (float) Math.hypot(i, j); 25 | + // Leaf end - Fix distance overflow MC-177381 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /leaf-archived-patches/removed/hardfork/server/0124-ShreddedPaper-Don-t-block-main-thread-in-Connection-.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: "Author: PureGero" 3 | Date: Thu, 1 Aug 2024 00:43:05 +0900 4 | Subject: [PATCH] ShreddedPaper: Don't block main thread in 5 | Connection#syncAfterConfigurationChange 6 | 7 | Removed since Leaf 1.21.4, replaced by async config switch 8 | 9 | diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java 10 | index 00a82873d226f113278632a53c0faca420dd67d4..5b46036868b6c9d082e35591e58735e16adaae62 100644 11 | --- a/net/minecraft/network/Connection.java 12 | +++ b/net/minecraft/network/Connection.java 13 | @@ -325,6 +325,7 @@ public class Connection extends SimpleChannelInboundHandler> { 14 | 15 | private static void syncAfterConfigurationChange(ChannelFuture future) { 16 | try { 17 | + if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()) net.minecraft.server.MinecraftServer.getServer().managedBlock(future::isDone); // ShreddedPaper - Don't block main thread in Connection#syncAfterConfigurationChange 18 | future.syncUninterruptibly(); 19 | } catch (Exception var2) { 20 | if (var2 instanceof ClosedChannelException) { 21 | -------------------------------------------------------------------------------- /leaf-archived-patches/removed/hardfork/server/0146-Validate-recipe-display-index-before-retrieving-it.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Wed, 19 Mar 2025 13:32:39 -0400 4 | Subject: [PATCH] Validate recipe display index before retrieving it 5 | 6 | Removed since Paper 1.21.4, fixed on Paper side 7 | 8 | diff --git a/net/minecraft/world/item/crafting/RecipeManager.java b/net/minecraft/world/item/crafting/RecipeManager.java 9 | index 4bd1b514f91c0a2c9261b41211a4a341f784a995..5b69c4927174611d62f0f4698215ab97c827c7f5 100644 10 | --- a/net/minecraft/world/item/crafting/RecipeManager.java 11 | +++ b/net/minecraft/world/item/crafting/RecipeManager.java 12 | @@ -206,7 +206,11 @@ public class RecipeManager extends SimplePreparableReloadListener imp 13 | 14 | @Nullable 15 | public RecipeManager.ServerDisplayInfo getRecipeFromDisplay(RecipeDisplayId display) { 16 | - return this.allDisplays.get(display.index()); 17 | + // Leaf start - Validate recipe display index before retrieving it 18 | + final int index = display.index(); 19 | + 20 | + return this.allDisplays.size() > index ? this.allDisplays.get(index) : null; 21 | + // Leaf end - Validate recipe display index before retrieving it 22 | } 23 | 24 | public void listDisplaysForRecipe(ResourceKey> recipe, Consumer output) { 25 | -------------------------------------------------------------------------------- /leaf-archived-patches/removed/hardfork/server/0166-Save-world-async-properly.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Thu, 8 May 2025 00:05:01 +0200 4 | Subject: [PATCH] Save world async properly 5 | 6 | Removed since Paper 1.21.4/5, added on Paper side 7 | 8 | P.S from Tai: I've been using this fix for weeks in my own server but didn't had balls to push it as thought it may cause issues but, it's merged in paper 1.21.5 now. 9 | 10 | diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java 11 | index ba1dd51e7187a80e8438e46383257c22f5382130..6cb0c14cb7aa243bbee6ca9ba57da4cc6eafdfd8 100644 12 | --- a/net/minecraft/server/level/ServerLevel.java 13 | +++ b/net/minecraft/server/level/ServerLevel.java 14 | @@ -1439,7 +1439,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe 15 | } 16 | 17 | if (doFull) { 18 | - this.saveLevelData(true); 19 | + this.saveLevelData(false); // Leaf - Save world async properly 20 | } 21 | // chunk autosave is already called by the ChunkSystem during unload processing (ChunkMap#processUnloads) 22 | // Copied from save() 23 | -------------------------------------------------------------------------------- /leaf-archived-patches/removed/legacy/server/0036-Fix-Make-log4j-compatible-with-future-release.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Sun, 30 Apr 2023 06:22:08 -0400 4 | Subject: [PATCH] Fix: Make log4j compatible with future release 5 | 6 | Removed since 1.20.6 7 | 8 | This patch fixes the warnning "WARN StatusConsoleListener The use of package scanning to locate plugins is deprecated and will be removed in a future release" during server launching. 9 | 10 | diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml 11 | index 0769f5c4711a3b7f59489e611ed01ad8367e5db1..a056aa167887abef9e6d531a9edd2cda433567d2 100644 12 | --- a/src/main/resources/log4j2.xml 13 | +++ b/src/main/resources/log4j2.xml 14 | @@ -1,5 +1,5 @@ 15 | 16 | - 17 | + 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /leaf-archived-patches/removed/legacy/server/0048-Fix-keepalive-kicked-name.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Sun, 3 Dec 2023 05:33:24 -0500 4 | Subject: [PATCH] Fix keepalive kicked name 5 | 6 | Removed since 1.20.6 7 | 8 | diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java 9 | index 9fa1cb2146bb8173a246981c0f73cd8c1bc44abe..487e24f1a26428cdaee3ca946ac8f5f1f599b260 100644 10 | --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java 11 | +++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java 12 | @@ -288,7 +288,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack 13 | if (GaleGlobalConfiguration.get().misc.keepalive.sendMultiple) { 14 | if (elapsedTime >= 1000L) { // 1 second 15 | if (!this.processedDisconnect && this.keepAlives.size() >= KEEPALIVE_LIMIT_IN_SECONDS) { 16 | - LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getName()); 17 | + LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // Leaf - Fix keepalive kicked name 18 | disconnect(Component.translatable("disconnect.timeout"), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); 19 | } else { 20 | this.keepAliveTime = currentTime; // hijack this field for 1 second intervals 21 | -------------------------------------------------------------------------------- /leaf-archived-patches/removed/legacy/server/0069-Fix-NPE-during-creating-GUI-graph.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Tue, 27 Feb 2024 03:27:48 -0500 4 | Subject: [PATCH] Fix NPE during creating GUI graph 5 | 6 | Removed in 1.21.1, Paper fixed it 7 | 8 | diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java 9 | index 7c32c60100cf2bd109eb8762efa856c10b704fdd..81d40895cfa84676f5b200f53b128d9d6c5bc0bd 100644 10 | --- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java 11 | +++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java 12 | @@ -59,7 +59,14 @@ public class RAMDetails extends JList { 13 | GraphData data = RAMGraph.DATA.peekLast(); 14 | Vector vector = new Vector<>(); 15 | 16 | - double[] tps = org.bukkit.Bukkit.getTPSIncluding5SecondAverage(); // Gale - Purpur - 5 second TPS average 17 | + // Leaf - Revert to fix potential NPE during creating GUI graph 18 | + double[] tps = new double[] { 19 | + server.tps5s.getAverage(), 20 | + server.tps1.getAverage(), 21 | + server.tps5.getAverage(), 22 | + server.tps15.getAverage() 23 | + }; // Gale - Purpur - 5 second TPS average 24 | + // Leaf end - Revert to fix potential NPE during creating GUI graph 25 | String[] tpsAvg = new String[tps.length]; 26 | 27 | for ( int g = 0; g < tps.length; g++) { 28 | -------------------------------------------------------------------------------- /leaf-archived-patches/removed/legacy/server/0075-Use-a-shadow-fork-that-supports-Java-21.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: nostalfinals 3 | Date: Tue, 12 Mar 2024 01:10:54 +0800 4 | Subject: [PATCH] Use a shadow fork that supports Java 21 5 | 6 | Removed since 1.20.6 7 | 8 | diff --git a/build.gradle.kts b/build.gradle.kts 9 | index 71f72777303cce3b94628f96c5877e75332cf4d8..78a543150da9e2db42ec8ce07f4fa7528467462d 100644 10 | --- a/build.gradle.kts 11 | +++ b/build.gradle.kts 12 | @@ -3,7 +3,7 @@ import io.papermc.paperweight.util.* 13 | plugins { 14 | java 15 | `maven-publish` 16 | - id("com.github.johnrengelman.shadow") 17 | + id("io.github.goooler.shadow") // Leaf - use a shadow fork that supports Java 21 18 | } 19 | 20 | val log4jPlugins = sourceSets.create("log4jPlugins") 21 | -------------------------------------------------------------------------------- /leaf-archived-patches/removed/legacy/server/0083-Ignore-terminal-provider-warning.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Thu, 2 May 2024 20:21:29 -0400 4 | Subject: [PATCH] Ignore terminal provider warning 5 | 6 | Removed since Leaf 1.21.1, since ported jline update from Paper 1.21.3 7 | don't need deprected jansi anymore 8 | 9 | diff --git a/src/main/java/org/dreeam/leaf/LeafBootstrap.java b/src/main/java/org/dreeam/leaf/LeafBootstrap.java 10 | index 316654051b80ac0fd62cf3b7a0e1b91010ec24b7..9a9bd633c6ed1b2231d36ef7a285a1f1463ccee4 100644 11 | --- a/src/main/java/org/dreeam/leaf/LeafBootstrap.java 12 | +++ b/src/main/java/org/dreeam/leaf/LeafBootstrap.java 13 | @@ -12,5 +12,6 @@ public class LeafBootstrap { 14 | } 15 | 16 | private static void runPreBootTasks() { 17 | + System.setProperty("org.jline.terminal.disableDeprecatedProviderWarning", "true"); // Leaf - Ignore terminal provider warning 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /leaf-archived-patches/removed/legacy/server/0084-Fix-console-freeze-above-JAVA-22.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Sat, 4 May 2024 02:46:17 -0400 4 | Subject: [PATCH] Fix console freeze above JAVA 22 5 | 6 | Removed since Leaf 1.21.1, since ported jline update from Paper 1.21.3 7 | Console input command seems work soomthly on Java 22+ 8 | 9 | Revert to old console provider, Fix https://github.com/PaperMC/Paper/issues/10405 10 | Solution refers to https://inside.java/2023/07/31/quality-heads-up 11 | 12 | diff --git a/src/main/java/org/dreeam/leaf/LeafBootstrap.java b/src/main/java/org/dreeam/leaf/LeafBootstrap.java 13 | index 9a9bd633c6ed1b2231d36ef7a285a1f1463ccee4..780affb51ebddcd05729c8e3272e28630bed8077 100644 14 | --- a/src/main/java/org/dreeam/leaf/LeafBootstrap.java 15 | +++ b/src/main/java/org/dreeam/leaf/LeafBootstrap.java 16 | @@ -13,5 +13,6 @@ public class LeafBootstrap { 17 | 18 | private static void runPreBootTasks() { 19 | System.setProperty("org.jline.terminal.disableDeprecatedProviderWarning", "true"); // Leaf - Ignore terminal provider warning 20 | + if (org.galemc.gale.virtualthread.VirtualThreadService.getJavaMajorVersion() >= 22) System.setProperty("jdk.console", "java.base"); // Leaf - Fix console freeze above JAVA 22 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /leaf-archived-patches/ver/README.md: -------------------------------------------------------------------------------- 1 | # Note 2 | 3 | If you want to check those patches under api or server folder of a previous MC version. 4 | 5 | You can switch git branch to look into them. 6 | -------------------------------------------------------------------------------- /leaf-server/gale-patches/features/0002-Leaf-Commands.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Mon, 4 Nov 2024 23:07:27 -0500 4 | Subject: [PATCH] Leaf Commands 5 | 6 | 7 | diff --git a/src/main/java/org/galemc/gale/command/GaleCommand.java b/src/main/java/org/galemc/gale/command/GaleCommand.java 8 | index c2000206777f62592a4950d7ba96a14d15717126..a077869e1385695ac99e6ddb74aba5f4e215df08 100644 9 | --- a/src/main/java/org/galemc/gale/command/GaleCommand.java 10 | +++ b/src/main/java/org/galemc/gale/command/GaleCommand.java 11 | @@ -37,7 +37,7 @@ import static net.kyori.adventure.text.format.NamedTextColor.RED; 12 | public final class GaleCommand extends Command { 13 | public static final String COMMAND_LABEL = "gale"; 14 | public static final String BASE_PERM = GaleCommands.COMMAND_BASE_PERM + "." + COMMAND_LABEL; 15 | - private static final Permission basePermission = new Permission(BASE_PERM, PermissionDefault.TRUE); 16 | + private static final Permission basePermission = new Permission(BASE_PERM, PermissionDefault.OP); // Leaf - Leaf commands 17 | // subcommand label -> subcommand 18 | private static final GaleSubcommand RELOAD_SUBCOMMAND = new ReloadCommand(); 19 | private static final GaleSubcommand VERSION_SUBCOMMAND = new VersionCommand(); 20 | -------------------------------------------------------------------------------- /leaf-server/gale-patches/features/0004-KeYi-Disable-arrow-despawn-counter-by-default.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: nostalgic853 3 | Date: Mon, 24 Oct 2022 10:28:54 +0800 4 | Subject: [PATCH] KeYi: Disable arrow despawn counter by default 5 | 6 | Original license: MIT 7 | Original project: https://github.com/KeYiMC/KeYi 8 | 9 | diff --git a/src/main/java/org/galemc/gale/configuration/GaleWorldConfiguration.java b/src/main/java/org/galemc/gale/configuration/GaleWorldConfiguration.java 10 | index 34cccb190510c041062858fca20cc40ea5be5f9e..f550c88d125ffafebfad7663088c080bbf771665 100644 11 | --- a/src/main/java/org/galemc/gale/configuration/GaleWorldConfiguration.java 12 | +++ b/src/main/java/org/galemc/gale/configuration/GaleWorldConfiguration.java 13 | @@ -132,7 +132,7 @@ public class GaleWorldConfiguration extends ConfigurationPart { 14 | 15 | } 16 | 17 | - public boolean arrowMovementResetsDespawnCounter = true; // Gale - Purpur - make arrow movement resetting despawn counter configurable 18 | + public boolean arrowMovementResetsDespawnCounter = false; // Gale - Purpur - make arrow movement resetting despawn counter configurable // Leaf - KeYi - Disable arrow despawn counter by default 19 | public boolean entitiesCanRandomStrollIntoNonTickingChunks = true; // Gale - MultiPaper - prevent entities random strolling into non-ticking chunks 20 | public double entityWakeUpDurationRatioStandardDeviation = 0.2; // Gale - variable entity wake-up duration 21 | public boolean hideFlamesOnEntitiesWithFireResistance = false; // Gale - Slice - hide flames on entities with fire resistance 22 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0009-Purpur-Configurable-server-mod-name.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Mon, 17 Jul 2023 08:31:51 +0800 4 | Subject: [PATCH] Purpur: Configurable server mod name 5 | 6 | Original license: MIT 7 | Original project: https://github.com/PurpurMC/Purpur 8 | 9 | diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java 10 | index 719615a559fbcbb2ba78f2f8b333919f4875ae0d..93572d8cc3cff757f36387940dd593885b95ff82 100644 11 | --- a/net/minecraft/server/MinecraftServer.java 12 | +++ b/net/minecraft/server/MinecraftServer.java 13 | @@ -1850,7 +1850,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 3 | Date: Thu, 28 Mar 2024 14:04:35 -0400 4 | Subject: [PATCH] Remove change non-editable sign warning 5 | 6 | 7 | diff --git a/net/minecraft/world/level/block/entity/SignBlockEntity.java b/net/minecraft/world/level/block/entity/SignBlockEntity.java 8 | index 662f53ca5826fb5b68eb4d426f1d9c5d83906eaf..e0a519af9a567eb660fad5ae55c95900fc2472f5 100644 9 | --- a/net/minecraft/world/level/block/entity/SignBlockEntity.java 10 | +++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java 11 | @@ -152,7 +152,7 @@ public class SignBlockEntity extends BlockEntity { 12 | this.setAllowedPlayerEditor(null); 13 | this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); 14 | } else { 15 | - LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString()); 16 | + if (!org.dreeam.leaf.config.modules.misc.RemoveChangeNonEditableSignWarning.enabled) LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString()); // Leaf - Remove change non-editable sign warning 17 | if (player.distanceToSqr(this.getBlockPos().getX(), this.getBlockPos().getY(), this.getBlockPos().getZ()) < Mth.square(32)) // Paper - Don't send far away sign update 18 | ((net.minecraft.server.level.ServerPlayer) player).connection.send(this.getUpdatePacket()); // CraftBukkit 19 | } 20 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0015-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: nostalgic853 3 | Date: Sun, 23 Oct 2022 23:21:45 +0800 4 | Subject: [PATCH] KeYi: Add an option for spigot item merging mechanism 5 | 6 | Original license: MIT 7 | Original project: https://github.com/KeYiMC/KeYi 8 | 9 | diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java 10 | index bbd3253dc6ab09f166447b163b19730244ff7443..6436afc0e59a8efdc9551fdde4d03d245548f3ef 100644 11 | --- a/net/minecraft/world/entity/item/ItemEntity.java 12 | +++ b/net/minecraft/world/entity/item/ItemEntity.java 13 | @@ -315,7 +315,7 @@ public class ItemEntity extends Entity implements TraceableEntity { 14 | ItemStack item = this.getItem(); 15 | ItemStack item1 = itemEntity.getItem(); 16 | if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) { 17 | - if (true || item1.getCount() < item.getCount()) { // Spigot 18 | + if (org.dreeam.leaf.config.modules.gameplay.UseSpigotItemMergingMech.enabled || item1.getCount() < item.getCount()) { // Spigot // Leaf - KeYi - Configurable spigot item merging mechanism 19 | merge(this, item, itemEntity, item1); 20 | } else { 21 | merge(itemEntity, item1, this, item); 22 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0023-Leaves-Xaero-Map-Protocol.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: violetc <58360096+s-yh-china@users.noreply.github.com> 3 | Date: Fri, 27 Jan 2023 09:42:57 +0800 4 | Subject: [PATCH] Leaves: Xaero Map Protocol 5 | 6 | Original license: GPLv3 7 | Original project: https://github.com/LeavesMC/Leaves 8 | 9 | This patch is Powered by Xaero Map 10 | 11 | diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java 12 | index 924faf76763588fb41b8aee53236ccb05b1239b1..e3d09d5f4efb32bb276e001e5ee747a775b502ee 100644 13 | --- a/net/minecraft/server/players/PlayerList.java 14 | +++ b/net/minecraft/server/players/PlayerList.java 15 | @@ -1222,6 +1222,7 @@ public abstract class PlayerList { 16 | player.connection.send(new ClientboundInitializeBorderPacket(worldBorder)); 17 | player.connection.send(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); 18 | player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle())); 19 | + org.leavesmc.leaves.protocol.XaeroMapProtocol.onSendWorldInfo(player); // Leaves - xaero map protocol 20 | if (level.isRaining()) { 21 | // CraftBukkit start - handle player weather 22 | // player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0F)); 23 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0029-Fix-sprint-glitch.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: pixelNightly 3 | Date: Mon, 4 Dec 2023 16:11:36 +0200 4 | Subject: [PATCH] Fix sprint glitch 5 | 6 | 7 | diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java 8 | index c9870c7ce29e240d60b5b29bdf4deba85023be60..ca1d8c9ea018368cc85da46185aee71df8d48ce0 100644 9 | --- a/net/minecraft/world/entity/LivingEntity.java 10 | +++ b/net/minecraft/world/entity/LivingEntity.java 11 | @@ -1379,7 +1379,8 @@ public abstract class LivingEntity extends Entity implements Attackable { 12 | player.setRealHealth(health); 13 | } 14 | 15 | - player.updateScaledHealth(false); 16 | + //player.updateScaledHealth(false); // Leaf - Fix sprint glitch - commented out 17 | + this.entityData.set(LivingEntity.DATA_HEALTH_ID, player.getScaledHealth()); // Leaf - Fix sprint glitch 18 | return; 19 | } 20 | // CraftBukkit end 21 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0040-SparklyPaper-Allow-throttling-hopper-checks-if-the-t.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: MrPowerGamerBR 3 | Date: Fri, 23 Aug 2024 16:20:45 -0300 4 | Subject: [PATCH] SparklyPaper: Allow throttling hopper checks if the target 5 | container is full 6 | 7 | Original project: https://github.com/SparklyPower/SparklyPaper 8 | 9 | diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java 10 | index 2549dd08b60cd81dcbf3412ed71cfc40729ae468..fe1dba198fced6f23556d95ba2f8fbc9200d878a 100644 11 | --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java 12 | +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java 13 | @@ -419,6 +419,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen 14 | } else { 15 | Direction opposite = blockEntity.facing.getOpposite(); 16 | if (isFullContainer(attachedContainer, opposite)) { 17 | + // Leaf start - SparklyPaper - Throttle hopper when full 18 | + if (org.dreeam.leaf.config.modules.opt.ThrottleHopperWhenFull.enabled && org.dreeam.leaf.config.modules.opt.ThrottleHopperWhenFull.skipTicks > 0) { 19 | + blockEntity.setCooldown(org.dreeam.leaf.config.modules.opt.ThrottleHopperWhenFull.skipTicks); 20 | + } 21 | + // Leaf end - SparklyPaper - Throttle hopper when full 22 | return false; 23 | } else { 24 | // Paper start - Perf: Optimize Hoppers 25 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0042-Redirect-vanilla-getProfiler-to-inactive-in-PathNavi.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Mon, 19 Feb 2024 13:10:16 -0500 4 | Subject: [PATCH] Redirect vanilla getProfiler to inactive in 5 | PathNavigationRegion 6 | 7 | To fix compatibility with some plugins, e.g. Citizens, ModelEngine, etc. 8 | 9 | diff --git a/net/minecraft/world/level/PathNavigationRegion.java b/net/minecraft/world/level/PathNavigationRegion.java 10 | index 97a1cb8f30eb1668b1054912789bd100b96bee18..89b293acd22c3f9b324b30d9b1919a8765b11fe7 100644 11 | --- a/net/minecraft/world/level/PathNavigationRegion.java 12 | +++ b/net/minecraft/world/level/PathNavigationRegion.java 13 | @@ -150,4 +150,10 @@ public class PathNavigationRegion implements CollisionGetter { 14 | public int getHeight() { 15 | return this.level.getHeight(); 16 | } 17 | + 18 | + // Leaf start - Redirect vanilla getProfiler to inactive in PathNavigationRegion 19 | + public net.minecraft.util.profiling.ProfilerFiller getProfiler() { 20 | + return net.minecraft.util.profiling.InactiveProfiler.INSTANCE; // Gale - Purpur - remove vanilla profiler 21 | + } 22 | + // Leaf end - Redirect vanilla getProfiler to inactive in PathNavigationRegion 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0043-Remove-useless-creating-stats-json-bases-on-player-n.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Tue, 27 Feb 2024 03:17:10 -0500 4 | Subject: [PATCH] Remove useless creating stats json bases on player name logic 5 | 6 | 7 | diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java 8 | index 4c172e2aee3e48d42009cd39b28f694aa71e20e3..386423589443051b8c461926c570352dd612a051 100644 9 | --- a/net/minecraft/server/players/PlayerList.java 10 | +++ b/net/minecraft/server/players/PlayerList.java 11 | @@ -1561,6 +1561,8 @@ public abstract class PlayerList { 12 | if (serverStatsCounter == null) { 13 | File file = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile(); 14 | File file1 = new File(file, uuid + ".json"); 15 | + // Leaf start - Remove useless creating stats json bases on player name logic 16 | + /* 17 | if (!file1.exists()) { 18 | File file2 = new File(file, displayName + ".json"); // CraftBukkit 19 | Path path = file2.toPath(); 20 | @@ -1568,6 +1570,8 @@ public abstract class PlayerList { 21 | file2.renameTo(file1); 22 | } 23 | } 24 | + */ 25 | + // Leaf end - Remove useless creating stats json bases on player name logic 26 | 27 | serverStatsCounter = new ServerStatsCounter(this.server, file1); 28 | // this.stats.put(uuid, serverStatsCounter); // CraftBukkit 29 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0052-Don-t-save-primed-tnt-entity.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: nostalfinals 3 | Date: Mon, 29 Apr 2024 23:30:21 +0800 4 | Subject: [PATCH] Don't save primed tnt entity 5 | 6 | 7 | diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java 8 | index 40f5534b425ef57c435b365f156d3b988b74f911..c96f458994818392857642282ec3d492124885da 100644 9 | --- a/net/minecraft/world/entity/item/PrimedTnt.java 10 | +++ b/net/minecraft/world/entity/item/PrimedTnt.java 11 | @@ -279,4 +279,11 @@ public class PrimedTnt extends Entity implements TraceableEntity { 12 | return super.interact(player, hand); 13 | } 14 | // Purpur end - Shears can defuse TNT 15 | + 16 | + // Leaf start - PMC - Don't save primed tnt entity 17 | + @Override 18 | + public boolean shouldBeSaved() { 19 | + return !org.dreeam.leaf.config.modules.opt.DontSaveEntity.dontSavePrimedTNT && super.shouldBeSaved(); 20 | + } 21 | + // Leaf - PMC - Don't save primed tnt entity 22 | } 23 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0053-Don-t-save-falling-block-entity.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: nostalfinals 3 | Date: Mon, 29 Apr 2024 23:31:25 +0800 4 | Subject: [PATCH] Don't save falling block entity 5 | 6 | 7 | diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java 8 | index 5746587666c7cb788764aab2f6ccf0f3ac5c282f..fd2f93b070f96d28a8c694a6d943d92d257d0c9e 100644 9 | --- a/net/minecraft/world/entity/item/FallingBlockEntity.java 10 | +++ b/net/minecraft/world/entity/item/FallingBlockEntity.java 11 | @@ -404,4 +404,11 @@ public class FallingBlockEntity extends Entity { 12 | this.forceTickAfterTeleportToDuplicate = entity != null && flag && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowUnsafeEndPortalTeleportation; // Paper 13 | return entity; 14 | } 15 | + 16 | + // Leaf start - PMC - Don't save falling block entity 17 | + @Override 18 | + public boolean shouldBeSaved() { 19 | + return !org.dreeam.leaf.config.modules.opt.DontSaveEntity.dontSaveFallingBlock && super.shouldBeSaved(); 20 | + } 21 | + // Leaf end - PMC - Don't save falling block entity 22 | } 23 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0065-Remove-stream-in-GateBehavior.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Tue, 9 Nov 2077 00:00:00 +0800 4 | Subject: [PATCH] Remove stream in GateBehavior 5 | 6 | 7 | diff --git a/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/net/minecraft/world/entity/ai/behavior/GateBehavior.java 8 | index bd31d1cac0d022a72bd536c41d1ef811886e7068..2830792cd98c0849280aa1e2116fa89f3c8d2c85 100644 9 | --- a/net/minecraft/world/entity/ai/behavior/GateBehavior.java 10 | +++ b/net/minecraft/world/entity/ai/behavior/GateBehavior.java 11 | @@ -73,9 +73,19 @@ public class GateBehavior implements BehaviorControl 12 | } 13 | } 14 | // Paper end - Perf: Remove streams from hot code 15 | - if (this.behaviors.stream().noneMatch(behavior -> behavior.getStatus() == Behavior.Status.RUNNING)) { 16 | + // Leaf start - Remove more streams in GateBehavior 17 | + boolean hasRunningTask = false; 18 | + for (final BehaviorControl behavior : this.behaviors) { 19 | + if (behavior.getStatus() == Behavior.Status.RUNNING) { 20 | + hasRunningTask = true; 21 | + break; 22 | + } 23 | + } 24 | + 25 | + if (!hasRunningTask) { 26 | this.doStop(level, entity, gameTime); 27 | } 28 | + // Leaf end - Remove more streams in GateBehavior 29 | } 30 | 31 | @Override 32 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0067-Remove-stream-in-matchingSlot.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Tue, 26 Nov 2024 19:58:29 -0500 4 | Subject: [PATCH] Remove stream in matchingSlot 5 | 6 | 7 | diff --git a/net/minecraft/world/item/enchantment/Enchantment.java b/net/minecraft/world/item/enchantment/Enchantment.java 8 | index 7a620eb92b1e672cedd72ec4d986c01eba337686..183874d90d576d740c5d924accc5c0d7fdb8450c 100644 9 | --- a/net/minecraft/world/item/enchantment/Enchantment.java 10 | +++ b/net/minecraft/world/item/enchantment/Enchantment.java 11 | @@ -126,7 +126,15 @@ public record Enchantment(Component description, Enchantment.EnchantmentDefiniti 12 | } 13 | 14 | public boolean matchingSlot(EquipmentSlot slot) { 15 | - return this.definition.slots().stream().anyMatch(equipmentSlotGroup -> equipmentSlotGroup.test(slot)); 16 | + // Leaf start - Remove stream in matchingSlot 17 | + for (EquipmentSlotGroup equipmentSlotGroup : this.definition.slots()) { 18 | + if (equipmentSlotGroup.test(slot)) { 19 | + return true; 20 | + } 21 | + } 22 | + 23 | + return false; 24 | + // Leaf end - Remove stream in matchingSlot 25 | } 26 | 27 | public boolean isPrimaryItem(ItemStack stack) { 28 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0069-Replace-criterion-map-with-optimized-collection.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Sat, 7 Sep 2024 02:12:55 -0400 4 | Subject: [PATCH] Replace criterion map with optimized collection 5 | 6 | 7 | diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java 8 | index e4ea26ae84efde7ce54e08a246a6ea2ae2a17151..ddd1eac136fc3327aea8286769efd2d7309f67ec 100644 9 | --- a/net/minecraft/server/PlayerAdvancements.java 10 | +++ b/net/minecraft/server/PlayerAdvancements.java 11 | @@ -60,7 +60,7 @@ public class PlayerAdvancements { 12 | private AdvancementHolder lastSelectedTab; 13 | private boolean isFirstPacket = true; 14 | private final Codec codec; 15 | - public final Map, Set>> criterionData = new java.util.IdentityHashMap<>(); // Paper - fix advancement data player leakage 16 | + public final Map, Set>> criterionData = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(); // Paper - fix advancement data player leakage // Leaf - Replace criterion map with optimized collection 17 | 18 | public PlayerAdvancements(DataFixer dataFixer, PlayerList playerList, ServerAdvancementManager manager, Path playerSavePath, ServerPlayer player) { 19 | this.playerList = playerList; 20 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0075-Fix-MC-200418.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> 3 | Date: Sun, 7 Jul 2024 01:29:57 +0800 4 | Subject: [PATCH] Fix-MC-200418 5 | 6 | Related MC issue: https://bugs.mojang.com/browse/MC-200418 7 | 8 | diff --git a/net/minecraft/world/entity/monster/ZombieVillager.java b/net/minecraft/world/entity/monster/ZombieVillager.java 9 | index cb0e000c5b8636296c7d7474d0947c75f41b6058..d4b6c93f9f0e109be300164c4fd9167aba2d951c 100644 10 | --- a/net/minecraft/world/entity/monster/ZombieVillager.java 11 | +++ b/net/minecraft/world/entity/monster/ZombieVillager.java 12 | @@ -320,6 +320,12 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { 13 | if (!this.isSilent()) { 14 | serverLevel.levelEvent(null, 1027, this.blockPosition(), 0); 15 | } 16 | + 17 | + // Leaf start - Fix MC-200418 18 | + if (villager.isPassenger() && villager.getVehicle() instanceof net.minecraft.world.entity.animal.Chicken && villager.isBaby()) { 19 | + villager.removeVehicle(); 20 | + } 21 | + // Leaf end - Fix MC-200418 22 | // CraftBukkit start 23 | }, org.bukkit.event.entity.EntityTransformEvent.TransformReason.CURED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CURED // CraftBukkit 24 | ); 25 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0076-Fix-MC-119417.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> 3 | Date: Sun, 7 Jul 2024 01:42:45 +0800 4 | Subject: [PATCH] Fix-MC-119417 5 | 6 | Related MC issue: https://bugs.mojang.com/browse/MC-119417 7 | 8 | diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java 9 | index 8a9c2489730dd47cc776493695393e788fd2033e..4f01b53bf801f99253efd27df6216912705d18af 100644 10 | --- a/net/minecraft/server/level/ServerPlayer.java 11 | +++ b/net/minecraft/server/level/ServerPlayer.java 12 | @@ -2261,6 +2261,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc 13 | this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, gameMode.getId())); 14 | if (gameMode == GameType.SPECTATOR) { 15 | this.removeEntitiesOnShoulder(); 16 | + this.stopSleeping(); // Leaf - Fix MC-119417 17 | this.stopRiding(); 18 | EnchantmentHelper.stopLocationBasedEffects(this); 19 | } else { 20 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0077-Fix-MC-223153.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> 3 | Date: Sun, 7 Jul 2024 01:59:11 +0800 4 | Subject: [PATCH] Fix-MC-223153 5 | 6 | Related MC issue: https://bugs.mojang.com/browse/MC-223153 7 | 8 | diff --git a/net/minecraft/world/level/block/Blocks.java b/net/minecraft/world/level/block/Blocks.java 9 | index bf047be5b577b0d1bf70458df14618bcfe2d1de2..07a8fbfa7eb6e684ea699f009ce2d19311994e39 100644 10 | --- a/net/minecraft/world/level/block/Blocks.java 11 | +++ b/net/minecraft/world/level/block/Blocks.java 12 | @@ -6632,6 +6632,7 @@ public class Blocks { 13 | .mapColor(MapColor.COLOR_ORANGE) 14 | .instrument(NoteBlockInstrument.BASEDRUM) 15 | .requiresCorrectToolForDrops() 16 | + .sound(SoundType.COPPER) // Leaf - Fix MC-223153 17 | .strength(5.0F, 6.0F) 18 | ); 19 | public static final Block RAW_GOLD_BLOCK = register( 20 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0093-EMC-Don-t-use-snapshots-for-TileEntity-getOwner.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Aikar 3 | Date: Tue, 7 Nov 2017 00:01:04 -0500 4 | Subject: [PATCH] EMC: Don't use snapshots for TileEntity::getOwner 5 | 6 | Original license: MIT 7 | Original project: https://github.com/starlis/empirecraft 8 | 9 | Also see Leaf's EMC-Don-t-use-snapshots-for-acquiring-blockstate 10 | 11 | diff --git a/net/minecraft/world/level/block/entity/BlockEntity.java b/net/minecraft/world/level/block/entity/BlockEntity.java 12 | index 3fd0f42618e5c2c683335d1d3e0bb74c6d32ef66..8f4d13d897ac92c6ea239da22029c8058bd82eaa 100644 13 | --- a/net/minecraft/world/level/block/entity/BlockEntity.java 14 | +++ b/net/minecraft/world/level/block/entity/BlockEntity.java 15 | @@ -361,7 +361,7 @@ public abstract class BlockEntity { 16 | // CraftBukkit start - add method 17 | public org.bukkit.inventory.InventoryHolder getOwner() { 18 | // Paper start 19 | - return getOwner(true); 20 | + return getOwner(org.dreeam.leaf.config.modules.opt.TileEntitySnapshotCreation.enabled); // Leaf - EMC - Don't use snapshots for TileEntity::getOwner 21 | } 22 | public org.bukkit.inventory.InventoryHolder getOwner(boolean useSnapshot) { 23 | // Paper end 24 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0096-C2ME-Reduce-Allocations.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Thu, 7 Nov 2024 19:45:31 +0100 4 | Subject: [PATCH] C2ME: Reduce Allocations 5 | 6 | This patch is based on the following mixin: 7 | "com/ishland/c2me/opts/allocs/mixin/object_pooling_caching/MixinOreFeature.java" 8 | By: ishland 9 | As part of: C2ME (https://github.com/RelativityMC/C2ME-fabric) 10 | Licensed under: MIT (https://opensource.org/licenses/MIT) 11 | 12 | diff --git a/net/minecraft/world/level/levelgen/feature/OreFeature.java b/net/minecraft/world/level/levelgen/feature/OreFeature.java 13 | index c7b46efd4f08067e2c9c5c8b0e8b71a94a79823d..d14609e932f2ce4e97d1e354b424cc3ec86bd25b 100644 14 | --- a/net/minecraft/world/level/levelgen/feature/OreFeature.java 15 | +++ b/net/minecraft/world/level/levelgen/feature/OreFeature.java 16 | @@ -69,7 +69,7 @@ public class OreFeature extends Feature { 17 | int height 18 | ) { 19 | int i = 0; 20 | - BitSet bitSet = new BitSet(width * height * width); 21 | + BitSet bitSet = org.dreeam.leaf.util.cache.CachedOrNewBitsGetter.getCachedOrNewBitSet(width * height * width); // Leaf - C2ME - Reduce Allocations 22 | BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); 23 | int i1 = config.size; 24 | double[] doubles = new double[i1 * 4]; 25 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0112-SparklyPaper-Reset-dirty-flag-when-loading-maps-from.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: MrPowerGamerBR 3 | Date: Wed, 5 Jun 2024 15:20:00 -0300 4 | Subject: [PATCH] SparklyPaper: Reset dirty flag when loading maps from the 5 | disk 6 | 7 | By default, the server will start rewriting all map datas to the disk after loading it, even if the map didn't have any changes 8 | 9 | This also slows down world saving a lot if you have a lot of maps 10 | 11 | diff --git a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java 12 | index 681dec447486138088fe5f705ef4fadab531139f..07f9287ff1f1dbd1795582c74102c072ea59b29f 100644 13 | --- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java 14 | +++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java 15 | @@ -198,6 +198,7 @@ public class MapItemSavedData extends SavedData { 16 | } 17 | } 18 | 19 | + mapItemSavedData.setDirty(false); // SparklyPaper - reset dirty flag when loading maps from the disk (context for updates: this modification is at the end of the map "load" function) 20 | return mapItemSavedData; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0115-Avoid-useless-deque-clear-on-LevelTicks-cleanupAfter.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: MachineBreaker 3 | Date: Wed, 16 Oct 2024 03:39:24 -0400 4 | Subject: [PATCH] Avoid useless deque clear on LevelTicks#cleanupAfterTick 5 | 6 | 7 | diff --git a/net/minecraft/world/ticks/LevelTicks.java b/net/minecraft/world/ticks/LevelTicks.java 8 | index fbf0d3b808c66e8971c747619f6acf7417af5ef7..d4542a86a2a9bfcfa7b6b7a213f233542ffed797 100644 9 | --- a/net/minecraft/world/ticks/LevelTicks.java 10 | +++ b/net/minecraft/world/ticks/LevelTicks.java 11 | @@ -182,7 +182,7 @@ public class LevelTicks implements LevelTickAccess { 12 | } 13 | 14 | private void cleanupAfterTick() { 15 | - this.toRunThisTick.clear(); 16 | + //this.toRunThisTick.clear(); // Leaf - Avoid useless deque clear on LevelTicks#cleanupAfterTick - This method runs after toRunThisTick is polled so this is always empty 17 | this.containersToTick.clear(); 18 | this.alreadyRunThisTick.clear(); 19 | this.toRunThisTickSet.clear(); 20 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0116-Replace-brain-activity-maps-with-optimized-collectio.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Sat, 8 Feb 2025 20:45:14 +0100 4 | Subject: [PATCH] Replace brain activity maps with optimized collection 5 | 6 | 7 | diff --git a/net/minecraft/world/entity/ai/Brain.java b/net/minecraft/world/entity/ai/Brain.java 8 | index ea6c8e85ccff67b1c24109732f74f1e8199cad07..e27284f9897923f67985e3d60c3438bd00cc4a51 100644 9 | --- a/net/minecraft/world/entity/ai/Brain.java 10 | +++ b/net/minecraft/world/entity/ai/Brain.java 11 | @@ -390,8 +390,8 @@ public class Brain { 12 | 13 | for (Pair> pair : tasks) { 14 | this.availableBehaviorsByPriority 15 | - .computeIfAbsent(pair.getFirst(), integer -> Maps.newHashMap()) 16 | - .computeIfAbsent(activity, activity1 -> Sets.newLinkedHashSet()) 17 | + .computeIfAbsent(pair.getFirst(), integer -> new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>()) // Leaf - Replace brain activity maps with optimized collection 18 | + .computeIfAbsent(activity, activity1 -> new it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet<>()) // Leaf - Replace brain activity maps with optimized collection 19 | .add((BehaviorControl)pair.getSecond()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0124-Use-ensureCapacity-to-pre-populate-the-size-of-ticki.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Sun, 16 Feb 2025 01:13:04 +0100 4 | Subject: [PATCH] Use ensureCapacity to pre-populate the size of ticking chunks 5 | list output 6 | 7 | 8 | diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java 9 | index 6735f9e23c8972b7cf1438a2f3b49d780c1ff78c..c80464d333bd37a9b8bc7cea2291c8c72e6f9bd6 100644 10 | --- a/net/minecraft/server/level/ServerChunkCache.java 11 | +++ b/net/minecraft/server/level/ServerChunkCache.java 12 | @@ -585,7 +585,11 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon 13 | final ServerChunkCache.ChunkAndHolder[] raw = tickingChunks.getRawDataUnchecked(); 14 | final int size = tickingChunks.size(); 15 | 16 | - final ChunkMap chunkMap = this.chunkMap; 17 | + // Leaf start - Use ensureCapacity to pre-populate the size of ticking chunks list output 18 | + if (output instanceof ArrayList arrayList) { 19 | + arrayList.ensureCapacity(size); 20 | + } 21 | + // Leaf end - Use ensureCapacity to pre-populate the size of ticking chunks list output 22 | 23 | for (int i = 0; i < size; ++i) { 24 | final ServerChunkCache.ChunkAndHolder chunkAndHolder = raw[i]; 25 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0125-Directly-use-the-pre-filtered-ticking-chunks-list-as.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Sun, 16 Feb 2025 01:13:04 +0100 4 | Subject: [PATCH] Directly use the pre-filtered ticking chunks list as the 5 | output 6 | 7 | This patch uses already pre filtered chunks, which completely skips the isChunkNearPlayer check 8 | 9 | diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java 10 | index c80464d333bd37a9b8bc7cea2291c8c72e6f9bd6..b1f1b596a597d559aa672a3cb46a03917ad746af 100644 11 | --- a/net/minecraft/server/level/ServerChunkCache.java 12 | +++ b/net/minecraft/server/level/ServerChunkCache.java 13 | @@ -592,14 +592,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon 14 | // Leaf end - Use ensureCapacity to pre-populate the size of ticking chunks list output 15 | 16 | for (int i = 0; i < size; ++i) { 17 | - final ServerChunkCache.ChunkAndHolder chunkAndHolder = raw[i]; 18 | - final LevelChunk levelChunk = chunkAndHolder.chunk(); 19 | - 20 | - if (!this.isChunkNearPlayer(chunkMap, levelChunk.getPos(), levelChunk)) { 21 | - continue; 22 | - } 23 | - 24 | - output.add(levelChunk); 25 | + output.add(raw[i].chunk()); // Leaf - Directly use the pre-filtered ticking chunks list as the output 26 | } 27 | // Paper end - chunk tick iteration optimisation 28 | } 29 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0143-Optimize-addOrUpdateTransientModifier.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Sat, 22 Mar 2025 00:07:38 +0100 4 | Subject: [PATCH] Optimize addOrUpdateTransientModifier 5 | 6 | 7 | diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java 8 | index ed5077708415a74da171b88fa1fb8b736446666b..62cadad97109247e65a550acc5955424b1f6fc5e 100644 9 | --- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java 10 | +++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java 11 | @@ -107,8 +107,13 @@ public class AttributeInstance { 12 | } 13 | 14 | public void addOrUpdateTransientModifier(AttributeModifier modifier) { 15 | - AttributeModifier attributeModifier = this.modifierById.put(modifier.id(), modifier); 16 | - if (modifier != attributeModifier) { 17 | + // Leaf start - Optimize addOrUpdateTransientModifier 18 | + // First check if we already have the same modifier instance to avoid unnecessary put operations 19 | + AttributeModifier existingModifier = this.modifierById.get(modifier.id()); 20 | + // Only perform updates if the modifier is new or different 21 | + if (existingModifier != modifier) { 22 | + this.modifierById.put(modifier.id(), modifier); 23 | + // Leaf end - Optimize addOrUpdateTransientModifier 24 | this.getModifiers(modifier.operation()).put(modifier.id(), modifier); 25 | this.setDirty(); 26 | } 27 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0148-Use-direct-iteration-on-Sensing.tick.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Sun, 23 Mar 2025 20:48:16 +0100 4 | Subject: [PATCH] Use direct iteration on Sensing.tick 5 | 6 | 7 | diff --git a/net/minecraft/world/entity/ai/sensing/Sensing.java b/net/minecraft/world/entity/ai/sensing/Sensing.java 8 | index cc25f5838aec5ed9fca2fb8b0322fafad9397a46..002d3c0d8b1107a275020d5c582c37e9a5c536ee 100644 9 | --- a/net/minecraft/world/entity/ai/sensing/Sensing.java 10 | +++ b/net/minecraft/world/entity/ai/sensing/Sensing.java 11 | @@ -39,7 +39,12 @@ public class Sensing { 12 | } else { 13 | var expiringNow = this.expiring[this.nextToExpireIndex]; 14 | 15 | - expiringNow.forEach(this.seen::remove); 16 | + // Leaf start - Use direct iteration on Sensing.tick 17 | + var iterator = expiringNow.iterator(); 18 | + while (iterator.hasNext()) { 19 | + this.seen.remove(iterator.nextInt()); 20 | + } 21 | + // Leaf end - Use direct iteration on Sensing.tick 22 | expiringNow.clear(); 23 | 24 | this.currentCacheAddIndex++; 25 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0151-Null-handling-on-MultifaceSpreader.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Wed, 2 Apr 2025 23:03:22 +0200 4 | Subject: [PATCH] Null handling on MultifaceSpreader 5 | 6 | WHYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY 7 | 8 | diff --git a/net/minecraft/world/level/block/MultifaceSpreader.java b/net/minecraft/world/level/block/MultifaceSpreader.java 9 | index 60f47334bb855d5216f57f888f131ba41f728d21..718223a54da75d000e3c3090acf6e28b4283820a 100644 10 | --- a/net/minecraft/world/level/block/MultifaceSpreader.java 11 | +++ b/net/minecraft/world/level/block/MultifaceSpreader.java 12 | @@ -148,6 +148,14 @@ public class MultifaceSpreader { 13 | } 14 | 15 | default boolean placeBlock(LevelAccessor level, MultifaceSpreader.SpreadPos pos, BlockState state, boolean markForPostprocessing) { 16 | + // Leaf start - Null handling on MultifaceSpreader 17 | + // Check for null 18 | + if (pos.source() == null || pos.pos() == null) { 19 | + org.dreeam.leaf.config.LeafConfig.LOGGER.warn("Invalid SpreadPos with null source or position: {}", pos); 20 | + return false; 21 | + } 22 | + // Leaf end - Null handling on MultifaceSpreader 23 | + 24 | BlockState stateForPlacement = this.getStateForPlacement(state, level, pos.pos(), pos.face()); 25 | if (stateForPlacement != null) { 26 | if (markForPostprocessing) { 27 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0166-Optimise-BlockEntities-tickersInLevel.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Thu, 8 May 2025 13:30:07 +0200 4 | Subject: [PATCH] Optimise BlockEntities tickersInLevel 5 | 6 | 7 | diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java 8 | index 546fb78339c005ed71142cb3c894f816b8c72d08..e6eab6929b08503c49debbbd25497ffedad438e1 100644 9 | --- a/net/minecraft/world/level/chunk/LevelChunk.java 10 | +++ b/net/minecraft/world/level/chunk/LevelChunk.java 11 | @@ -72,7 +72,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p 12 | return ""; 13 | } 14 | }; 15 | - private final Map tickersInLevel = Maps.newHashMap(); 16 | + private final Map tickersInLevel = org.dreeam.leaf.config.modules.opt.OptimiseBlockEntities.enabled ? new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>() : Maps.newHashMap(); // Leaf - Optimise BlockEntities tickersInLevel 17 | public boolean loaded; 18 | public final ServerLevel level; // CraftBukkit - type 19 | @Nullable 20 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0171-Optimise-player-movement-checks.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Sat, 10 May 2025 23:18:17 +0200 4 | Subject: [PATCH] Optimise player movement checks 5 | 6 | 7 | diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java 8 | index a4de10a32f49b7b361fc9dd1d142caeef8d7d148..5eb740476dff894e91c2bd779ef6b760213a78a5 100644 9 | --- a/net/minecraft/world/entity/Entity.java 10 | +++ b/net/minecraft/world/entity/Entity.java 11 | @@ -1209,7 +1209,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess 12 | } 13 | // Paper end 14 | 15 | - movement = this.maybeBackOffFromEdge(movement, type); 16 | + if (!org.dreeam.leaf.config.modules.opt.OptimizePlayerMovementProcessing.enabled) movement = this.maybeBackOffFromEdge(movement, type); // Leaf - Optimise player movement checks 17 | Vec3 vec3 = this.collide(movement); 18 | double d = vec3.lengthSqr(); 19 | if (d > 1.0E-7 || movement.lengthSqr() - d < 1.0E-7) { 20 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0172-Remove-streams-in-MobSensor.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Mon, 12 May 2025 19:11:16 +0200 4 | Subject: [PATCH] Remove streams in MobSensor 5 | 6 | 7 | diff --git a/net/minecraft/world/entity/ai/sensing/MobSensor.java b/net/minecraft/world/entity/ai/sensing/MobSensor.java 8 | index bda210b4809a5aade7ab4d0f26fdda4d5f53f619..2271196768bfc90626e007a70602f818c832e348 100644 9 | --- a/net/minecraft/world/entity/ai/sensing/MobSensor.java 10 | +++ b/net/minecraft/world/entity/ai/sensing/MobSensor.java 11 | @@ -40,10 +40,15 @@ public class MobSensor extends Sensor { 12 | public void checkForMobsNearby(T sensingEntity) { 13 | Optional> memory = sensingEntity.getBrain().getMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES); 14 | if (!memory.isEmpty()) { 15 | - boolean flag = memory.get().stream().anyMatch(livingEntity -> this.mobTest.test(sensingEntity, livingEntity)); 16 | - if (flag) { 17 | - this.mobDetected(sensingEntity); 18 | + // Leaf start - Remove streams in MobSensor 19 | + List entities = memory.get(); 20 | + for (LivingEntity livingEntity : entities) { 21 | + if (this.mobTest.test(sensingEntity, livingEntity)) { 22 | + this.mobDetected(sensingEntity); 23 | + break; 24 | + } 25 | } 26 | + // Leaf end - Remove streams in MobSensor 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0176-Optimize-getScaledTrackingDistance.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: hayanesuru 3 | Date: Sat, 17 May 2025 19:01:50 +0900 4 | Subject: [PATCH] Optimize getScaledTrackingDistance 5 | 6 | 7 | diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java 8 | index eb0589b203bcf72cd24bb37f2c448c23cb8d6f2b..a54f9030c81a2eb36f4dae951b09a9a6057be936 100644 9 | --- a/net/minecraft/server/dedicated/DedicatedServer.java 10 | +++ b/net/minecraft/server/dedicated/DedicatedServer.java 11 | @@ -838,7 +838,13 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface 12 | 13 | @Override 14 | public int getScaledTrackingDistance(int trackingDistance) { 15 | - return this.getProperties().entityBroadcastRangePercentage * trackingDistance / 100; 16 | + // Leaf start - Optimize getScaledTrackingDistance 17 | + int p = this.getProperties().entityBroadcastRangePercentage; 18 | + if (p == 100) { 19 | + return trackingDistance; 20 | + } 21 | + return p * trackingDistance / 100; 22 | + // Leaf end - Optimize getScaledTrackingDistance 23 | } 24 | 25 | @Override 26 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0177-Optimize-SynchedEntityData-packDirty.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: hayanesuru 3 | Date: Sat, 17 May 2025 19:03:31 +0900 4 | Subject: [PATCH] Optimize SynchedEntityData#packDirty 5 | 6 | 7 | diff --git a/net/minecraft/network/syncher/SynchedEntityData.java b/net/minecraft/network/syncher/SynchedEntityData.java 8 | index 3d90f9f1ac1bd281edf6bb0f93ea821657d5bd2f..f0b8d44009ebfaf7a45f9cbaea5dc3ff157815fc 100644 9 | --- a/net/minecraft/network/syncher/SynchedEntityData.java 10 | +++ b/net/minecraft/network/syncher/SynchedEntityData.java 11 | @@ -84,7 +84,15 @@ public class SynchedEntityData { 12 | return null; 13 | } else { 14 | this.isDirty = false; 15 | - List> list = new ArrayList<>(); 16 | + // Leaf start - Optimize SynchedEntityData#packDirty 17 | + int cap = 0; 18 | + for (SynchedEntityData.DataItem dataItem : this.itemsById) { 19 | + if (dataItem.isDirty()) { 20 | + cap += 1; 21 | + } 22 | + } 23 | + ArrayList> list = new ArrayList<>(cap); 24 | + // Leaf end - Optimize SynchedEntityData#packDirty 25 | 26 | for (SynchedEntityData.DataItem dataItem : this.itemsById) { 27 | if (dataItem.isDirty()) { 28 | -------------------------------------------------------------------------------- /leaf-server/minecraft-patches/features/0189-Add-BlockExplosionHitEvent.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Pascalpex 3 | Date: Wed, 4 Jun 2025 17:03:32 +0200 4 | Subject: [PATCH] Add BlockExplosionHitEvent 5 | 6 | 7 | diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java 8 | index 6030c4eefd77969a1a9251de76d4291dcb0a2092..ea9c641fe9a9685307b6de2999ea4ff5342269b7 100644 9 | --- a/net/minecraft/world/level/ServerExplosion.java 10 | +++ b/net/minecraft/world/level/ServerExplosion.java 11 | @@ -623,9 +623,13 @@ public class ServerExplosion implements Explosion { 12 | } 13 | // CraftBukkit end 14 | 15 | - this.level 16 | - .getBlockState(blockPos) 17 | - .onExplosionHit(this.level, blockPos, this, (itemStack, blockPos1) -> addOrAppendStack(list, itemStack, blockPos1)); 18 | + // Leaf start - BlockExplosionHitEvent 19 | + if(new org.dreeam.leaf.event.BlockExplosionHitEvent(CraftLocation.toBukkit(blockPos, bworld).getBlock(), this.source == null ? null : this.source.getBukkitEntity(), org.bukkit.craftbukkit.CraftExplosionResult.toBukkit(this.blockInteraction)).callEvent()) { 20 | + this.level 21 | + .getBlockState(blockPos) 22 | + .onExplosionHit(this.level, blockPos, this, (itemStack, blockPos1) -> addOrAppendStack(list, itemStack, blockPos1)); 23 | + } 24 | + // Leaf end 25 | } 26 | 27 | for (ServerExplosion.StackCollector stackCollector : list) { 28 | -------------------------------------------------------------------------------- /leaf-server/paper-patches/features/0002-Leaf-Bootstrap.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Wed, 31 Jul 2024 22:05:21 +0800 4 | Subject: [PATCH] Leaf Bootstrap 5 | 6 | Removed since Leaf 1.21.4, useless 7 | 8 | org.bukkit.craftbukkit.Main#main -> LeafBootstrap -> PaperBootstrap -> ... 9 | 10 | diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java 11 | index bf5343b0847e9f57ffbc7f33714ae6ca62f14332..70d093f71cca569d9da3ae82e738f8f3069f405e 100644 12 | --- a/src/main/java/org/bukkit/craftbukkit/Main.java 13 | +++ b/src/main/java/org/bukkit/craftbukkit/Main.java 14 | @@ -278,7 +278,8 @@ public class Main { 15 | System.setProperty("jdk.console", "java.base"); // Paper - revert default console provider back to java.base so we can have our own jline 16 | //System.out.println("Loading libraries, please wait..."); 17 | //net.minecraft.server.Main.main(options); 18 | - io.papermc.paper.PaperBootstrap.boot(options); 19 | + //io.papermc.paper.PaperBootstrap.boot(options); // Leaf - Leaf Boostrap - diff on change 20 | + org.dreeam.leaf.LeafBootstrap.boot(options); // Leaf - Leaf Boostrap 21 | } catch (Throwable t) { 22 | t.printStackTrace(); 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/paper-patches/features/0003-Leaf-Commands.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Mon, 4 Nov 2024 23:07:27 -0500 4 | Subject: [PATCH] Leaf Commands 5 | 6 | 7 | diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java 8 | index 7d66126c1f5957c109a2426d53f5d0072886309b..f623a1d9e580104e1ab8b7cf88b9d26212f8acd8 100644 9 | --- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java 10 | +++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java 11 | @@ -6,6 +6,7 @@ import org.bukkit.util.permissions.DefaultPermissions; 12 | public final class CraftDefaultPermissions { 13 | private static final String ROOT = "minecraft"; 14 | public static final String GALE_ROOT = "gale"; // Gale - set Gale permissions root 15 | + public static final String LEAF_ROOT = "leaf"; // Leaf - Leaf commands 16 | 17 | public static final String writeBooks = GALE_ROOT + ".writebooks"; // Gale - Pufferfish - make book writing configurable 18 | 19 | -------------------------------------------------------------------------------- /leaf-server/paper-patches/features/0015-Including-5s-in-getTPS.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Sat, 24 Feb 2024 01:16:07 -0500 4 | Subject: [PATCH] Including 5s in getTPS() 5 | 6 | 7 | diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java 8 | index 7ca77be262e6c8c9882db42295a42487b672d43e..99a3c2d19bb263f499a5be1e9f603ad55b60ebe7 100644 9 | --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java 10 | +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java 11 | @@ -3185,6 +3185,8 @@ public final class CraftServer implements Server { 12 | 13 | @Override 14 | public double[] getTPS() { 15 | + if (org.dreeam.leaf.config.modules.misc.Including5sIngetTPS.enabled) return getTPSIncluding5SecondAverage(); // Leaf - Including 5s in getTPS() 16 | + 17 | return new double[] { 18 | net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(), 19 | net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(), 20 | -------------------------------------------------------------------------------- /leaf-server/paper-patches/features/0020-Faster-random-generator.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> 3 | Date: Tue, 9 Nov 2077 00:00:00 +0800 4 | Subject: [PATCH] Faster random generator 5 | 6 | This patch replaces LegacyRandomSource with FasterRandomSource by default, 7 | which is faster in general. 8 | 9 | Benchmark results (10,000,000 iterations) (Azul Zulu 23.0.1) 10 | 11 | FasterRandomSource (Leaf) (Backed by Xoroshiro128PlusPlus): 51,633,700 ns 12 | LegacyRandomSource (Vanilla): 254,857,500 ns 13 | ThreadUnsafeRandom (Moonrise): 102,265,100 ns 14 | SimpleThreadUnsafeRandom (Moonrise): 97,054,600 ns 15 | 16 | diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java 17 | index c60c05b9e426f56ed3e812abb9aae9ef52bd20e8..268fd8e60630e835c750a8b67201cc63f0b5193d 100644 18 | --- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java 19 | +++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java 20 | @@ -97,7 +97,7 @@ public class CustomChunkGenerator extends InternalChunkGenerator { 21 | } 22 | 23 | private static WorldgenRandom getSeededRandom() { 24 | - return new WorldgenRandom(new LegacyRandomSource(0)); 25 | + return new WorldgenRandom(org.dreeam.leaf.config.modules.opt.FastRNG.worldgenEnabled() ? new org.dreeam.leaf.util.math.random.FasterRandomSource(0) : new LegacyRandomSource(0)); // Leaf - Faster random generator 26 | } 27 | 28 | @Override 29 | -------------------------------------------------------------------------------- /leaf-server/paper-patches/features/0022-Replace-world-map-with-optimized-collection.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Sun, 10 Nov 2024 14:36:18 +0100 4 | Subject: [PATCH] Replace world map with optimized collection 5 | 6 | 7 | diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java 8 | index eacc39145d22b9afac773623497f8b18836914e8..d0d2ceb45218e6eec14ac9963bf816ff17053af8 100644 9 | --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java 10 | +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java 11 | @@ -286,7 +286,7 @@ public final class CraftServer implements Server { 12 | private final StructureManager structureManager; 13 | protected final DedicatedServer console; 14 | protected final DedicatedPlayerList playerList; 15 | - private final Map worlds = new LinkedHashMap(); 16 | + private final Map worlds = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap(); // Leaf - Replace world map with optimized collection 17 | private final it.unimi.dsi.fastutil.objects.Object2ObjectMap worldsByUUID = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // Gale - MultiPaper - CraftBukkit UUID to world map 18 | // private final Map, Registry> registries = new HashMap<>(); // Paper - replace with RegistryAccess 19 | private YamlConfiguration configuration; 20 | -------------------------------------------------------------------------------- /leaf-server/paper-patches/features/0027-Faster-CraftServer-getworlds-list-creation.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com> 3 | Date: Tue, 9 Nov 2077 00:00:00 +0800 4 | Subject: [PATCH] Faster CraftServer#getworlds list creation 5 | 6 | CraftServer#getWorlds/Bukkit#getWorlds is frequently used in plugins, 7 | replacing ArrayList with Fastutil ObjectArrayList 8 | brings about 40% performance improvement in benchmark. 9 | 10 | diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java 11 | index d0d2ceb45218e6eec14ac9963bf816ff17053af8..dd38057071de1ecce2e420bd0696a134190a09c1 100644 12 | --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java 13 | +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java 14 | @@ -994,7 +994,7 @@ public final class CraftServer implements Server { 15 | 16 | @Override 17 | public List getWorlds() { 18 | - return new ArrayList(this.worlds.values()); 19 | + return new it.unimi.dsi.fastutil.objects.ObjectArrayList(this.worlds.values()); // Leaf - Faster CraftServer#getWorlds list creation 20 | } 21 | 22 | @Override 23 | -------------------------------------------------------------------------------- /leaf-server/paper-patches/features/0028-Cache-chunk-key.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> 3 | Date: Sat, 2 Nov 2024 04:15:20 -0400 4 | Subject: [PATCH] Cache chunk key 5 | 6 | Cache convert process between ChunkPos < - > chunkKey 7 | This patch didn't cahce SectionPos or BlockPos to chunkKey, since it needs to consider the mutable blockpos siutation. 8 | 9 | TODO: Cache block pos and section pos, whether need? 10 | 11 | diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java b/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java 12 | index 036c1a287db04c0191e5f84b027ea68d31447cbc..3cda726b5ef7419da512889d3edd1fb6935e6a54 100644 13 | --- a/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java 14 | +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/CoordinateUtils.java 15 | @@ -20,7 +20,7 @@ public final class CoordinateUtils { 16 | } 17 | 18 | public static long getChunkKey(final ChunkPos pos) { 19 | - return ((long)pos.z << 32) | (pos.x & 0xFFFFFFFFL); 20 | + return ((long)pos.z << 32) | (pos.x & 0xFFFFFFFFL); // Leaf - Cache chunk key 21 | } 22 | 23 | public static long getChunkKey(final SectionPos pos) { 24 | -------------------------------------------------------------------------------- /leaf-server/paper-patches/features/0036-Async-chunk-send.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: hayanesuru 3 | Date: Fri, 2 May 2025 18:22:24 -0700 4 | Subject: [PATCH] Async chunk send 5 | 6 | 7 | diff --git a/src/main/java/io/papermc/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/io/papermc/paper/antixray/ChunkPacketBlockControllerAntiXray.java 8 | index ee2d3a54d760f9c26542eab03c51651a30e279a0..0a4382315ee62e8defa50b3e8018a8f97687c139 100644 9 | --- a/src/main/java/io/papermc/paper/antixray/ChunkPacketBlockControllerAntiXray.java 10 | +++ b/src/main/java/io/papermc/paper/antixray/ChunkPacketBlockControllerAntiXray.java 11 | @@ -185,7 +185,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo 12 | return; 13 | } 14 | 15 | - if (!Bukkit.isPrimaryThread()) { 16 | + if (!Bukkit.isPrimaryThread() && !(Thread.currentThread() instanceof org.dreeam.leaf.async.chunk.AsyncChunkSendThread)) { // Leaf - Async chunk send 17 | // Plugins? 18 | MinecraftServer.getServer().scheduleOnMain(() -> modifyBlocks(chunkPacket, chunkPacketInfo)); 19 | return; 20 | -------------------------------------------------------------------------------- /leaf-server/paper-patches/features/0037-Optimise-player-movement-checks.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Taiyou06 3 | Date: Sun, 11 May 2025 00:37:44 +0200 4 | Subject: [PATCH] Optimise player movement checks 5 | 6 | 7 | diff --git a/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java b/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java 8 | index 94689e0342cf95dbedec955d67c95fa07a219678..8a888d52495bd6f447b8d767ca80de20dfee66b9 100644 9 | --- a/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java 10 | +++ b/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java 11 | @@ -88,6 +88,11 @@ public abstract class SingleUserAreaMap { 12 | if (fromX == NOT_SET) { 13 | return false; 14 | } 15 | + // Leaf start - Optimise player movement checks 16 | + if (org.dreeam.leaf.config.modules.opt.OptimizePlayerMovementProcessing.enabled && fromX == toX && fromZ == toZ && oldViewDistance == newViewDistance) { 17 | + return true; 18 | + } 19 | + // Leaf end - Optimise player movement checks 20 | 21 | this.lastChunkX = toX; 22 | this.lastChunkZ = toZ; 23 | -------------------------------------------------------------------------------- /leaf-server/paper-patches/features/0040-cache-getBiome.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: hayanesuru 3 | Date: Tue, 3 Jun 2025 18:51:44 +0900 4 | Subject: [PATCH] cache getBiome 5 | 6 | 7 | diff --git a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java 8 | index 09e87552159e24603aa9a4f658ab4449d7eaeb0a..cfe6d74fa06e19c33e6342c76ca99e473840a65b 100644 9 | --- a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java 10 | +++ b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java 11 | @@ -302,6 +302,13 @@ public abstract class DelegatedGeneratorAccess implements WorldGenLevel { 12 | return this.handle.getBiome(pos); 13 | } 14 | 15 | + // Leaf start - cache getBiome 16 | + @Override 17 | + public Holder getBiomeCached(BlockPos pos) { 18 | + return this.handle.getBiomeCached(pos); 19 | + } 20 | + // Leaf end - cache getBiome 21 | + 22 | @Override 23 | public Stream getBlockStatesIfLoaded(AABB box) { 24 | return this.handle.getBlockStatesIfLoaded(box); 25 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/gg/pufferfish/pufferfish/sentry/SentryManager.java: -------------------------------------------------------------------------------- 1 | package gg.pufferfish.pufferfish.sentry; 2 | 3 | import io.sentry.Sentry; 4 | import org.apache.logging.log4j.Level; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.dreeam.leaf.config.modules.misc.SentryDSN; 8 | 9 | public class SentryManager { 10 | 11 | private static final Logger LOGGER = LogManager.getLogger(SentryManager.class); 12 | 13 | private SentryManager() { 14 | } 15 | 16 | private static boolean initialized = false; 17 | 18 | public static synchronized void init(Level logLevel) { 19 | if (initialized) { 20 | return; 21 | } 22 | if (logLevel == null) { 23 | LOGGER.error("Invalid log level, defaulting to WARN."); 24 | logLevel = Level.WARN; 25 | } 26 | try { 27 | initialized = true; 28 | 29 | Sentry.init(options -> { 30 | options.setDsn(SentryDSN.sentryDsn); 31 | options.setMaxBreadcrumbs(100); 32 | }); 33 | 34 | PufferfishSentryAppender appender = new PufferfishSentryAppender(logLevel); 35 | appender.start(); 36 | ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()).addAppender(appender); 37 | LOGGER.info("Sentry logging started!"); 38 | } catch (Exception e) { 39 | LOGGER.warn("Failed to initialize sentry!", e); 40 | initialized = false; 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/gg/pufferfish/pufferfish/util/IterableWrapper.java: -------------------------------------------------------------------------------- 1 | package gg.pufferfish.pufferfish.util; 2 | 3 | import java.util.Iterator; 4 | 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public record IterableWrapper(Iterator iterator) implements Iterable { 8 | @NotNull 9 | @Override 10 | public Iterator iterator() { 11 | return iterator; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/net/caffeinemc/mods/lithium/common/entity/EquipmentEntity.java: -------------------------------------------------------------------------------- 1 | package net.caffeinemc.mods.lithium.common.entity; 2 | 3 | import net.caffeinemc.mods.lithium.common.util.change_tracking.ChangeSubscriber; 4 | import net.minecraft.world.item.ItemStack; 5 | 6 | public interface EquipmentEntity { 7 | 8 | void onEquipmentReplaced(ItemStack oldStack, ItemStack newStack); 9 | 10 | interface EquipmentTrackingEntity { 11 | void onEquipmentChanged(); 12 | } 13 | 14 | interface TickableEnchantmentTrackingEntity extends ChangeSubscriber.EnchantmentSubscriber { 15 | void updateHasTickableEnchantments(ItemStack oldStack, ItemStack newStack); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/net/caffeinemc/mods/lithium/common/util/change_tracking/ChangePublisher.java: -------------------------------------------------------------------------------- 1 | package net.caffeinemc.mods.lithium.common.util.change_tracking; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | 5 | public interface ChangePublisher { 6 | 7 | void subscribe(ChangeSubscriber subscriber, int subscriberData); 8 | 9 | int unsubscribe(ChangeSubscriber subscriber); 10 | 11 | default void unsubscribeWithData(ChangeSubscriber subscriber, int index) { 12 | throw new UnsupportedOperationException("Only implemented for ItemStacks"); 13 | } 14 | 15 | default boolean isSubscribedWithData(ChangeSubscriber subscriber, int subscriberData) { 16 | throw new UnsupportedOperationException("Only implemented for ItemStacks"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/LeafBootstrap.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf; 2 | 3 | import io.papermc.paper.PaperBootstrap; 4 | import joptsimple.OptionSet; 5 | 6 | public class LeafBootstrap { 7 | 8 | public static final boolean enableFMA = Boolean.parseBoolean(System.getProperty("Leaf.enableFMA", "false")); // Leaf - FMA feature 9 | 10 | public static void boot(final OptionSet options) { 11 | //runPreBootTasks(); 12 | 13 | PaperBootstrap.boot(options); 14 | } 15 | 16 | private static void runPreBootTasks() { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/AsyncPlayerDataSaving.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async; 2 | 3 | import net.minecraft.Util; 4 | import org.dreeam.leaf.config.modules.async.AsyncPlayerDataSave; 5 | 6 | import java.util.Optional; 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.Future; 9 | import java.util.concurrent.LinkedBlockingQueue; 10 | import java.util.concurrent.ThreadPoolExecutor; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | public class AsyncPlayerDataSaving { 14 | 15 | public static final ExecutorService IO_POOL = new ThreadPoolExecutor( 16 | 1, 1, 0L, TimeUnit.MILLISECONDS, 17 | new LinkedBlockingQueue<>(), 18 | new com.google.common.util.concurrent.ThreadFactoryBuilder() 19 | .setPriority(Thread.NORM_PRIORITY - 2) 20 | .setNameFormat("Leaf IO Thread") 21 | .setUncaughtExceptionHandler(Util::onThreadException) 22 | .build(), 23 | new ThreadPoolExecutor.DiscardPolicy() 24 | ); 25 | 26 | private AsyncPlayerDataSaving() { 27 | } 28 | 29 | public static Optional> submit(Runnable runnable) { 30 | if (!AsyncPlayerDataSave.enabled) { 31 | runnable.run(); 32 | return Optional.empty(); 33 | } else { 34 | return Optional.of(IO_POOL.submit(runnable)); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/ShutdownExecutors.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async; 2 | 3 | import net.minecraft.server.MinecraftServer; 4 | import org.dreeam.leaf.async.tracker.MultithreadedTracker; 5 | 6 | public class ShutdownExecutors { 7 | public static void shutdown(MinecraftServer server) { 8 | 9 | if (server.mobSpawnExecutor != null) { 10 | try { 11 | server.mobSpawnExecutor.kill(); 12 | } catch (InterruptedException ignored) { 13 | } 14 | } 15 | 16 | if (AsyncPlayerDataSaving.IO_POOL != null) { 17 | AsyncPlayerDataSaving.IO_POOL.shutdown(); 18 | try { 19 | AsyncPlayerDataSaving.IO_POOL.awaitTermination(300L, java.util.concurrent.TimeUnit.SECONDS); 20 | } catch (InterruptedException ignored) { 21 | } 22 | } 23 | 24 | if (server.asyncGoalThread != null) { 25 | try { 26 | server.asyncGoalThread.join(); 27 | } catch (InterruptedException ignored) { 28 | } 29 | } 30 | 31 | if (MultithreadedTracker.TRACKER_EXECUTOR != null) { 32 | MultithreadedTracker.TRACKER_EXECUTOR.shutdown(); 33 | try { 34 | MultithreadedTracker.TRACKER_EXECUTOR.awaitTermination(10L, java.util.concurrent.TimeUnit.SECONDS); 35 | } catch (InterruptedException ignored) { 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/ai/VWaker.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.ai; 2 | 3 | import org.jetbrains.annotations.Nullable; 4 | 5 | @FunctionalInterface 6 | public interface VWaker { 7 | @Nullable Object wake(); 8 | } 9 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/ai/Waker.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.ai; 2 | 3 | import org.jetbrains.annotations.Nullable; 4 | 5 | public class Waker { 6 | 7 | @Nullable 8 | public volatile VWaker wake = null; 9 | @Nullable 10 | public volatile Object result = null; 11 | public boolean state = true; 12 | 13 | public final @Nullable Object result() { 14 | Object result = this.result; 15 | this.result = null; 16 | return result; 17 | } 18 | 19 | final void wake() { 20 | final var wake = this.wake; 21 | if (wake != null) { 22 | try { 23 | this.result = wake.wake(); 24 | } catch (Exception e) { 25 | AsyncGoalExecutor.LOGGER.error("Exception while wake", e); 26 | } 27 | this.wake = null; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/chunk/AsyncChunkSend.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.chunk; 2 | 3 | import com.google.common.util.concurrent.ThreadFactoryBuilder; 4 | import net.minecraft.Util; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | 8 | import java.util.concurrent.ExecutorService; 9 | import java.util.concurrent.LinkedBlockingQueue; 10 | import java.util.concurrent.ThreadPoolExecutor; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | public class AsyncChunkSend { 14 | 15 | public static final ExecutorService POOL = new ThreadPoolExecutor( 16 | 1, 1, 0L, TimeUnit.MILLISECONDS, 17 | new LinkedBlockingQueue<>(), 18 | new ThreadFactoryBuilder() 19 | .setPriority(Thread.NORM_PRIORITY) 20 | .setNameFormat("Leaf Async Chunk Send Thread") 21 | .setUncaughtExceptionHandler(Util::onThreadException) 22 | .setThreadFactory(AsyncChunkSendThread::new) 23 | .build(), 24 | new ThreadPoolExecutor.CallerRunsPolicy() 25 | ); 26 | public static final Logger LOGGER = LogManager.getLogger("Leaf Async Chunk Send"); 27 | } 28 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/chunk/AsyncChunkSendThread.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.chunk; 2 | 3 | public class AsyncChunkSendThread extends Thread { 4 | 5 | protected AsyncChunkSendThread(Runnable task) { 6 | super(task); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/path/NodeEvaluatorFeatures.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.path; 2 | 3 | import net.minecraft.world.level.pathfinder.NodeEvaluator; 4 | import net.minecraft.world.level.pathfinder.SwimNodeEvaluator; 5 | 6 | public record NodeEvaluatorFeatures( 7 | NodeEvaluatorType type, 8 | boolean canPassDoors, 9 | boolean canFloat, 10 | boolean canWalkOverFences, 11 | boolean canOpenDoors, 12 | boolean allowBreaching 13 | ) { 14 | public static NodeEvaluatorFeatures fromNodeEvaluator(NodeEvaluator nodeEvaluator) { 15 | NodeEvaluatorType type = NodeEvaluatorType.fromNodeEvaluator(nodeEvaluator); 16 | boolean canPassDoors = nodeEvaluator.canPassDoors(); 17 | boolean canFloat = nodeEvaluator.canFloat(); 18 | boolean canWalkOverFences = nodeEvaluator.canWalkOverFences(); 19 | boolean canOpenDoors = nodeEvaluator.canOpenDoors(); 20 | boolean allowBreaching = nodeEvaluator instanceof SwimNodeEvaluator swimNodeEvaluator && swimNodeEvaluator.allowBreaching; 21 | return new NodeEvaluatorFeatures(type, canPassDoors, canFloat, canWalkOverFences, canOpenDoors, allowBreaching); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/path/NodeEvaluatorGenerator.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.path; 2 | 3 | import net.minecraft.world.level.pathfinder.NodeEvaluator; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public interface NodeEvaluatorGenerator { 7 | @NotNull NodeEvaluator generate(NodeEvaluatorFeatures nodeEvaluatorFeatures); 8 | } 9 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/path/NodeEvaluatorType.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.path; 2 | 3 | import net.minecraft.world.level.pathfinder.AmphibiousNodeEvaluator; 4 | import net.minecraft.world.level.pathfinder.FlyNodeEvaluator; 5 | import net.minecraft.world.level.pathfinder.NodeEvaluator; 6 | import net.minecraft.world.level.pathfinder.SwimNodeEvaluator; 7 | 8 | public enum NodeEvaluatorType { 9 | WALK, 10 | SWIM, 11 | AMPHIBIOUS, 12 | FLY; 13 | 14 | public static NodeEvaluatorType fromNodeEvaluator(NodeEvaluator nodeEvaluator) { 15 | if (nodeEvaluator instanceof SwimNodeEvaluator) return SWIM; 16 | if (nodeEvaluator instanceof FlyNodeEvaluator) return FLY; 17 | if (nodeEvaluator instanceof AmphibiousNodeEvaluator) return AMPHIBIOUS; 18 | return WALK; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/path/PathProcessState.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.path; 2 | 3 | public enum PathProcessState { 4 | WAITING, 5 | PROCESSING, 6 | COMPLETED, 7 | } 8 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/path/PathfindTaskRejectPolicy.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.path; 2 | 3 | import org.dreeam.leaf.config.LeafConfig; 4 | 5 | import java.util.Locale; 6 | 7 | public enum PathfindTaskRejectPolicy { 8 | FLUSH_ALL, 9 | CALLER_RUNS, 10 | DISCARD; 11 | 12 | public static PathfindTaskRejectPolicy fromString(String policy) { 13 | try { 14 | return PathfindTaskRejectPolicy.valueOf(policy.toUpperCase(Locale.ROOT)); 15 | } catch (IllegalArgumentException e) { 16 | LeafConfig.LOGGER.warn("Invalid pathfind task reject policy: {}, falling back to {}.", policy, FLUSH_ALL.toString()); 17 | return FLUSH_ALL; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/world/PWTEventScheduler.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.world; 2 | 3 | import com.google.common.util.concurrent.ThreadFactoryBuilder; 4 | 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | public class PWTEventScheduler { 9 | 10 | private static volatile PWTEventScheduler instance; 11 | private final ExecutorService executor; 12 | 13 | private PWTEventScheduler() { 14 | this.executor = Executors.newCachedThreadPool( 15 | new ThreadFactoryBuilder() 16 | .setNameFormat("Leaf PWT Event Scheduler Thread - %d") 17 | .setDaemon(true) 18 | .setPriority(Thread.NORM_PRIORITY - 2) 19 | .build() 20 | ); 21 | } 22 | 23 | public static PWTEventScheduler getScheduler() { 24 | if (instance == null) { 25 | synchronized (PWTEventScheduler.class) { 26 | if (instance == null) { 27 | instance = new PWTEventScheduler(); 28 | } 29 | } 30 | } 31 | return instance; 32 | } 33 | 34 | public void scheduleTask(Runnable task) { 35 | this.executor.execute(task); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/world/ReadOperationType.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.world; 2 | 3 | public enum ReadOperationType { 4 | BLOCK_GET_BIOME, 5 | BLOCK_GET_COMPUTED_BIOME, 6 | BLOCK_IS_INDIRECTLY_POWERED, 7 | BLOCK_GET_BLOCK_POWER, 8 | BLOCK_RAY_TRACE, 9 | BLOCK_CAN_PLACE, 10 | BLOCK_GET_NMS_STATE 11 | } 12 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/world/SparklyPaperServerLevelTickExecutorThreadFactory.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.world; 2 | 3 | import ca.spottedleaf.moonrise.common.util.TickThread; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.concurrent.ThreadFactory; 7 | 8 | public class SparklyPaperServerLevelTickExecutorThreadFactory implements ThreadFactory { 9 | 10 | private final String worldName; 11 | 12 | public SparklyPaperServerLevelTickExecutorThreadFactory(final String worldName) { 13 | this.worldName = worldName; 14 | } 15 | 16 | @Override 17 | public Thread newThread(@NotNull Runnable runnable) { 18 | TickThread.ServerLevelTickThread tickThread = new TickThread.ServerLevelTickThread(runnable, "Leaf World Ticking Thread - " + this.worldName); 19 | 20 | if (tickThread.isDaemon()) { 21 | tickThread.setDaemon(false); 22 | } 23 | 24 | if (tickThread.getPriority() != 5) { 25 | tickThread.setPriority(5); 26 | } 27 | 28 | return tickThread; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/async/world/WorldReadRequest.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.async.world; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | public record WorldReadRequest( 6 | ReadOperationType type, 7 | Object[] params, // Parameters for the read operation 8 | CompletableFuture future // Future to complete with the result 9 | ) { 10 | } 11 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/command/LeafCommands.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.command; 2 | 3 | import net.minecraft.server.MinecraftServer; 4 | import org.checkerframework.checker.nullness.qual.NonNull; 5 | import org.checkerframework.framework.qual.DefaultQualifier; 6 | import org.bukkit.command.Command; 7 | import org.bukkit.craftbukkit.util.permissions.CraftDefaultPermissions; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | @DefaultQualifier(NonNull.class) 13 | public final class LeafCommands { 14 | 15 | public static final String COMMAND_BASE_PERM = CraftDefaultPermissions.LEAF_ROOT + ".command"; 16 | 17 | private LeafCommands() { 18 | } 19 | 20 | private static final Map COMMANDS = new HashMap<>(); 21 | 22 | static { 23 | COMMANDS.put(LeafCommand.COMMAND_LABEL, new LeafCommand()); 24 | } 25 | 26 | public static void registerCommands(final MinecraftServer server) { 27 | COMMANDS.forEach((s, command) -> server.server.getCommandMap().register(s, "Leaf", command)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/command/LeafSubcommand.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.command; 2 | 3 | import org.checkerframework.checker.nullness.qual.NonNull; 4 | import org.checkerframework.framework.qual.DefaultQualifier; 5 | import org.jetbrains.annotations.Nullable; 6 | import org.bukkit.command.CommandSender; 7 | import org.bukkit.permissions.Permission; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | @DefaultQualifier(NonNull.class) 13 | public interface LeafSubcommand { 14 | 15 | boolean execute(CommandSender sender, String subCommand, String[] args); 16 | 17 | default List tabComplete(final CommandSender sender, final String subCommand, final String[] args) { 18 | return Collections.emptyList(); 19 | } 20 | 21 | boolean testPermission(CommandSender sender); 22 | 23 | @Nullable Permission getPermission(); 24 | } 25 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/command/PermissionedLeafSubcommand.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.command; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import org.jetbrains.annotations.Nullable; 5 | import org.bukkit.command.CommandSender; 6 | import org.bukkit.permissions.Permission; 7 | import org.bukkit.permissions.PermissionDefault; 8 | 9 | public abstract class PermissionedLeafSubcommand implements LeafSubcommand { 10 | 11 | public final Permission permission; 12 | 13 | protected PermissionedLeafSubcommand(Permission permission) { 14 | this.permission = permission; 15 | } 16 | 17 | protected PermissionedLeafSubcommand(String permission, PermissionDefault permissionDefault) { 18 | this(new Permission(permission, permissionDefault)); 19 | } 20 | 21 | @Override 22 | public boolean testPermission(@NotNull CommandSender sender) { 23 | return sender.hasPermission(this.permission); 24 | } 25 | 26 | @Override 27 | public @Nullable Permission getPermission() { 28 | return this.permission; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/command/subcommands/ReloadCommand.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.command.subcommands; 2 | 3 | import net.kyori.adventure.text.Component; 4 | import net.kyori.adventure.text.format.NamedTextColor; 5 | import org.checkerframework.checker.nullness.qual.NonNull; 6 | import org.checkerframework.framework.qual.DefaultQualifier; 7 | import org.dreeam.leaf.command.LeafCommand; 8 | import org.dreeam.leaf.command.PermissionedLeafSubcommand; 9 | import org.dreeam.leaf.config.LeafConfig; 10 | import org.bukkit.command.Command; 11 | import org.bukkit.command.CommandSender; 12 | import org.bukkit.permissions.PermissionDefault; 13 | 14 | @DefaultQualifier(NonNull.class) 15 | public final class ReloadCommand extends PermissionedLeafSubcommand { 16 | 17 | public final static String LITERAL_ARGUMENT = "reload"; 18 | public static final String PERM = LeafCommand.BASE_PERM + "." + LITERAL_ARGUMENT; 19 | 20 | public ReloadCommand() { 21 | super(PERM, PermissionDefault.OP); 22 | } 23 | 24 | @Override 25 | public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { 26 | this.doReload(sender); 27 | return true; 28 | } 29 | 30 | private void doReload(final CommandSender sender) { 31 | Command.broadcastCommandMessage(sender, Component.text("Reloading Leaf config...", NamedTextColor.GREEN)); 32 | 33 | LeafConfig.reloadAsync(sender); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/command/subcommands/VersionCommand.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.command.subcommands; 2 | 3 | import net.minecraft.server.MinecraftServer; 4 | import org.checkerframework.checker.nullness.qual.NonNull; 5 | import org.checkerframework.checker.nullness.qual.Nullable; 6 | import org.checkerframework.framework.qual.DefaultQualifier; 7 | import org.dreeam.leaf.command.LeafCommand; 8 | import org.dreeam.leaf.command.PermissionedLeafSubcommand; 9 | import org.bukkit.command.Command; 10 | import org.bukkit.command.CommandSender; 11 | import org.bukkit.permissions.PermissionDefault; 12 | 13 | @DefaultQualifier(NonNull.class) 14 | public final class VersionCommand extends PermissionedLeafSubcommand { 15 | 16 | public final static String LITERAL_ARGUMENT = "version"; 17 | public static final String PERM = LeafCommand.BASE_PERM + "." + LITERAL_ARGUMENT; 18 | 19 | public VersionCommand() { 20 | super(PERM, PermissionDefault.TRUE); 21 | } 22 | 23 | @Override 24 | public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { 25 | final @Nullable Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version"); 26 | 27 | if (ver != null) { 28 | ver.execute(sender, LeafCommand.COMMAND_LABEL, me.titaniumtown.ArrayConstants.emptyStringArray); // Gale - JettPack - reduce array allocations 29 | } 30 | 31 | return true; 32 | } 33 | 34 | @Override 35 | public boolean testPermission(CommandSender sender) { 36 | return super.testPermission(sender) && sender.hasPermission("bukkit.command.version"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/EnumConfigCategory.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config; 2 | 3 | public enum EnumConfigCategory { 4 | ASYNC("async"), 5 | PERF("performance"), 6 | FIXES("fixes"), 7 | GAMEPLAY("gameplay-mechanisms"), 8 | NETWORK("network"), 9 | MISC("misc"); 10 | 11 | private final String baseKeyName; 12 | private static final EnumConfigCategory[] VALUES = EnumConfigCategory.values(); 13 | 14 | EnumConfigCategory(String baseKeyName) { 15 | this.baseKeyName = baseKeyName; 16 | } 17 | 18 | public String getBaseKeyName() { 19 | return this.baseKeyName; 20 | } 21 | 22 | public static EnumConfigCategory[] getCategoryValues() { 23 | return VALUES; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/annotations/DoNotLoad.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.annotations; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | @Retention(RetentionPolicy.RUNTIME) 7 | public @interface DoNotLoad { 8 | } 9 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/annotations/Experimental.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.annotations; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Indicates that a feature is experimental and may be removed or changed in the future. 11 | */ 12 | @Documented 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target(value = {ElementType.FIELD}) 15 | public @interface Experimental { 16 | } 17 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/annotations/HotReloadUnsupported.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.annotations; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | @Retention(RetentionPolicy.RUNTIME) 7 | public @interface HotReloadUnsupported { 8 | } 9 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/AsyncChunkSend.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.async; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class AsyncChunkSend extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.ASYNC.getBaseKeyName() + ".async-chunk-send"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | private static boolean asyncChunkSendInitialized; 14 | 15 | @Override 16 | public void onLoaded() { 17 | config.addCommentRegionBased(getBasePath(), """ 18 | Makes chunk packet preparation and sending asynchronous to improve server performance. 19 | This can significantly reduce main thread load when many players are loading chunks.""", 20 | """ 21 | 使区块数据包准备和发送异步化以提高服务器性能. 22 | 当许多玩家同时加载区块时, 这可以显著减少主线程负载."""); 23 | 24 | if (asyncChunkSendInitialized) { 25 | config.getConfigSection(getBasePath()); 26 | return; 27 | } 28 | asyncChunkSendInitialized = true; 29 | 30 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/AsyncLocator.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.async; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | import org.dreeam.leaf.config.LeafConfig; 6 | 7 | public class AsyncLocator extends ConfigModules { 8 | 9 | public String getBasePath() { 10 | return EnumConfigCategory.ASYNC.getBaseKeyName() + ".async-locator"; 11 | } 12 | 13 | public static boolean enabled = false; 14 | public static int asyncLocatorThreads = 0; 15 | public static int asyncLocatorKeepalive = 60; 16 | 17 | @Override 18 | public void onLoaded() { 19 | config.addCommentRegionBased(getBasePath(), """ 20 | Whether or not asynchronous locator should be enabled. 21 | This offloads structure locating to other threads. 22 | Only for locate command, dolphin treasure finding and eye of ender currently.""", 23 | """ 24 | 是否启用异步结构搜索. 25 | 目前可用于 /locate 指令, 海豚寻宝和末影之眼."""); 26 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled); 27 | asyncLocatorThreads = config.getInt(getBasePath() + ".threads", asyncLocatorThreads); 28 | asyncLocatorKeepalive = config.getInt(getBasePath() + ".keepalive", asyncLocatorKeepalive); 29 | 30 | if (asyncLocatorThreads <= 0) 31 | asyncLocatorThreads = 1; 32 | if (!enabled) 33 | asyncLocatorThreads = 0; 34 | else 35 | LeafConfig.LOGGER.info("Using {} threads for Async Locator", asyncLocatorThreads); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/AsyncMobSpawning.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.async; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class AsyncMobSpawning extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.ASYNC.getBaseKeyName() + ".async-mob-spawning"; 10 | } 11 | 12 | public static boolean enabled = true; 13 | private static boolean asyncMobSpawningInitialized; 14 | 15 | @Override 16 | public void onLoaded() { 17 | config.addCommentRegionBased(getBasePath(), """ 18 | Whether or not asynchronous mob spawning should be enabled. 19 | On servers with many entities, this can improve performance by up to 15%. You must have 20 | paper's per-player-mob-spawns setting set to true for this to work. 21 | One quick note - this does not actually spawn mobs async (that would be very unsafe). 22 | This just offloads some expensive calculations that are required for mob spawning.""", 23 | """ 24 | 是否异步化生物生成. 25 | 在实体较多的服务器上, 异步生成可最高带来 15% 的性能提升. 26 | 须在Paper配置文件中打开 per-player-mob-spawns 才能生效."""); 27 | 28 | // This prevents us from changing the value during a reload. 29 | if (asyncMobSpawningInitialized) { 30 | config.getConfigSection(getBasePath()); 31 | return; 32 | } 33 | asyncMobSpawningInitialized = true; 34 | 35 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/async/AsyncPlayerDataSave.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.async; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class AsyncPlayerDataSave extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.ASYNC.getBaseKeyName() + ".async-playerdata-save"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | config.addCommentRegionBased(getBasePath(), """ 17 | Make PlayerData saving asynchronously.""", 18 | """ 19 | 异步保存玩家数据."""); 20 | 21 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/fixes/DontPlacePlayerIfFull.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.fixes; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class DontPlacePlayerIfFull extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.FIXES.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".dont-place-player-if-server-full", enabled, config.pickStringRegionBased(""" 17 | Don't let player join server if the server is full. 18 | If enable this, you should use 'purpur.joinfullserver' permission instead of 19 | PlayerLoginEvent#allow to let player join full server.""", 20 | """ 21 | 服务器已满时禁止玩家加入. 22 | 开启后需使用权限 'purpur.joinfullserver' 而不是 23 | PlayerLoginEvent#allow 让玩家进入已满的服务器.""")); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/AfkCommand.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.gameplay; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class AfkCommand extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.GAMEPLAY.getBaseKeyName() + ".afk-command"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled, config.pickStringRegionBased(""" 17 | The AFK command based on Minecraft built-in idle-timeout mechanism 18 | Rest of AFK settings are in the Purpur config""", 19 | """ 20 | 基于原版 idle-timeout 系统的 AFK 指令 21 | 剩余配置项在 Purpur 配置里""")); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/ConfigurableInventoryOverflowEvent.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.gameplay; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class ConfigurableInventoryOverflowEvent extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.GAMEPLAY.getBaseKeyName() + ".inventory-overflow-event"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | public static String listenerClass = "com.example.package.PlayerInventoryOverflowEvent"; 14 | 15 | @Override 16 | public void onLoaded() { 17 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled, config.pickStringRegionBased(""" 18 | The event called when used plugin to Inventory#addItem 19 | into player's inventory, and the inventory is full. 20 | This is not recommended to use, please re-design to use the 21 | returned map of Inventory#addItem method as soon as possible!""", 22 | """ 23 | 此事件将在插件使用 Inventory#addItem 方法 24 | 添加物品到玩家背包, 但是背包已满时调用. 25 | 不建议使用此事件,请尽快迁移至使用 Inventory#addItem 方法 26 | 返回的 map""")); 27 | listenerClass = config.getString(getBasePath() + ".listener-class", listenerClass, config.pickStringRegionBased(""" 28 | The full class name of the listener which listens to this inventory overflow event.""", 29 | """ 30 | 监听此物品栏物品溢出事件的完整类名.""")); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/ConfigurableMaxUseItemDistance.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.gameplay; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class ConfigurableMaxUseItemDistance extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.GAMEPLAY.getBaseKeyName() + ".player"; 10 | } 11 | 12 | public static double maxUseItemDistance = 1.0000001; 13 | 14 | @Override 15 | public void onLoaded() { 16 | maxUseItemDistance = config.getDouble(getBasePath() + ".max-use-item-distance", maxUseItemDistance, config.pickStringRegionBased(""" 17 | The max distance of UseItem for players. 18 | Set to -1 to disable max-distance-check. 19 | NOTE: if set to -1 to disable the check, 20 | players are able to use some packet modules of hack clients, 21 | and NoCom Exploit!!""", 22 | """ 23 | 玩家 UseItem 的最大距离. 24 | 设置为 -1 来禁用最大距离检测. 25 | 注意: 禁用此项后, 26 | 玩家可以使用作弊客户端的部分发包模块和 NoCom 漏洞!!""")); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/ConfigurableTripWireDupe.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.gameplay; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class ConfigurableTripWireDupe extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.GAMEPLAY.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".allow-tripwire-dupe", enabled); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/DeathItemDropKnockback.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.gameplay; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class DeathItemDropKnockback extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.GAMEPLAY.getBaseKeyName() + ".death-item-drop-knockback"; 10 | } 11 | 12 | public static boolean dropAround = true; 13 | public static double horizontalForce = 0.5; 14 | public static double verticalForce = 0.2; 15 | 16 | @Override 17 | public void onLoaded() { 18 | dropAround = config.getBoolean(getBasePath() + ".drop-around", dropAround, 19 | config.pickStringRegionBased( 20 | "If true, items will drop randomly around the player on death.", 21 | "如果为 “true”,物品会在玩家死亡时随机掉落在其周围." 22 | )); 23 | 24 | horizontalForce = config.getDouble(getBasePath() + ".horizontal-force", horizontalForce, 25 | config.pickStringRegionBased( 26 | "Base speed for horizontal velocity when randomly dropping items.", 27 | "随机掉落物品时水平速度的基本速度." 28 | )); 29 | 30 | verticalForce = config.getDouble(getBasePath() + ".vertical-force", verticalForce, 31 | config.pickStringRegionBased( 32 | "Upward motion for randomly dropped items.", 33 | "随机掉落物品的向上运动." 34 | )); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/OnlyPlayerPushable.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.gameplay; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class OnlyPlayerPushable extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.GAMEPLAY.getBaseKeyName() + ".only-player-pushable"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath(), enabled, config.pickStringRegionBased( 17 | "Enable to make only player pushable", 18 | "是否只允许玩家被实体推动" 19 | )); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/SmoothTeleport.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.gameplay; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | import org.dreeam.leaf.config.annotations.Experimental; 6 | 7 | public class SmoothTeleport extends ConfigModules { 8 | 9 | public String getBasePath() { 10 | return EnumConfigCategory.GAMEPLAY.getBaseKeyName() + ".smooth-teleport"; 11 | } 12 | 13 | @Experimental 14 | public static boolean enabled = false; 15 | 16 | @Override 17 | public void onLoaded() { 18 | enabled = config.getBoolean(getBasePath(), enabled, config.pickStringRegionBased(""" 19 | **Experimental feature** 20 | Whether to make a "smooth teleport" when players changing dimension. 21 | This requires original world and target world have same logical height to work.""", 22 | """ 23 | **实验性功能** 24 | 是否在玩家切换世界时尝试使用 "平滑传送". 25 | 此项要求源世界和目标世界逻辑高度相同才会生效.""" 26 | )); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/gameplay/UseSpigotItemMergingMech.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.gameplay; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class UseSpigotItemMergingMech extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.GAMEPLAY.getBaseKeyName() + ".use-spigot-item-merging-mechanism"; 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath(), enabled); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/misc/Cache.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.misc; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class Cache extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.MISC.getBaseKeyName() + ".cache"; 10 | } 11 | 12 | public static boolean cachePlayerProfileResult = false; 13 | public static int cachePlayerProfileResultTimeout = 1440; 14 | 15 | @Override 16 | public void onLoaded() { 17 | cachePlayerProfileResult = config.getBoolean(getBasePath() + ".cache-player-profile-result", cachePlayerProfileResult, config.pickStringRegionBased(""" 18 | Cache the player profile result on they first join. 19 | It's useful if Mojang's verification server is down.""", 20 | """ 21 | 玩家首次加入时缓存 PlayerProfile. 22 | 正版验证服务器宕机时非常有用.""")); 23 | cachePlayerProfileResultTimeout = config.getInt(getBasePath() + ".cache-player-profile-result-timeout", cachePlayerProfileResultTimeout, 24 | config.pickStringRegionBased( 25 | "The timeout of the cache. Unit: Minutes.", 26 | "缓存过期时间. 单位: 分钟." 27 | )); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/misc/Including5sIngetTPS.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.misc; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class Including5sIngetTPS extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.MISC.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".including-5s-in-get-tps", enabled); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/misc/LagCompensation.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.misc; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class LagCompensation extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.MISC.getBaseKeyName() + ".lag-compensation"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | public static boolean enableForWater = false; 14 | public static boolean enableForLava = false; 15 | 16 | @Override 17 | public void onLoaded() { 18 | config.addCommentRegionBased(getBasePath(), """ 19 | This section contains lag compensation features, 20 | which could ensure basic playing experience during a lag.""", 21 | """ 22 | 这部分包含滞后补偿功能, 23 | 可以在卡顿情况下保障基本游戏体验."""); 24 | 25 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled); 26 | enableForWater = config.getBoolean(getBasePath() + ".enable-for-water", enableForWater); 27 | enableForLava = config.getBoolean(getBasePath() + ".enable-for-lava", enableForLava); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/misc/RemoveChangeNonEditableSignWarning.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.misc; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class RemoveChangeNonEditableSignWarning extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.MISC.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".remove-change-non-editable-sign-warning", enabled, 17 | config.pickStringRegionBased( 18 | "Enable to prevent console spam.", 19 | "移除修改无法编辑的告示牌时输出的警告." 20 | )); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/misc/RemoveSpigotCheckBungee.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.misc; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class RemoveSpigotCheckBungee extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.MISC.getBaseKeyName() + ".remove-spigot-check-bungee-config"; 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath(), enabled, config.pickStringRegionBased(""" 17 | Enable player enter backend server through proxy 18 | without backend server enabling its bungee mode.""", 19 | """ 20 | 使服务器无需打开 bungee 模式即可让玩家加入后端服务器.""")); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/misc/RemoveVanillaUsernameCheck.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.misc; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class RemoveVanillaUsernameCheck extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.MISC.getBaseKeyName() + ".remove-vanilla-username-check"; 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath(), enabled, config.pickStringRegionBased(""" 17 | Remove Vanilla username check, 18 | allowing all characters as username.""", 19 | """ 20 | 移除原版的用户名验证, 21 | 让所有字符均可作为玩家名.""")); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/misc/SecureSeed.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.misc; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class SecureSeed extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.MISC.getBaseKeyName() + ".secure-seed"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | config.addCommentRegionBased(getBasePath(), """ 17 | Once you enable secure seed, all ores and structures are generated with 1024-bit seed 18 | instead of using 64-bit seed in vanilla, made seed cracker become impossible.""", 19 | """ 20 | 安全种子开启后, 所有矿物与结构都将使用1024位的种子进行生成, 无法被破解."""); 21 | 22 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/misc/ServerBrand.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.misc; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class ServerBrand extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.MISC.getBaseKeyName() + ".rebrand"; 10 | } 11 | 12 | public static String serverModName = io.papermc.paper.ServerBuildInfo.buildInfo().brandName(); 13 | public static String serverGUIName = io.papermc.paper.ServerBuildInfo.buildInfo().brandName() + " Console"; 14 | 15 | @Override 16 | public void onLoaded() { 17 | serverModName = config.getString(getBasePath() + ".server-mod-name", serverModName); 18 | serverGUIName = config.getString(getBasePath() + ".server-gui-name", serverGUIName); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/misc/UnknownCommandMessage.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.misc; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class UnknownCommandMessage extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.MISC.getBaseKeyName() + ".message"; 10 | } 11 | 12 | public static String unknownCommandMessage = "default"; 13 | 14 | @Override 15 | public void onLoaded() { 16 | unknownCommandMessage = config.getString(getBasePath() + ".unknown-command", unknownCommandMessage, config.pickStringRegionBased(""" 17 | Unknown command message, using MiniMessage format, set to "default" to use vanilla message, 18 | placeholder: 19 | , show message of the command exception. 20 | , shows detail of the command exception.""", 21 | """ 22 | 发送未知命令时的消息, 使用 MiniMessage 格式, 设置为 "default" 使用原版消息. 23 | 变量: 24 | , 显示命令错误所附提示消息. 25 | , 显示命令错误详细信息.""")); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/network/AlternativeJoin.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.network; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class AlternativeJoin extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.NETWORK.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".async-switch-state", enabled, config.pickStringRegionBased( 17 | "Async switch connection state.", 18 | "异步切换连接状态.")); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/network/ChatMessageSignature.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.network; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class ChatMessageSignature extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.NETWORK.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".chat-message-signature", enabled, config.pickStringRegionBased(""" 17 | Whether or not enable chat message signature, 18 | disable will prevent players to report chat messages. 19 | And also disables the popup when joining a server without 20 | 'secure chat', such as offline-mode servers.""", 21 | """ 22 | 是否启用聊天签名, 禁用后玩家无法进行聊天举报.""")); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/network/OptimizeNonFlushPacketSending.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.network; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class OptimizeNonFlushPacketSending extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.NETWORK.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".OptimizeNonFlushPacketSending", enabled, config.pickStringRegionBased(""" 17 | WARNING: This option is NOT compatible with ProtocolLib and may cause 18 | issues with other plugins that modify packet handling. 19 | 20 | Optimizes non-flush packet sending by using Netty's lazyExecute method to avoid 21 | expensive thread wakeup calls when scheduling packet operations. 22 | 23 | Requires server restart to take effect.""", 24 | """ 25 | 警告: 此选项与 ProtocolLib 不兼容, 并可能导致与其他修改数据包 26 | 处理的插件出现问题. 27 | 28 | 通过使用 Netty 的 lazyExecute 方法来优化非刷新数据包的发送, 29 | 避免在调度数据包操作时进行昂贵的线程唤醒调用. 30 | 31 | 需要重启服务器才能生效.""")); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/BrainRunningBehaviorCacheUpdate.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class BrainRunningBehaviorCacheUpdate extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static int interval = 5; 13 | 14 | @Override 15 | public void onLoaded() { 16 | interval = config.getInt(getBasePath() + ".entity-running-behavior-cache-update-interval", interval, 17 | config.pickStringRegionBased( 18 | "How often entity update current brain running behavior list.", 19 | "生物更新现有 Brain Behavior 列表缓存的间隔.")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/CheckSurvivalBeforeGrowth.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class CheckSurvivalBeforeGrowth extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName() + ".check-survival-before-growth"; 10 | } 11 | 12 | public static boolean cactusCheckSurvivalBeforeGrowth = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | cactusCheckSurvivalBeforeGrowth = config.getBoolean(getBasePath() + ".cactus-check-survival", cactusCheckSurvivalBeforeGrowth, 17 | config.pickStringRegionBased(""" 18 | Check if a cactus can survive before growing.""", 19 | """ 20 | 在仙人掌生长前检查其是否能够存活。""")); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/DontSaveEntity.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class DontSaveEntity extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName() + ".dont-save-entity"; 10 | } 11 | 12 | public static boolean dontSavePrimedTNT = false; 13 | public static boolean dontSaveFallingBlock = false; 14 | 15 | @Override 16 | public void onLoaded() { 17 | dontSavePrimedTNT = config.getBoolean(getBasePath() + ".dont-save-primed-tnt", dontSavePrimedTNT, 18 | config.pickStringRegionBased(""" 19 | Disable save primed tnt on chunk unloads. 20 | Useful for redstone/technical servers, can prevent machines from being exploded by TNT, 21 | when player disconnected caused by Internet issue.""", 22 | """ 23 | 区块卸载时不保存掉落的方块和激活的 TNT, 24 | 可以避免在玩家掉线时机器被炸毁.""")); 25 | dontSaveFallingBlock = config.getBoolean(getBasePath() + ".dont-save-falling-block", dontSaveFallingBlock); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/EnableCachedMTBEntityTypeConvert.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class EnableCachedMTBEntityTypeConvert extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".enable-cached-minecraft-to-bukkit-entitytype-convert", enabled, config.pickStringRegionBased(""" 17 | Whether to cache expensive CraftEntityType#minecraftToBukkit call.""", 18 | """ 19 | 是否缓存Minecraft到Bukkit的实体类型转换.""")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/EyeFluidCache.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class EyeFluidCache extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".cache-eye-fluid-status", enabled, 17 | config.pickStringRegionBased( 18 | "Whether to cache the isEyeInFluid method to improve performance and reduce memory usage.", 19 | "是否为 isEyeInFluid 方法启用缓存,以优化性能并减少内存使用.")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/FasterStructureGenFutureSequencing.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class FasterStructureGenFutureSequencing extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".faster-structure-gen-future-sequencing", enabled, 17 | config.pickStringRegionBased( 18 | "May cause the inconsistent order of future compose tasks.", 19 | "更快的结构生成任务分段.")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimiseBlockEntities.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class OptimiseBlockEntities extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".optimise-block-entities", enabled); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizeBiome.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class OptimizeBiome extends ConfigModules { 7 | public String getBasePath() { 8 | return EnumConfigCategory.PERF.getBaseKeyName() + ".cache-biome"; 9 | } 10 | 11 | public static boolean enabled = false; 12 | public static boolean mobSpawn = false; 13 | public static boolean advancement = false; 14 | 15 | @Override 16 | public void onLoaded() { 17 | enabled = config().getBoolean(getBasePath() + ".enabled", enabled); 18 | mobSpawn = config.getBoolean(getBasePath() + ".mob-spawning", false); 19 | advancement = config.getBoolean(getBasePath() + ".advancements", false); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizeItemTicking.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class OptimizeItemTicking extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean onlyTickItemsInHand = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | onlyTickItemsInHand = config.getBoolean(getBasePath() + ".only-tick-items-in-hand", onlyTickItemsInHand, config.pickStringRegionBased(""" 17 | Whether to only tick / update items in main hand and offhand instead of the entire inventory.""", 18 | """ 19 | 是否只对主手和副手中的物品进行 tick / 更新,而不是整个物品栏中的所有物品。""")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizePlayerMovementProcessing.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class OptimizePlayerMovementProcessing extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".optimize-player-movement", enabled, config.pickStringRegionBased(""" 17 | Whether to optimize player movement processing by skipping unnecessary edge checks and avoiding redundant view distance updates.""", 18 | """ 19 | 是否优化玩家移动处理,跳过不必要的边缘检查并避免冗余的视距更新。""")); 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizedPoweredRails.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class OptimizedPoweredRails extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName() + ".optimized-powered-rails"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config().getBoolean(getBasePath(), enabled); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/PreloadNaturalMobSpawning.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class PreloadNaturalMobSpawning extends ConfigModules { 7 | public String getBasePath() { 8 | return EnumConfigCategory.PERF.getBaseKeyName() + ".preload-mob-spawning-position"; 9 | } 10 | 11 | public static boolean enabled = false; 12 | 13 | @Override 14 | public void onLoaded() { 15 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/ReduceChunkSourceUpdates.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class ReduceChunkSourceUpdates extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName() + ".reduce-chunk-source-updates"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled, 17 | config.pickStringRegionBased( 18 | "Reduces chunk source updates on inter-chunk player moves. (Recommended to enable)", 19 | "减少玩家跨区块移动时的区块源更新。" 20 | ) 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/ReduceUselessPackets.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class ReduceUselessPackets extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName() + ".reduce-packets"; 10 | } 11 | 12 | public static boolean reduceUselessEntityMovePackets = false; 13 | 14 | @Override 15 | public void onLoaded() { 16 | reduceUselessEntityMovePackets = config.getBoolean(getBasePath() + ".reduce-entity-move-packets", reduceUselessEntityMovePackets); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/SkipAIForNonAwareMob.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class SkipAIForNonAwareMob extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".skip-ai-for-non-aware-mob", enabled); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/SkipMapItemDataUpdates.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class SkipMapItemDataUpdates extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".skip-map-item-data-updates-if-map-does-not-have-craftmaprenderer", enabled); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/ThrottleHopperWhenFull.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class ThrottleHopperWhenFull extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName() + ".throttle-hopper-when-full"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | public static int skipTicks = 8; 14 | 15 | @Override 16 | public void onLoaded() { 17 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled, config.pickStringRegionBased(""" 18 | Throttles the hopper if target container is full.""", 19 | """ 20 | 是否在目标容器已满时阻塞漏斗.""")); 21 | skipTicks = config.getInt(getBasePath() + ".skip-ticks", skipTicks, config.pickStringRegionBased(""" 22 | How many ticks to throttle when the Hopper is throttled.""", 23 | """ 24 | 每次阻塞多少 tick.""")); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/ThrottleInactiveGoalSelectorTick.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class ThrottleInactiveGoalSelectorTick extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".inactive-goal-selector-throttle", enabled, config.pickStringRegionBased(""" 17 | Throttles the AI goal selector in entity inactive ticks. 18 | This can improve performance by a few percent, but has minor gameplay implications.""", 19 | """ 20 | 是否在实体不活跃 tick 时阻塞 AI 目标选择器. 21 | 有助于提升性能, 但对游戏有轻微影响.""")); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/ThrottleNaturalMobSpawning.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import net.minecraft.world.entity.MobCategory; 4 | import org.dreeam.leaf.config.ConfigModules; 5 | import org.dreeam.leaf.config.EnumConfigCategory; 6 | 7 | public class ThrottleNaturalMobSpawning extends ConfigModules { 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName() + ".throttle-mob-spawning"; 10 | } 11 | 12 | public static boolean enabled = false; 13 | public static long[] failedAttempts; 14 | public static int[] spawnChance; 15 | 16 | @Override 17 | public void onLoaded() { 18 | enabled = config.getBoolean(getBasePath() + ".enabled", enabled); 19 | MobCategory[] categories = MobCategory.values(); 20 | failedAttempts = new long[categories.length]; 21 | spawnChance = new int[categories.length]; 22 | for (int i = 0; i < categories.length; i++) { 23 | String category = getBasePath() + "." + categories[i].getSerializedName(); 24 | long attempts = config.getLong(category + ".min-failed", 8); 25 | double chance = config.getDouble(category + ".spawn-chance", 25.0); 26 | 27 | failedAttempts[i] = Math.max(-1, attempts); 28 | spawnChance[i] = Math.clamp(0, (int) Math.round(chance * 10.24), 1024); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/TileEntitySnapshotCreation.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class TileEntitySnapshotCreation extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".create-snapshot-on-retrieving-blockstate", enabled); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/VT4BukkitScheduler.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class VT4BukkitScheduler extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".use-virtual-thread-for-async-scheduler", enabled, 17 | config.pickStringRegionBased( 18 | "Use the new Virtual Thread introduced in JDK 21 for CraftAsyncScheduler.", 19 | "是否为异步任务调度器使用虚拟线程.")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/VT4ChatExecutor.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class VT4ChatExecutor extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".use-virtual-thread-for-async-chat-executor", enabled, 17 | config.pickStringRegionBased( 18 | "Use the new Virtual Thread introduced in JDK 21 for Async Chat Executor.", 19 | "是否为异步聊天线程使用虚拟线程.")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/VT4DownloadPool.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class VT4DownloadPool extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".use-virtual-thread-for-download-pool", enabled, 17 | config.pickStringRegionBased( 18 | "Use the new Virtual Thread introduced in JDK 21 for download worker pool.", 19 | "是否为下载工作线程池使用虚拟线程(如果可用)。")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/VT4ProfileExecutor.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class VT4ProfileExecutor extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".use-virtual-thread-for-profile-executor", enabled, 17 | config.pickStringRegionBased( 18 | "Use the new Virtual Thread introduced in JDK 21 for profile lookup executor.", 19 | "是否为档案查询执行器使用虚拟线程(如果可用)。")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/VT4UserAuthenticator.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.config.modules.opt; 2 | 3 | import org.dreeam.leaf.config.ConfigModules; 4 | import org.dreeam.leaf.config.EnumConfigCategory; 5 | 6 | public class VT4UserAuthenticator extends ConfigModules { 7 | 8 | public String getBasePath() { 9 | return EnumConfigCategory.PERF.getBaseKeyName(); 10 | } 11 | 12 | public static boolean enabled = true; 13 | 14 | @Override 15 | public void onLoaded() { 16 | enabled = config.getBoolean(getBasePath() + ".use-virtual-thread-for-user-authenticator", enabled, 17 | config.pickStringRegionBased( 18 | "Use the new Virtual Thread introduced in JDK 21 for User Authenticator.", 19 | "是否为用户验证器使用虚拟线程.")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/protocol/LeafCustomPayload.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.protocol; 2 | 3 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public interface LeafCustomPayload extends CustomPacketPayload { 7 | 8 | @NotNull 9 | @Override 10 | Type type(); 11 | } 12 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/protocol/Protocol.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.protocol; 2 | 3 | import net.minecraft.network.FriendlyByteBuf; 4 | import net.minecraft.server.MinecraftServer; 5 | import net.minecraft.server.level.ServerPlayer; 6 | 7 | import java.util.List; 8 | 9 | interface Protocol { 10 | 11 | String namespace(); 12 | 13 | List> c2s(); 14 | 15 | List> s2c(); 16 | 17 | void tickServer(MinecraftServer server); 18 | 19 | void tickPlayer(ServerPlayer player); 20 | 21 | void disconnected(ServerPlayer conn); 22 | 23 | void handle(ServerPlayer player, LeafCustomPayload payload); 24 | } 25 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/util/cache/CachedOrNewBitsGetter.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.util.cache; 2 | 3 | import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; 4 | 5 | import java.util.BitSet; 6 | import java.util.function.IntFunction; 7 | 8 | public class CachedOrNewBitsGetter { 9 | 10 | private static final IntFunction BITSET_CONSTRUCTOR = BitSet::new; 11 | private static final ThreadLocal> BITSETS = ThreadLocal.withInitial(Int2ObjectOpenHashMap::new); 12 | 13 | private CachedOrNewBitsGetter() { 14 | } 15 | 16 | public static BitSet getCachedOrNewBitSet(int bits) { 17 | final BitSet bitSet = BITSETS.get().computeIfAbsent(bits, BITSET_CONSTRUCTOR); 18 | 19 | bitSet.clear(); 20 | 21 | return bitSet; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/version/LeafVersionFetcher.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.version; 2 | 3 | import org.galemc.gale.version.AbstractPaperVersionFetcher; 4 | 5 | public class LeafVersionFetcher extends AbstractPaperVersionFetcher { 6 | 7 | public LeafVersionFetcher() { 8 | super( 9 | "https://www.leafmc.one/download", 10 | "Winds Studio", 11 | "Leaf", 12 | "Winds-Studio", 13 | "Leaf" 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/dreeam/leaf/world/biome/PositionalBiomeGetter.java: -------------------------------------------------------------------------------- 1 | package org.dreeam.leaf.world.biome; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.core.Holder; 5 | import net.minecraft.world.level.biome.Biome; 6 | 7 | import java.util.function.Function; 8 | import java.util.function.Supplier; 9 | 10 | public class PositionalBiomeGetter implements Supplier> { 11 | 12 | private final Function> biomeGetter; 13 | private final BlockPos.MutableBlockPos pos; 14 | private int nextX, nextY, nextZ; 15 | private volatile Holder curBiome; 16 | 17 | public PositionalBiomeGetter(Function> biomeGetter, BlockPos.MutableBlockPos pos) { 18 | this.biomeGetter = biomeGetter; 19 | this.pos = pos; 20 | } 21 | 22 | public void update(int nextX, int nextY, int nextZ) { 23 | this.nextX = nextX; 24 | this.nextY = nextY; 25 | this.nextZ = nextZ; 26 | this.curBiome = null; 27 | } 28 | 29 | @Override 30 | public Holder get() { 31 | Holder biome = curBiome; 32 | if (biome == null) { 33 | curBiome = biome = biomeGetter.apply(pos.set(nextX, nextY, nextZ)); 34 | } 35 | return biome; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/LeavesLogger.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves; 2 | 3 | import org.bukkit.Bukkit; 4 | 5 | import java.util.logging.Level; 6 | import java.util.logging.Logger; 7 | 8 | public class LeavesLogger extends Logger { 9 | 10 | public static final LeavesLogger LOGGER = new LeavesLogger(); 11 | 12 | private LeavesLogger() { 13 | super("Leaves", null); 14 | setParent(Bukkit.getLogger()); 15 | setLevel(Level.ALL); 16 | } 17 | 18 | public void severe(String msg, Exception exception) { 19 | this.log(Level.SEVERE, msg, exception); 20 | } 21 | 22 | public void warning(String msg, Exception exception) { 23 | this.log(Level.WARNING, msg, exception); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/bot/BotStatsCounter.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.bot; 2 | 3 | import com.mojang.datafixers.DataFixer; 4 | import net.minecraft.server.MinecraftServer; 5 | import net.minecraft.stats.ServerStatsCounter; 6 | import net.minecraft.stats.Stat; 7 | import net.minecraft.world.entity.player.Player; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | import java.io.File; 11 | 12 | public class BotStatsCounter extends ServerStatsCounter { 13 | 14 | private static final File UNKOWN_FILE = new File("BOT_STATS_REMOVE_THIS"); 15 | 16 | public BotStatsCounter(MinecraftServer server) { 17 | super(server, UNKOWN_FILE); 18 | } 19 | 20 | @Override 21 | public void save() { 22 | } 23 | 24 | @Override 25 | public void setValue(@NotNull Player player, @NotNull Stat stat, int value) { 26 | } 27 | 28 | @Override 29 | public void parseLocal(@NotNull DataFixer dataFixer, @NotNull String json) { 30 | } 31 | 32 | @Override 33 | public int getValue(@NotNull Stat stat) { 34 | return 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageIndex.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.chatimage; 2 | 3 | public class ChatImageIndex { 4 | 5 | public int index; 6 | public int total; 7 | public String url; 8 | public String bytes; 9 | 10 | public ChatImageIndex(int index, int total, String url, String bytes) { 11 | this.index = index; 12 | this.total = total; 13 | this.url = url; 14 | this.bytes = bytes; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesCustomPayload.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.core; 2 | 3 | import net.minecraft.network.FriendlyByteBuf; 4 | import net.minecraft.network.protocol.common.custom.CustomPacketPayload; 5 | import net.minecraft.resources.ResourceLocation; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.lang.annotation.ElementType; 9 | import java.lang.annotation.Retention; 10 | import java.lang.annotation.RetentionPolicy; 11 | import java.lang.annotation.Target; 12 | 13 | public interface LeavesCustomPayload> extends CustomPacketPayload { 14 | 15 | @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @interface New { 18 | } 19 | 20 | void write(FriendlyByteBuf buf); 21 | 22 | ResourceLocation id(); 23 | 24 | @Override 25 | @NotNull 26 | default Type type() { 27 | return new CustomPacketPayload.Type<>(id()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocol.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.core; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface LeavesProtocol { 11 | String[] namespace(); 12 | } 13 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolHandler.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.core; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | public class ProtocolHandler { 9 | 10 | @Target(ElementType.METHOD) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | public @interface Init { 13 | } 14 | 15 | @Target(ElementType.METHOD) 16 | @Retention(RetentionPolicy.RUNTIME) 17 | public @interface PayloadReceiver { 18 | Class> payload(); 19 | 20 | String[] payloadId() default ""; 21 | 22 | boolean ignoreId() default false; 23 | 24 | boolean sendFabricRegister() default true; 25 | } 26 | 27 | @Target(ElementType.METHOD) 28 | @Retention(RetentionPolicy.RUNTIME) 29 | public @interface Ticker { 30 | int delay() default 0; 31 | } 32 | 33 | @Target(ElementType.METHOD) 34 | @Retention(RetentionPolicy.RUNTIME) 35 | public @interface PlayerJoin { 36 | } 37 | 38 | @Target(ElementType.METHOD) 39 | @Retention(RetentionPolicy.RUNTIME) 40 | public @interface PlayerLeave { 41 | } 42 | 43 | @Target(ElementType.METHOD) 44 | @Retention(RetentionPolicy.RUNTIME) 45 | public @interface ReloadServer { 46 | } 47 | 48 | @Target(ElementType.METHOD) 49 | @Retention(RetentionPolicy.RUNTIME) 50 | public @interface MinecraftRegister { 51 | 52 | String[] channelId() default ""; 53 | 54 | boolean ignoreId() default false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.accessor; 2 | 3 | import net.minecraft.nbt.Tag; 4 | import net.minecraft.network.RegistryFriendlyByteBuf; 5 | import net.minecraft.network.codec.StreamEncoder; 6 | import net.minecraft.world.entity.player.Player; 7 | import net.minecraft.world.level.Level; 8 | import net.minecraft.world.phys.HitResult; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public interface Accessor { 12 | 13 | Level getLevel(); 14 | 15 | Player getPlayer(); 16 | 17 | Tag encodeAsNbt(StreamEncoder codec, D value); 18 | 19 | T getHitResult(); 20 | 21 | /** 22 | * @return {@code true} if the dedicated server has Jade installed. 23 | */ 24 | boolean isServerConnected(); 25 | 26 | boolean showDetails(); 27 | 28 | @Nullable 29 | Object getTarget(); 30 | 31 | float tickRate(); 32 | } 33 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessor.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.accessor; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.core.Direction; 5 | import net.minecraft.world.entity.player.Player; 6 | import net.minecraft.world.level.Level; 7 | import net.minecraft.world.level.block.Block; 8 | import net.minecraft.world.level.block.entity.BlockEntity; 9 | import net.minecraft.world.level.block.state.BlockState; 10 | import net.minecraft.world.phys.BlockHitResult; 11 | import org.jetbrains.annotations.ApiStatus; 12 | 13 | import java.util.function.Supplier; 14 | 15 | public interface BlockAccessor extends Accessor { 16 | 17 | Block getBlock(); 18 | 19 | BlockState getBlockState(); 20 | 21 | BlockEntity getBlockEntity(); 22 | 23 | BlockPos getPosition(); 24 | 25 | Direction getSide(); 26 | 27 | @ApiStatus.NonExtendable 28 | interface Builder { 29 | Builder level(Level level); 30 | 31 | Builder player(Player player); 32 | 33 | Builder showDetails(boolean showDetails); 34 | 35 | Builder hit(BlockHitResult hit); 36 | 37 | Builder blockState(BlockState state); 38 | 39 | default Builder blockEntity(BlockEntity blockEntity) { 40 | return blockEntity(() -> blockEntity); 41 | } 42 | 43 | Builder blockEntity(Supplier blockEntity); 44 | 45 | Builder from(BlockAccessor accessor); 46 | 47 | BlockAccessor build(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessor.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.accessor; 2 | 3 | import net.minecraft.world.entity.Entity; 4 | import net.minecraft.world.entity.player.Player; 5 | import net.minecraft.world.level.Level; 6 | import net.minecraft.world.phys.EntityHitResult; 7 | import org.jetbrains.annotations.ApiStatus; 8 | 9 | import java.util.function.Supplier; 10 | 11 | public interface EntityAccessor extends Accessor { 12 | 13 | Entity getEntity(); 14 | 15 | /** 16 | * For part entity like ender dragon's, getEntity() will return the parent entity. 17 | */ 18 | Entity getRawEntity(); 19 | 20 | @ApiStatus.NonExtendable 21 | interface Builder { 22 | Builder level(Level level); 23 | 24 | Builder player(Player player); 25 | 26 | Builder showDetails(boolean showDetails); 27 | 28 | default Builder hit(EntityHitResult hit) { 29 | return hit(() -> hit); 30 | } 31 | 32 | Builder hit(Supplier hit); 33 | 34 | default Builder entity(Entity entity) { 35 | return entity(() -> entity); 36 | } 37 | 38 | Builder entity(Supplier entity); 39 | 40 | Builder from(EntityAccessor accessor); 41 | 42 | EntityAccessor build(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ClientHandshakePayload.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.payload; 2 | 3 | import net.minecraft.network.FriendlyByteBuf; 4 | import net.minecraft.network.RegistryFriendlyByteBuf; 5 | import net.minecraft.network.codec.ByteBufCodecs; 6 | import net.minecraft.network.codec.StreamCodec; 7 | import net.minecraft.resources.ResourceLocation; 8 | import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; 9 | import org.leavesmc.leaves.protocol.core.ProtocolUtils; 10 | import org.leavesmc.leaves.protocol.jade.JadeProtocol; 11 | 12 | public record ClientHandshakePayload(String protocolVersion) implements LeavesCustomPayload { 13 | 14 | private static final ResourceLocation PACKET_CLIENT_HANDSHAKE = JadeProtocol.id("client_handshake"); 15 | 16 | private static final StreamCodec CODEC = StreamCodec.composite( 17 | ByteBufCodecs.STRING_UTF8, 18 | ClientHandshakePayload::protocolVersion, 19 | ClientHandshakePayload::new); 20 | 21 | @Override 22 | public void write(FriendlyByteBuf buf) { 23 | CODEC.encode(ProtocolUtils.decorate(buf), this); 24 | } 25 | 26 | @Override 27 | public ResourceLocation id() { 28 | return PACKET_CLIENT_HANDSHAKE; 29 | } 30 | 31 | @New 32 | public static ClientHandshakePayload create(ResourceLocation location, FriendlyByteBuf buf) { 33 | return CODEC.decode(ProtocolUtils.decorate(buf)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ReceiveDataPayload.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.payload; 2 | 3 | import net.minecraft.nbt.CompoundTag; 4 | import net.minecraft.network.FriendlyByteBuf; 5 | import net.minecraft.resources.ResourceLocation; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; 8 | import org.leavesmc.leaves.protocol.jade.JadeProtocol; 9 | 10 | public record ReceiveDataPayload(CompoundTag tag) implements LeavesCustomPayload { 11 | 12 | private static final ResourceLocation PACKET_RECEIVE_DATA = JadeProtocol.id("receive_data"); 13 | 14 | @New 15 | public ReceiveDataPayload(ResourceLocation id, FriendlyByteBuf buf) { 16 | this(buf.readNbt()); 17 | } 18 | 19 | @Override 20 | public void write(@NotNull FriendlyByteBuf buf) { 21 | buf.writeNbt(tag); 22 | } 23 | 24 | @Override 25 | public ResourceLocation id() { 26 | return PACKET_RECEIVE_DATA; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IJadeProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider; 2 | 3 | import net.minecraft.resources.ResourceLocation; 4 | 5 | public interface IJadeProvider { 6 | 7 | ResourceLocation getUid(); 8 | 9 | default int getDefaultPriority() { 10 | return 0; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IServerDataProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider; 2 | 3 | import net.minecraft.nbt.CompoundTag; 4 | import org.leavesmc.leaves.protocol.jade.accessor.Accessor; 5 | 6 | public interface IServerDataProvider> extends IJadeProvider { 7 | void appendServerData(CompoundTag data, T accessor); 8 | } 9 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IServerExtensionProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider; 2 | 3 | import org.leavesmc.leaves.protocol.jade.accessor.Accessor; 4 | import org.leavesmc.leaves.protocol.jade.util.ViewGroup; 5 | 6 | import java.util.List; 7 | 8 | public interface IServerExtensionProvider extends IJadeProvider { 9 | List> getGroups(Accessor request); 10 | } -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/StreamServerDataProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider; 2 | 3 | import net.minecraft.nbt.CompoundTag; 4 | import net.minecraft.nbt.Tag; 5 | import net.minecraft.network.RegistryFriendlyByteBuf; 6 | import net.minecraft.network.codec.StreamCodec; 7 | import org.jetbrains.annotations.Nullable; 8 | import org.leavesmc.leaves.protocol.jade.accessor.Accessor; 9 | 10 | import java.util.Optional; 11 | 12 | public interface StreamServerDataProvider, D> extends IServerDataProvider { 13 | 14 | @Override 15 | default void appendServerData(CompoundTag data, T accessor) { 16 | D value = streamData(accessor); 17 | if (value != null) { 18 | data.put(getUid().toString(), accessor.encodeAsNbt(streamCodec(), value)); 19 | } 20 | } 21 | 22 | @Nullable 23 | D streamData(T accessor); 24 | 25 | StreamCodec streamCodec(); 26 | } 27 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/BeehiveProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider.block; 2 | 3 | import net.minecraft.network.RegistryFriendlyByteBuf; 4 | import net.minecraft.network.codec.ByteBufCodecs; 5 | import net.minecraft.network.codec.StreamCodec; 6 | import net.minecraft.resources.ResourceLocation; 7 | import net.minecraft.world.level.block.entity.BeehiveBlockEntity; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.leavesmc.leaves.protocol.jade.JadeProtocol; 10 | import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; 11 | import org.leavesmc.leaves.protocol.jade.provider.StreamServerDataProvider; 12 | 13 | public enum BeehiveProvider implements StreamServerDataProvider { 14 | INSTANCE; 15 | 16 | private static final ResourceLocation MC_BEEHIVE = JadeProtocol.mc_id("beehive"); 17 | 18 | @Override 19 | public @NotNull StreamCodec streamCodec() { 20 | return ByteBufCodecs.BYTE.cast(); 21 | } 22 | 23 | @Override 24 | public Byte streamData(@NotNull BlockAccessor accessor) { 25 | BeehiveBlockEntity beehive = (BeehiveBlockEntity) accessor.getBlockEntity(); 26 | int bees = beehive.getOccupantCount(); 27 | return (byte) (beehive.isFull() ? bees : -bees); 28 | } 29 | 30 | @Override 31 | public ResourceLocation getUid() { 32 | return MC_BEEHIVE; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/HopperLockProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider.block; 2 | 3 | import net.minecraft.network.RegistryFriendlyByteBuf; 4 | import net.minecraft.network.codec.ByteBufCodecs; 5 | import net.minecraft.network.codec.StreamCodec; 6 | import net.minecraft.resources.ResourceLocation; 7 | import net.minecraft.world.level.block.state.properties.BlockStateProperties; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.leavesmc.leaves.protocol.jade.JadeProtocol; 10 | import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; 11 | import org.leavesmc.leaves.protocol.jade.provider.StreamServerDataProvider; 12 | 13 | public enum HopperLockProvider implements StreamServerDataProvider { 14 | INSTANCE; 15 | 16 | private static final ResourceLocation MC_HOPPER_LOCK = JadeProtocol.mc_id("hopper_lock"); 17 | 18 | @Override 19 | public Boolean streamData(@NotNull BlockAccessor accessor) { 20 | return !accessor.getBlockState().getValue(BlockStateProperties.ENABLED); 21 | } 22 | 23 | @Override 24 | public @NotNull StreamCodec streamCodec() { 25 | return ByteBufCodecs.BOOL.cast(); 26 | } 27 | 28 | @Override 29 | public ResourceLocation getUid() { 30 | return MC_HOPPER_LOCK; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/JukeboxProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider.block; 2 | 3 | import net.minecraft.network.RegistryFriendlyByteBuf; 4 | import net.minecraft.network.codec.StreamCodec; 5 | import net.minecraft.resources.ResourceLocation; 6 | import net.minecraft.world.item.ItemStack; 7 | import net.minecraft.world.level.block.entity.JukeboxBlockEntity; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.leavesmc.leaves.protocol.jade.JadeProtocol; 10 | import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; 11 | import org.leavesmc.leaves.protocol.jade.provider.StreamServerDataProvider; 12 | 13 | public enum JukeboxProvider implements StreamServerDataProvider { 14 | INSTANCE; 15 | 16 | private static final ResourceLocation MC_JUKEBOX = JadeProtocol.mc_id("jukebox"); 17 | 18 | @Override 19 | public @NotNull ItemStack streamData(BlockAccessor accessor) { 20 | return ((JukeboxBlockEntity) accessor.getBlockEntity()).getTheItem(); 21 | } 22 | 23 | @Override 24 | public StreamCodec streamCodec() { 25 | return ItemStack.OPTIONAL_STREAM_CODEC; 26 | } 27 | 28 | @Override 29 | public ResourceLocation getUid() { 30 | return MC_JUKEBOX; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/LecternProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider.block; 2 | 3 | import net.minecraft.network.RegistryFriendlyByteBuf; 4 | import net.minecraft.network.codec.StreamCodec; 5 | import net.minecraft.resources.ResourceLocation; 6 | import net.minecraft.world.item.ItemStack; 7 | import net.minecraft.world.level.block.entity.LecternBlockEntity; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.leavesmc.leaves.protocol.jade.JadeProtocol; 10 | import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; 11 | import org.leavesmc.leaves.protocol.jade.provider.StreamServerDataProvider; 12 | 13 | public enum LecternProvider implements StreamServerDataProvider { 14 | INSTANCE; 15 | 16 | private static final ResourceLocation MC_LECTERN = JadeProtocol.mc_id("lectern"); 17 | 18 | @Override 19 | public @NotNull ItemStack streamData(@NotNull BlockAccessor accessor) { 20 | return ((LecternBlockEntity) accessor.getBlockEntity()).getBook(); 21 | } 22 | 23 | @Override 24 | public StreamCodec streamCodec() { 25 | return ItemStack.OPTIONAL_STREAM_CODEC; 26 | } 27 | 28 | 29 | @Override 30 | public ResourceLocation getUid() { 31 | return MC_LECTERN; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/NextEntityDropProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider.entity; 2 | 3 | import net.minecraft.nbt.CompoundTag; 4 | import net.minecraft.resources.ResourceLocation; 5 | import net.minecraft.world.entity.animal.Chicken; 6 | import net.minecraft.world.entity.animal.armadillo.Armadillo; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.leavesmc.leaves.protocol.jade.JadeProtocol; 9 | import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessor; 10 | import org.leavesmc.leaves.protocol.jade.provider.IServerDataProvider; 11 | 12 | public enum NextEntityDropProvider implements IServerDataProvider { 13 | INSTANCE; 14 | 15 | private static final ResourceLocation MC_NEXT_ENTITY_DROP = JadeProtocol.mc_id("next_entity_drop"); 16 | 17 | @Override 18 | public void appendServerData(CompoundTag tag, @NotNull EntityAccessor accessor) { 19 | int max = 24000 * 2; 20 | if (accessor.getEntity() instanceof Chicken chicken) { 21 | if (!chicken.isBaby() && chicken.eggTime < max) { 22 | tag.putInt("NextEggIn", chicken.eggTime); 23 | } 24 | } else if (accessor.getEntity() instanceof Armadillo armadillo) { 25 | if (!armadillo.isBaby() && armadillo.scuteTime < max) { 26 | tag.putInt("NextScuteIn", armadillo.scuteTime); 27 | } 28 | } 29 | } 30 | 31 | @Override 32 | public ResourceLocation getUid() { 33 | return MC_NEXT_ENTITY_DROP; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/PetArmorProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider.entity; 2 | 3 | import net.minecraft.network.RegistryFriendlyByteBuf; 4 | import net.minecraft.network.codec.StreamCodec; 5 | import net.minecraft.resources.ResourceLocation; 6 | import net.minecraft.world.entity.Mob; 7 | import net.minecraft.world.item.ItemStack; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | import org.leavesmc.leaves.protocol.jade.JadeProtocol; 11 | import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessor; 12 | import org.leavesmc.leaves.protocol.jade.provider.StreamServerDataProvider; 13 | 14 | public enum PetArmorProvider implements StreamServerDataProvider { 15 | INSTANCE; 16 | 17 | private static final ResourceLocation MC_PET_ARMOR = JadeProtocol.mc_id("pet_armor"); 18 | 19 | @Nullable 20 | @Override 21 | public ItemStack streamData(@NotNull EntityAccessor accessor) { 22 | ItemStack armor = ((Mob) accessor.getEntity()).getBodyArmorItem(); 23 | return armor.isEmpty() ? null : armor; 24 | } 25 | 26 | @Override 27 | public StreamCodec streamCodec() { 28 | return ItemStack.OPTIONAL_STREAM_CODEC; 29 | } 30 | 31 | @Override 32 | public ResourceLocation getUid() { 33 | return MC_PET_ARMOR; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/ZombieVillagerProvider.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.provider.entity; 2 | 3 | import net.minecraft.network.RegistryFriendlyByteBuf; 4 | import net.minecraft.network.codec.ByteBufCodecs; 5 | import net.minecraft.network.codec.StreamCodec; 6 | import net.minecraft.resources.ResourceLocation; 7 | import net.minecraft.world.entity.monster.ZombieVillager; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | import org.leavesmc.leaves.protocol.jade.JadeProtocol; 11 | import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessor; 12 | import org.leavesmc.leaves.protocol.jade.provider.StreamServerDataProvider; 13 | 14 | public enum ZombieVillagerProvider implements StreamServerDataProvider { 15 | INSTANCE; 16 | 17 | private static final ResourceLocation MC_ZOMBIE_VILLAGER = JadeProtocol.mc_id("zombie_villager"); 18 | 19 | @Override 20 | public @Nullable Integer streamData(@NotNull EntityAccessor accessor) { 21 | int time = ((ZombieVillager) accessor.getEntity()).villagerConversionTime; 22 | return time > 0 ? time : null; 23 | } 24 | 25 | @Override 26 | public @NotNull StreamCodec streamCodec() { 27 | return ByteBufCodecs.VAR_INT.cast(); 28 | } 29 | 30 | @Override 31 | public ResourceLocation getUid() { 32 | return MC_ZOMBIE_VILLAGER; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/ShearsToolHandler.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.tool; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraft.world.item.Items; 6 | import net.minecraft.world.level.Level; 7 | import net.minecraft.world.level.block.Blocks; 8 | import net.minecraft.world.level.block.state.BlockState; 9 | import org.leavesmc.leaves.protocol.jade.JadeProtocol; 10 | 11 | import java.util.List; 12 | 13 | public class ShearsToolHandler extends SimpleToolHandler { 14 | 15 | private static final ShearsToolHandler INSTANCE = new ShearsToolHandler(); 16 | 17 | public static ShearsToolHandler getInstance() { 18 | return INSTANCE; 19 | } 20 | 21 | public ShearsToolHandler() { 22 | super(JadeProtocol.id("shears"), List.of(Items.SHEARS.getDefaultInstance()), true); 23 | } 24 | 25 | @Override 26 | public ItemStack test(BlockState state, Level world, BlockPos pos) { 27 | if (state.is(Blocks.TRIPWIRE)) { 28 | return tools.getFirst(); 29 | } 30 | return super.test(state, world, pos); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/ToolHandler.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.tool; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.world.item.ItemStack; 5 | import net.minecraft.world.level.Level; 6 | import net.minecraft.world.level.block.state.BlockState; 7 | import org.leavesmc.leaves.protocol.jade.provider.IJadeProvider; 8 | 9 | import java.util.List; 10 | 11 | public interface ToolHandler extends IJadeProvider { 12 | 13 | ItemStack test(BlockState state, Level world, BlockPos pos); 14 | 15 | List getTools(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/PriorityStore.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.jade.util; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; 4 | import it.unimi.dsi.fastutil.objects.Object2IntMap; 5 | 6 | import java.util.Objects; 7 | import java.util.function.Function; 8 | import java.util.function.ToIntFunction; 9 | 10 | public class PriorityStore { 11 | 12 | private final Object2IntMap priorities = new Object2IntLinkedOpenHashMap<>(); 13 | private final Function keyGetter; 14 | private final ToIntFunction defaultPriorityGetter; 15 | 16 | public PriorityStore(ToIntFunction defaultPriorityGetter, Function keyGetter) { 17 | this.defaultPriorityGetter = defaultPriorityGetter; 18 | this.keyGetter = keyGetter; 19 | } 20 | 21 | public void put(V provider) { 22 | Objects.requireNonNull(provider); 23 | put(provider, defaultPriorityGetter.applyAsInt(provider)); 24 | } 25 | 26 | public void put(V provider, int priority) { 27 | Objects.requireNonNull(provider); 28 | K uid = keyGetter.apply(provider); 29 | Objects.requireNonNull(uid); 30 | priorities.put(uid, priority); 31 | } 32 | 33 | public int byValue(V value) { 34 | return byKey(keyGetter.apply(value)); 35 | } 36 | 37 | public int byKey(K id) { 38 | return priorities.getInt(id); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/Feature.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.syncmatica; 2 | 3 | import org.jetbrains.annotations.Nullable; 4 | 5 | public enum Feature { 6 | CORE, 7 | FEATURE, 8 | MODIFY, 9 | MESSAGE, 10 | QUOTA, 11 | DEBUG, 12 | CORE_EX; 13 | 14 | @Nullable 15 | public static Feature fromString(final String s) { 16 | for (final Feature f : Feature.values()) { 17 | if (f.toString().equals(s)) { 18 | return f; 19 | } 20 | } 21 | return null; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/LocalLitematicState.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.syncmatica; 2 | 3 | public enum LocalLitematicState { 4 | NO_LOCAL_LITEMATIC(true, false), 5 | LOCAL_LITEMATIC_DESYNC(true, false), 6 | DOWNLOADING_LITEMATIC(false, false), 7 | LOCAL_LITEMATIC_PRESENT(false, true); 8 | 9 | private final boolean downloadReady; 10 | private final boolean fileReady; 11 | 12 | LocalLitematicState(final boolean downloadReady, final boolean fileReady) { 13 | this.downloadReady = downloadReady; 14 | this.fileReady = fileReady; 15 | } 16 | 17 | public boolean isReadyForDownload() { 18 | return downloadReady; 19 | } 20 | 21 | public boolean isLocalFileReady() { 22 | return fileReady; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/MessageType.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.syncmatica; 2 | 3 | public enum MessageType { 4 | SUCCESS, 5 | INFO, 6 | WARNING, 7 | ERROR 8 | } 9 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/PacketType.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.syncmatica; 2 | 3 | import net.minecraft.resources.ResourceLocation; 4 | 5 | public enum PacketType { 6 | REGISTER_METADATA("register_metadata"), 7 | CANCEL_SHARE("cancel_share"), 8 | REQUEST_LITEMATIC("request_download"), 9 | SEND_LITEMATIC("send_litematic"), 10 | RECEIVED_LITEMATIC("received_litematic"), 11 | FINISHED_LITEMATIC("finished_litematic"), 12 | CANCEL_LITEMATIC("cancel_litematic"), 13 | REMOVE_SYNCMATIC("remove_syncmatic"), 14 | REGISTER_VERSION("register_version"), 15 | CONFIRM_USER("confirm_user"), 16 | FEATURE_REQUEST("feature_request"), 17 | FEATURE("feature"), 18 | MODIFY("modify"), 19 | MODIFY_REQUEST("modify_request"), 20 | MODIFY_REQUEST_DENY("modify_request_deny"), 21 | MODIFY_REQUEST_ACCEPT("modify_request_accept"), 22 | MODIFY_FINISH("modify_finish"), 23 | MESSAGE("mesage"); 24 | 25 | public final ResourceLocation identifier; 26 | 27 | PacketType(final String id) { 28 | identifier = ResourceLocation.tryBuild(SyncmaticaProtocol.PROTOCOL_ID, id); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/PlayerIdentifier.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.syncmatica; 2 | 3 | import com.google.gson.JsonObject; 4 | import com.google.gson.JsonPrimitive; 5 | 6 | import java.util.UUID; 7 | 8 | public class PlayerIdentifier { 9 | 10 | public static final UUID MISSING_PLAYER_UUID = UUID.fromString("4c1b738f-56fa-4011-8273-498c972424ea"); 11 | public static final PlayerIdentifier MISSING_PLAYER = new PlayerIdentifier(MISSING_PLAYER_UUID, "No Player"); 12 | 13 | public final UUID uuid; 14 | private String bufferedPlayerName; 15 | 16 | PlayerIdentifier(final UUID uuid, final String bufferedPlayerName) { 17 | this.uuid = uuid; 18 | this.bufferedPlayerName = bufferedPlayerName; 19 | } 20 | 21 | public String getName() { 22 | return bufferedPlayerName; 23 | } 24 | 25 | public void updatePlayerName(final String name) { 26 | bufferedPlayerName = name; 27 | } 28 | 29 | public JsonObject toJson() { 30 | final JsonObject jsonObject = new JsonObject(); 31 | 32 | jsonObject.add("uuid", new JsonPrimitive(uuid.toString())); 33 | jsonObject.add("name", new JsonPrimitive(bufferedPlayerName)); 34 | 35 | return jsonObject; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SyncmaticaPayload.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.syncmatica; 2 | 3 | import net.minecraft.network.FriendlyByteBuf; 4 | import net.minecraft.resources.ResourceLocation; 5 | import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; 6 | 7 | public record SyncmaticaPayload(ResourceLocation packetType, 8 | FriendlyByteBuf data) implements LeavesCustomPayload { 9 | 10 | private static final ResourceLocation NETWORK_ID = ResourceLocation.tryBuild(SyncmaticaProtocol.PROTOCOL_ID, "main"); 11 | 12 | @New 13 | public static SyncmaticaPayload decode(ResourceLocation location, FriendlyByteBuf buf) { 14 | return new SyncmaticaPayload(buf.readResourceLocation(), new FriendlyByteBuf(buf.readBytes(buf.readableBytes()))); 15 | } 16 | 17 | @Override 18 | public void write(FriendlyByteBuf buf) { 19 | buf.writeResourceLocation(this.packetType); 20 | buf.writeBytes(this.data.readBytes(this.data.readableBytes())); 21 | } 22 | 23 | @Override 24 | public ResourceLocation id() { 25 | return NETWORK_ID; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/AbstractExchange.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.syncmatica.exchange; 2 | 3 | import net.minecraft.network.FriendlyByteBuf; 4 | 5 | import java.util.UUID; 6 | 7 | public abstract class AbstractExchange implements Exchange { 8 | 9 | private boolean success = false; 10 | private boolean finished = false; 11 | private final ExchangeTarget partner; 12 | 13 | protected AbstractExchange(final ExchangeTarget partner) { 14 | this.partner = partner; 15 | } 16 | 17 | @Override 18 | public ExchangeTarget getPartner() { 19 | return partner; 20 | } 21 | 22 | @Override 23 | public boolean isFinished() { 24 | return finished; 25 | } 26 | 27 | @Override 28 | public boolean isSuccessful() { 29 | return success; 30 | } 31 | 32 | @Override 33 | public void close(final boolean notifyPartner) { 34 | finished = true; 35 | success = false; 36 | onClose(); 37 | if (notifyPartner) { 38 | sendCancelPacket(); 39 | } 40 | } 41 | 42 | protected void sendCancelPacket() { 43 | } 44 | 45 | protected void onClose() { 46 | } 47 | 48 | protected void succeed() { 49 | finished = true; 50 | success = true; 51 | onClose(); 52 | } 53 | 54 | protected static boolean checkUUID(final FriendlyByteBuf sourceBuf, final UUID targetId) { 55 | final int r = sourceBuf.readerIndex(); 56 | final UUID sourceId = sourceBuf.readUUID(); 57 | sourceBuf.readerIndex(r); 58 | return sourceId.equals(targetId); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/Exchange.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.syncmatica.exchange; 2 | 3 | import net.minecraft.network.FriendlyByteBuf; 4 | import net.minecraft.resources.ResourceLocation; 5 | 6 | public interface Exchange { 7 | 8 | ExchangeTarget getPartner(); 9 | 10 | boolean checkPacket(ResourceLocation id, FriendlyByteBuf packetBuf); 11 | 12 | void handle(ResourceLocation id, FriendlyByteBuf packetBuf); 13 | 14 | boolean isFinished(); 15 | 16 | boolean isSuccessful(); 17 | 18 | void close(boolean notifyPartner); 19 | 20 | void init(); 21 | } 22 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/ExchangeTarget.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.protocol.syncmatica.exchange; 2 | 3 | import net.minecraft.network.FriendlyByteBuf; 4 | import net.minecraft.resources.ResourceLocation; 5 | import net.minecraft.server.network.ServerGamePacketListenerImpl; 6 | import org.leavesmc.leaves.protocol.core.ProtocolUtils; 7 | import org.leavesmc.leaves.protocol.syncmatica.FeatureSet; 8 | import org.leavesmc.leaves.protocol.syncmatica.SyncmaticaPayload; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collection; 12 | import java.util.List; 13 | 14 | public class ExchangeTarget { 15 | 16 | private final List ongoingExchanges = new ArrayList<>(); 17 | private final ServerGamePacketListenerImpl client; 18 | private FeatureSet features; 19 | 20 | public ExchangeTarget(final ServerGamePacketListenerImpl client) { 21 | this.client = client; 22 | } 23 | 24 | public void sendPacket(final ResourceLocation id, final FriendlyByteBuf packetBuf) { 25 | ProtocolUtils.sendPayloadPacket(client.player, new SyncmaticaPayload(id, packetBuf)); 26 | } 27 | 28 | public FeatureSet getFeatureSet() { 29 | return features; 30 | } 31 | 32 | public void setFeatureSet(final FeatureSet f) { 33 | features = f; 34 | } 35 | 36 | public Collection getExchanges() { 37 | return ongoingExchanges; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/replay/DigestOutputStream.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.replay; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.util.zip.Checksum; 8 | 9 | public class DigestOutputStream extends OutputStream { 10 | 11 | private final Checksum sum; 12 | private final OutputStream out; 13 | 14 | public DigestOutputStream(OutputStream out, Checksum sum) { 15 | this.out = out; 16 | this.sum = sum; 17 | } 18 | 19 | @Override 20 | public void close() throws IOException { 21 | out.close(); 22 | } 23 | 24 | @Override 25 | public void flush() throws IOException { 26 | out.flush(); 27 | } 28 | 29 | @Override 30 | public void write(int b) throws IOException { 31 | sum.update(b); 32 | out.write(b); 33 | } 34 | 35 | @Override 36 | public void write(byte @NotNull [] b) throws IOException { 37 | sum.update(b); 38 | out.write(b); 39 | } 40 | 41 | @Override 42 | public void write(byte @NotNull [] b, int off, int len) throws IOException { 43 | sum.update(b, off, len); 44 | out.write(b, off, len); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/replay/RecordMetaData.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.replay; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | import java.util.UUID; 6 | 7 | public class RecordMetaData { 8 | 9 | public static final int CURRENT_FILE_FORMAT_VERSION = 14; 10 | 11 | public boolean singleplayer = false; 12 | public String serverName = "Leaf"; 13 | public int duration = 0; 14 | public long date; 15 | public String mcversion; 16 | public String fileFormat = "MCPR"; 17 | public int fileFormatVersion; 18 | public int protocol; 19 | public String generator; 20 | public int selfId = -1; 21 | 22 | public Set players = new HashSet<>(); 23 | } 24 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/replay/ServerPhotographerGameMode.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.replay; 2 | 3 | import net.kyori.adventure.text.Component; 4 | import net.minecraft.server.level.ServerPlayerGameMode; 5 | import net.minecraft.world.level.GameType; 6 | import org.bukkit.event.player.PlayerGameModeChangeEvent; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | public class ServerPhotographerGameMode extends ServerPlayerGameMode { 11 | 12 | public ServerPhotographerGameMode(ServerPhotographer photographer) { 13 | super(photographer); 14 | super.setGameModeForPlayer(GameType.SPECTATOR, null); 15 | } 16 | 17 | @Override 18 | public boolean changeGameModeForPlayer(@NotNull GameType gameMode) { 19 | return false; 20 | } 21 | 22 | @Nullable 23 | @Override 24 | public PlayerGameModeChangeEvent changeGameModeForPlayer(@NotNull GameType gameMode, PlayerGameModeChangeEvent.@NotNull Cause cause, @Nullable Component cancelMessage) { 25 | return null; 26 | } 27 | 28 | @Override 29 | protected void setGameModeForPlayer(@NotNull GameType gameMode, @Nullable GameType previousGameMode) { 30 | } 31 | 32 | @Override 33 | public void tick() { 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/leavesmc/leaves/util/UUIDSerializer.java: -------------------------------------------------------------------------------- 1 | package org.leavesmc.leaves.util; 2 | 3 | import com.google.gson.JsonElement; 4 | import com.google.gson.JsonPrimitive; 5 | import com.google.gson.JsonSerializationContext; 6 | import com.google.gson.JsonSerializer; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.lang.reflect.Type; 10 | import java.util.UUID; 11 | 12 | public class UUIDSerializer implements JsonSerializer { 13 | 14 | @Override 15 | public JsonElement serialize(@NotNull UUID src, Type typeOfSrc, JsonSerializationContext context) { 16 | return new JsonPrimitive(src.toString()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/purpurmc/purpur/command/AFKCommand.java: -------------------------------------------------------------------------------- 1 | package org.purpurmc.purpur.command; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import net.minecraft.commands.CommandSourceStack; 5 | import net.minecraft.commands.Commands; 6 | import net.minecraft.commands.arguments.EntityArgument; 7 | import net.minecraft.server.level.ServerPlayer; 8 | 9 | import java.util.Collection; 10 | import java.util.Collections; 11 | 12 | public class AFKCommand { 13 | public static void register(CommandDispatcher dispatcher) { 14 | dispatcher.register(Commands.literal("afk") 15 | .requires((listener) -> listener.hasPermission(2, "bukkit.command.afk")) 16 | .executes((context) -> execute(context.getSource(), Collections.singleton(context.getSource().getPlayerOrException()))) 17 | .then(Commands.argument("targets", EntityArgument.players()) 18 | .requires(listener -> listener.hasPermission(2, "bukkit.command.afk.other")) 19 | .executes((context) -> execute(context.getSource(), EntityArgument.getPlayers(context, "targets"))) 20 | ) 21 | ); 22 | } 23 | 24 | private static int execute(CommandSourceStack sender, Collection targets) { 25 | for (ServerPlayer player : targets) { 26 | boolean afk = player.isCommandAfk 27 | ? !player.commandAfkStatus 28 | : !player.isAfk(); 29 | 30 | if (afk) player.setAfk(true); 31 | 32 | player.isCommandAfk = false; 33 | } 34 | 35 | return targets.size(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/stupidcraft/linearpaper/region/EnumRegionFileExtension.java: -------------------------------------------------------------------------------- 1 | package org.stupidcraft.linearpaper.region; 2 | 3 | import org.jetbrains.annotations.Contract; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.Locale; 7 | 8 | public enum EnumRegionFileExtension { 9 | LINEAR(".linear"), 10 | MCA(".mca"), 11 | UNKNOWN(null); 12 | 13 | private final String extensionName; 14 | 15 | EnumRegionFileExtension(String extensionName) { 16 | this.extensionName = extensionName; 17 | } 18 | 19 | public String getExtensionName() { 20 | return this.extensionName; 21 | } 22 | 23 | @Contract(pure = true) 24 | public static EnumRegionFileExtension fromName(@NotNull String name) { 25 | switch (name.toUpperCase(Locale.ROOT)) { 26 | case "MCA" -> { 27 | return MCA; 28 | } 29 | 30 | case "LINEAR" -> { 31 | return LINEAR; 32 | } 33 | default -> { 34 | return UNKNOWN; 35 | } 36 | 37 | } 38 | } 39 | 40 | @Contract(pure = true) 41 | public static EnumRegionFileExtension fromExtension(@NotNull String name) { 42 | switch (name.toLowerCase()) { 43 | case "mca" -> { 44 | return MCA; 45 | } 46 | 47 | case "linear" -> { 48 | return LINEAR; 49 | } 50 | 51 | default -> { 52 | return UNKNOWN; 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /leaf-server/src/main/java/org/stupidcraft/linearpaper/region/IRegionFile.java: -------------------------------------------------------------------------------- 1 | package org.stupidcraft.linearpaper.region; 2 | 3 | import java.io.DataInputStream; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.nio.ByteBuffer; 7 | import java.nio.file.Path; 8 | 9 | import ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile; 10 | import net.minecraft.nbt.CompoundTag; 11 | import net.minecraft.world.level.ChunkPos; 12 | 13 | public interface IRegionFile extends AutoCloseable, ChunkSystemRegionFile { 14 | 15 | Path getPath(); 16 | 17 | void flush() throws IOException; 18 | 19 | void clear(ChunkPos pos) throws IOException; 20 | 21 | void close() throws IOException; 22 | 23 | void setOversized(int x, int z, boolean b) throws IOException; 24 | 25 | void write(ChunkPos pos, ByteBuffer buffer) throws IOException; 26 | 27 | boolean hasChunk(ChunkPos pos); 28 | 29 | boolean doesChunkExist(ChunkPos pos) throws Exception; 30 | 31 | boolean isOversized(int x, int z); 32 | 33 | boolean recalculateHeader() throws IOException; 34 | 35 | DataOutputStream getChunkDataOutputStream(ChunkPos pos) throws IOException; 36 | 37 | DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException; 38 | 39 | CompoundTag getOversizedData(int x, int z) throws IOException; 40 | } 41 | -------------------------------------------------------------------------------- /licenses/MIT.txt: -------------------------------------------------------------------------------- 1 | Below is the MIT License (MIT), 2 | which applies only to parts of Leaf that are specifically and explicitly released under MIT. 3 | 4 | MIT License 5 | 6 | Copyright (c) 2022-2024 Respective authors of parts of Leaf, or software included therein 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. -------------------------------------------------------------------------------- /public/image/JiankeServer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Winds-Studio/Leaf/b70aaa04505e2cad4862321bc5b03e71c670ed93/public/image/JiankeServer.jpg -------------------------------------------------------------------------------- /public/image/leaf_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Winds-Studio/Leaf/b70aaa04505e2cad4862321bc5b03e71c670ed93/public/image/leaf_banner.png -------------------------------------------------------------------------------- /public/image/leaf_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Winds-Studio/Leaf/b70aaa04505e2cad4862321bc5b03e71c670ed93/public/image/leaf_logo.png -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.util.Locale 2 | 3 | pluginManagement { 4 | repositories { 5 | gradlePluginPortal() 6 | maven("https://repo.papermc.io/repository/maven-public/") 7 | } 8 | } 9 | 10 | plugins { 11 | id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0" 12 | } 13 | 14 | rootProject.name = "leaf" 15 | 16 | for (name in listOf("leaf-api", "leaf-server")) { 17 | val projName = name.lowercase(Locale.ENGLISH) 18 | include(projName) 19 | findProject(":$projName")!!.projectDir = file(name) 20 | } 21 | --------------------------------------------------------------------------------