From f09fbb247dbe79c7a612b104861e2ee162c58e39 Mon Sep 17 00:00:00 2001 From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> Date: Thu, 5 Jun 2025 18:41:51 +0800 Subject: [PATCH] 1.21.5 (#470) --------- Co-authored-by: violetc <58360096+s-yh-china@users.noreply.github.com> Co-authored-by: Fortern Co-authored-by: MC_XiaoHei Co-authored-by: Helvetica Volubi <88063803+Suisuroru@users.noreply.github.com> Co-authored-by: MC_XiaoHei --- .github/workflows/build.yml | 2 +- .github/workflows/test.yml | 2 +- LICENSE.md | 1 + README.md | 4 +- README_cn.md | 4 +- gradle.properties | 8 +- leaves-api/build.gradle.kts.patch | 16 +- .../features/0001-Delete-Timings.patch | 91 +- ...Add-isShrink-to-EntityResurrectEvent.patch | 42 +- .../features/0003-Add-fakeplayer-api.patch | 18 +- .../0004-Force-peaceful-mode-switch.patch | 4 +- .../features/0005-Replay-Mod-API.patch | 22 +- .../features/0006-Bytebuf-API.patch | 14 +- .../features/0007-Revert-raid-changes.patch | 4 +- .../0008-Fix-SculkCatalyst-exp-skip.patch | 61 +- .../features/0009-Leaves-Config-API.patch | 34 + .../org/leavesmc/leaves/bytebuf/Bytebuf.java | 4 +- .../leaves/bytebuf/BytebufManager.java | 2 + .../leaves/bytebuf/packet/Packet.java | 1 + .../leaves/bytebuf/packet/PacketListener.java | 1 + .../leaves/bytebuf/packet/PacketType.java | 1 + .../leaves/config/LeavesConfigProvider.java | 8 + .../leaves/config/LeavesConfigValue.java | 36 + .../java/org/leavesmc/leaves/entity/Bot.java | 23 +- .../leavesmc/leaves/entity/BotCreator.java | 17 +- .../leavesmc/leaves/entity/BotManager.java | 16 +- .../leavesmc/leaves/entity/Photographer.java | 17 +- .../leaves/entity/PhotographerManager.java | 22 +- .../entity/botaction/BotActionType.java | 4 +- .../entity/botaction/CustomBotAction.java | 28 +- .../entity/botaction/LeavesBotAction.java | 95 ++- .../event/bot/BotActionExecuteEvent.java | 15 +- .../event/bot/BotActionScheduleEvent.java | 11 +- .../leaves/event/bot/BotActionStopEvent.java | 21 +- .../event/bot/BotConfigModifyEvent.java | 10 +- .../leaves/event/bot/BotCreateEvent.java | 22 +- .../leaves/event/bot/BotDeathEvent.java | 8 +- .../event/bot/BotInventoryOpenEvent.java | 10 +- .../leaves/event/bot/BotJoinEvent.java | 10 +- .../leaves/event/bot/BotLoadEvent.java | 10 +- .../leaves/event/bot/BotRemoveEvent.java | 22 +- .../event/bot/BotSpawnLocationEvent.java | 10 +- .../player/PlayerOperationLimitEvent.java | 10 +- .../leaves/plugin/FeatureManager.java | 10 + .../org/leavesmc/leaves/plugin/Features.java | 9 + leaves-server/build.gradle.kts.patch | 74 +- .../features/0001-Build-changes.patch | 14 +- ...002-Leaves-Server-Config-And-Command.patch | 4 +- .../features/0003-Leaves-Protocol-Core.patch | 94 -- .../features/0003-Leaves-entity-ex-data.patch | 49 ++ .../features/0004-Leaves-Protocol-Core.patch | 147 ++++ ...h => 0005-Fix-trading-with-the-void.patch} | 4 +- ...owball-and-egg-can-knockback-player.patch} | 6 +- ...yer.patch => 0007-Leaves-Fakeplayer.patch} | 126 ++- ...ears-in-dispenser-can-unlimited-use.patch} | 4 +- ...atch => 0009-Redstone-Shears-Wrench.patch} | 6 +- ...dd-isShrink-to-EntityResurrectEvent.patch} | 4 +- ...Budding-Amethyst-can-push-by-piston.patch} | 12 +- ...0012-Spectator-dont-get-Advancement.patch} | 2 +- ...ck-can-change-ArmorStand-arm-status.patch} | 5 +- ...patch => 0014-Configurable-MC-59471.patch} | 18 +- ...hat-sign.patch => 0015-No-chat-sign.patch} | 16 +- ...16-Dont-send-useless-entity-packets.patch} | 12 +- ....patch => 0017-Optimize-suffocation.patch} | 20 +- ...heck-for-spooky-season-once-an-hour.patch} | 4 +- ...9-Config-to-disable-method-profiler.patch} | 4 +- ...al-selector-during-inactive-ticking.patch} | 4 +- ...h => 0021-Reduce-entity-allocations.patch} | 6 +- ...22-Remove-lambda-from-ticking-guard.patch} | 4 +- ...Cache-climbing-check-for-activation.patch} | 6 +- ...> 0024-Reduce-chunk-loading-lookups.patch} | 4 +- ...25-InstantBlockUpdater-Reintroduced.patch} | 4 +- .../features/0026-BBOR-Protocol.patch | 34 - ...dom-flatten-triangular-distribution.patch} | 18 +- .../features/0027-BBOR-Protocol.patch | 22 + ...col.patch => 0028-PCA-sync-protocol.patch} | 82 +- ...Alternative-block-placement-Protocol.patch | 8 +- ...rotocol.patch => 0030-Jade-Protocol.patch} | 18 +- ...ch => 0031-Player-operation-limiter.patch} | 20 +- ...ytra.patch => 0032-Renewable-Elytra.patch} | 4 +- .../0033-MC-Technical-Survival-Mode.patch | 22 +- ...atch => 0034-Stackable-ShulkerBoxes.patch} | 182 ++-- ...ch => 0035-Return-nether-portal-fix.patch} | 16 +- ...0036-Leaves-Extra-Yggdrasil-Service.patch} | 6 +- ...=> 0037-Configurable-vanilla-random.patch} | 18 +- ...0038-Catch-update-suppression-crash.patch} | 47 +- ...st.patch => 0039-Bedrock-break-list.patch} | 22 +- ....patch => 0040-Fix-trapdoor-feature.patch} | 12 +- ...-distance-check-for-UseItemOnPacket.patch} | 4 +- ... => 0042-No-feather-falling-trample.patch} | 2 +- ....patch => 0043-Disable-packet-limit.patch} | 14 +- ...one-wire-dont-connect-if-on-trapdoor.patch | 28 - ...l.patch => 0044-Syncmatica-Protocol.patch} | 4 +- ...h => 0045-Shared-villager-discounts.patch} | 4 +- .../0046-Redstone-ignore-upwards-update.patch | 52 ++ ...-Disable-check-out-of-order-command.patch} | 0 ...=> 0048-Despawn-enderman-with-block.patch} | 4 +- ...ch => 0049-Optimized-dragon-respawn.patch} | 6 +- ....patch => 0050-Creative-fly-no-clip.patch} | 52 +- ...050-Elytra-aeronautics-no-chunk-load.patch | 80 -- ...ers.patch => 0051-Shave-snow-layers.patch} | 4 +- ...052-Elytra-aeronautics-no-chunk-load.patch | 160 ++++ ...dds.patch => 0053-Cache-ignite-odds.patch} | 30 +- ...-riptide.patch => 0054-Lava-riptide.patch} | 6 +- ...tch => 0055-No-block-update-command.patch} | 32 +- ...056-Raider-die-skip-self-raid-check.patch} | 4 +- ... => 0057-Container-open-passthrough.patch} | 8 +- ...ont-respond-ping-before-start-fully.patch} | 0 ... => 0059-Faster-chunk-serialization.patch} | 2 +- ...Skip-secondary-POI-sensor-if-absent.patch} | 4 +- .../0061-Reduce-array-allocations.patch | 281 ------ ...> 0061-Store-mob-counts-in-an-array.patch} | 0 ...h => 0062-Optimize-noise-generation.patch} | 0 ...atch => 0063-Optimize-sun-burn-tick.patch} | 52 +- ...-Optional-allocation-in-EntityBased.patch} | 0 ...ignableFrom-call-in-ClassInstanceMu.patch} | 0 ...ch => 0066-Optimized-CubePointRange.patch} | 0 ...k-frozen-ticks-before-landing-block.patch} | 4 +- ...kip-entity-move-if-movement-is-zero.patch} | 8 +- ...9-Skip-cloning-advancement-criteria.patch} | 4 +- ...0-Fix-villagers-dont-release-memory.patch} | 12 +- ...h => 0071-Avoid-anvil-too-expensive.patch} | 8 +- ...-fix.patch => 0072-Bow-infinity-fix.patch} | 8 +- ...ants.patch => 0073-Zero-tick-plants.patch} | 18 +- ... => 0074-Force-peaceful-mode-switch.patch} | 18 +- ...od-API.patch => 0075-Replay-Mod-API.patch} | 34 +- ...aves-I18n.patch => 0076-Leaves-I18n.patch} | 4 +- ...raft-hopper-not-work-without-player.patch} | 4 +- ...G-Fishing.patch => 0078-RNG-Fishing.patch} | 4 +- .../0079-Spider-jockeys-drop-gapples.patch | 29 - ...r.patch => 0079-Wool-Hopper-Counter.patch} | 6 +- .../0080-Spider-jockeys-drop-gapples.patch | 50 ++ ...rade.patch => 0081-Force-Void-Trade.patch} | 34 +- ...=> 0082-Villager-infinite-discounts.patch} | 0 ...atch => 0083-CCE-update-suppression.patch} | 6 +- ...4-Disable-offline-warn-if-use-proxy.patch} | 4 +- ...r-stand-cant-kill-by-mob-projectile.patch} | 4 +- ...atch => 0086-Make-Item-tick-vanilla.patch} | 6 +- ...atch => 0087-Copper-Bulb-1-gt-delay.patch} | 2 +- ...ay.patch => 0088-Crafter-1-gt-delay.patch} | 8 +- ... => 0089-More-Region-Format-Support.patch} | 63 +- .../features/0089-No-TNT-place-update.patch | 19 - .../features/0090-No-TNT-place-update.patch | 19 + ...ked-hopper-no-longer-send-NC-updates.patch | 23 - ...tocol.patch => 0091-Servux-Protocol.patch} | 6 +- ...ked-hopper-no-longer-send-NC-updates.patch | 23 + ...e.patch => 0093-Renewable-deepslate.patch} | 8 +- ...ges.patch => 0094-Renewable-sponges.patch} | 4 +- ...coral.patch => 0095-Renewable-coral.patch} | 33 +- ...st-resume.patch => 0096-Fast-resume.patch} | 24 +- ...hopper.patch => 0097-Vanilla-hopper.patch} | 4 +- ... => 0098-Old-hopper-suckin-behavior.patch} | 4 +- ...-Fix-falling-block-s-block-location.patch} | 4 +- ...tebuf-API.patch => 0100-Bytebuf-API.patch} | 17 +- ... 0101-Allow-grindstone-overstacking.patch} | 8 +- ...67.patch => 0102-Configurable-MC-67.patch} | 4 +- ...e-end-gateway-portal-entity-ticking.patch} | 4 +- ...able-crystal-portal-proximity-check.patch} | 18 +- ...ble-LivingEntity-aiStep-alive-check.patch} | 4 +- .../0105-Fix-fortress-mob-spawn.patch | 25 - ...106-Fix-FallingBlockEntity-Duplicate.patch | 4 +- .../0107-Old-Block-remove-behaviour.patch | 804 ++++++++++++++++++ .../0107-Old-BlockEntity-behaviour.patch | 90 -- .../features/0108-Revert-raid-changes.patch | 59 +- ...09-Allow-anvil-destroy-item-entities.patch | 6 +- ...0110-Configurable-collision-behavior.patch | 54 ++ ...t-Collision-Behavior-for-Block-Shape.patch | 37 - .../0111-Disable-vault-blacklist.patch | 8 +- ...0112-Fix-EntityPortalExitEvent-logic.patch | 12 +- .../0113-Fix-CraftPortalEvent-logic.patch | 4 +- .../features/0114-Xaero-Map-Protocol.patch | 4 +- ...gible-planar-movement-multiplication.patch | 4 +- .../0116-Skippable-raid-height-check.patch | 12 +- .../features/0117-Support-REI-protocol.patch | 41 +- .../0118-Vanilla-player-display-name.patch | 4 +- ... => 0119-Fix-SculkCatalyst-exp-skip.patch} | 22 +- ...120-Vanilla-creative-pickup-behavior.patch | 24 + .../features/0121-Vanilla-portal-handle.patch | 40 + .../0122-Fix-chunk-reload-detector.patch | 19 + ...-not-reset-placed-block-on-exception.patch | 43 + ...lock-entity-and-entity-crash-at-Leve.patch | 29 + .../0125-Tripwire-behavior-modifier.patch | 86 ++ .../0126-Old-nether-portal-collision.patch | 20 + .../0127-Spawn-invulnerable-time.patch | 40 + .../0128-Old-zombie-reinforcement.patch | 19 + .../0129-Sound-update-suppression.patch | 55 ++ ...0130-Old-zombie-piglin-drop-behavior.patch | 21 + .../features/0131-Fast-exp-orb-absorb.patch | 31 + .../minecraft/world/entity/Entity.java.patch | 40 - .../features/0001-Build-changes.patch | 45 +- ...003-Leaves-Server-Config-And-Command.patch | 16 +- .../features/0004-Leaves-Protocol-Core.patch | 6 +- .../features/0005-Leaves-Fakeplayer.patch | 46 +- .../features/0006-No-chat-sign.patch | 2 +- .../0007-MC-Technical-Survival-Mode.patch | 4 +- .../features/0009-Disable-packet-limit.patch | 4 +- ... => 0010-Force-peaceful-mode-switch.patch} | 4 +- .../0010-Reduce-array-allocations.patch | 62 -- ...od-API.patch => 0011-Replay-Mod-API.patch} | 21 +- ...tch => 0012-Force-minecraft-command.patch} | 0 ...tebuf-API.patch => 0013-Bytebuf-API.patch} | 16 +- .../features/0014-Leaves-plugin.patch | 262 ++++++ ... => 0015-Fix-SculkCatalyst-exp-skip.patch} | 10 +- .../features/0015-Leaves-plugins.patch | 145 ---- .../features/0016-Leaves-Config-API.patch | 22 + .../util/CraftMagicNumbers.java.patch | 11 - .../main/java/co/aikar/timings/Timings.java | 6 + .../org/leavesmc/leaves/LeavesConfig.java | 102 ++- .../org/leavesmc/leaves/bot/BotCommand.java | 28 +- .../leavesmc/leaves/bot/BotDataStorage.java | 3 +- .../leaves/bot/BotInventoryContainer.java | 198 ++--- .../java/org/leavesmc/leaves/bot/BotList.java | 54 +- .../java/org/leavesmc/leaves/bot/BotUtil.java | 22 + .../org/leavesmc/leaves/bot/ServerBot.java | 135 ++- .../leaves/bot/agent/AbstractBotAction.java | 213 +++-- .../leavesmc/leaves/bot/agent/Actions.java | 1 + .../agent/actions/AbstractTimerAction.java | 14 +- .../bot/agent/actions/CraftBotAction.java | 4 +- .../agent/actions/CraftCustomBotAction.java | 15 +- .../leaves/bot/agent/actions/DropAction.java | 10 +- .../leaves/bot/agent/actions/FishAction.java | 28 +- .../leaves/bot/agent/actions/LookAction.java | 20 +- .../bot/agent/actions/RotateAction.java | 2 +- .../bot/agent/actions/RotationAction.java | 12 +- .../leaves/bot/agent/actions/ShootAction.java | 80 ++ .../leaves/bot/agent/actions/SneakAction.java | 2 +- .../leaves/bot/agent/actions/SwimAction.java | 2 +- .../agent/configs/AlwaysSendDataConfig.java | 4 +- .../configs/SimulationDistanceConfig.java | 5 +- .../bot/agent/configs/SkipSleepConfig.java | 4 +- .../bot/agent/configs/SpawnPhantomConfig.java | 4 +- .../bot/agent/configs/TickTypeConfig.java | 4 +- .../bot/subcommands/BotActionCommand.java | 44 +- .../bot/subcommands/BotConfigCommand.java | 49 +- .../bot/subcommands/BotCreateCommand.java | 4 +- .../bot/subcommands/BotLoadCommand.java | 2 +- .../leaves/bytebuf/SimpleBytebufManager.java | 2 + .../leaves/bytebuf/WrappedBytebuf.java | 5 + .../internal/InternalBytebufHandler.java | 39 +- .../leaves/command/CommandArgument.java | 52 +- .../leaves/command/LeavesCommand.java | 7 +- .../leaves/command/LeavesCommandUtil.java | 13 +- .../leaves/command/NoBlockUpdateCommand.java | 1 + .../leaves/config/InternalConfigProvider.java | 14 + .../org/leavesmc/leaves/entity/CraftBot.java | 2 +- .../leaves/entity/CraftBotManager.java | 7 +- .../leaves/plugin/ServerFeatureManager.java | 32 + .../configuration/FeaturesConfiguration.java | 21 + .../configuration/LeavesPluginMeta.java | 43 +- .../configuration/MixinConfiguration.java | 35 + .../leaves/protocol/AppleSkinProtocol.java | 92 +- .../leaves/protocol/BBORProtocol.java | 102 +-- .../leaves/protocol/CarpetServerProtocol.java | 38 +- .../leaves/protocol/LMSPasterProtocol.java | 70 +- .../leaves/protocol/PcaSyncProtocol.java | 151 ++-- .../leaves/protocol/XaeroMapProtocol.java | 13 +- .../protocol/bladeren/BladerenProtocol.java | 109 ++- .../protocol/bladeren/MsptSyncProtocol.java | 55 +- .../protocol/chatimage/ChatImageIndex.java | 16 - .../protocol/chatimage/ChatImageProtocol.java | 28 +- .../chatimage/DownloadFileChannelPayload.java | 26 +- .../chatimage/FileChannelPayload.java | 26 +- .../chatimage/FileInfoChannelPayload.java | 26 +- .../protocol/chatimage/ServerBlockCache.java | 12 +- .../protocol/core/LeavesCustomPayload.java | 27 +- .../leaves/protocol/core/LeavesProtocol.java | 19 +- .../protocol/core/LeavesProtocolManager.java | 538 ++++++------ .../leaves/protocol/core/ProtocolHandler.java | 25 +- .../leaves/protocol/core/ProtocolUtils.java | 30 +- .../core/invoker/AbstractInvokerHolder.java | 70 ++ .../invoker/BytebufReceiverInvokerHolder.java | 18 + .../core/invoker/EmptyInvokerHolder.java | 15 + .../core/invoker/InitInvokerHolder.java | 16 + .../MinecraftRegisterInvokerHolder.java | 18 + .../invoker/PayloadReceiverInvokerHolder.java | 18 + .../core/invoker/PlayerInvokerHolder.java | 16 + .../leaves/protocol/jade/JadeProtocol.java | 56 +- .../protocol/jade/accessor/Accessor.java | 10 - .../protocol/jade/accessor/AccessorImpl.java | 24 +- .../protocol/jade/accessor/BlockAccessor.java | 6 - .../jade/accessor/BlockAccessorImpl.java | 50 +- .../jade/accessor/EntityAccessor.java | 2 - .../jade/accessor/EntityAccessorImpl.java | 41 +- .../jade/payload/ClientHandshakePayload.java | 28 +- .../jade/payload/ReceiveDataPayload.java | 24 +- .../jade/payload/RequestBlockPayload.java | 24 +- .../jade/payload/RequestEntityPayload.java | 25 +- .../jade/payload/ServerHandshakePayload.java | 28 +- .../ItemStorageExtensionProvider.java | 94 +- .../jade/provider/ItemStorageProvider.java | 21 +- .../provider/block/BlockNameProvider.java | 60 ++ .../provider/block/BrewingStandProvider.java | 10 +- .../block/ChiseledBookshelfProvider.java | 7 +- .../jade/provider/block/FurnaceProvider.java | 35 +- .../provider/block/HopperLockProvider.java | 5 + .../provider/block/ObjectNameProvider.java | 63 -- .../provider/entity/AnimalOwnerProvider.java | 19 +- .../entity/NextEntityDropProvider.java | 7 + .../protocol/jade/tool/ShearsToolHandler.java | 33 +- .../protocol/jade/tool/SimpleToolHandler.java | 71 -- .../protocol/jade/tool/ToolHandler.java | 17 - .../leaves/protocol/jade/util/CommonUtil.java | 7 - .../protocol/jade/util/HierarchyLookup.java | 3 +- .../protocol/jade/util/IHierarchyLookup.java | 5 + .../protocol/jade/util/ItemCollector.java | 17 +- .../jade/util/LootTableMineableCollector.java | 38 +- .../jade/util/PairHierarchyLookup.java | 7 +- .../leaves/protocol/jade/util/ViewGroup.java | 38 +- .../jade/util/WrappedHierarchyLookup.java | 11 +- .../protocol/rei/PacketTransformer.java | 29 +- .../protocol/rei/REIServerProtocol.java | 113 ++- .../protocol/rei/display/BlastingDisplay.java | 4 +- .../protocol/rei/display/CampfireDisplay.java | 4 +- .../protocol/rei/display/CookingDisplay.java | 15 +- .../protocol/rei/display/CustomDisplay.java | 16 +- .../leaves/protocol/rei/display/Display.java | 109 +-- .../protocol/rei/display/ShapedDisplay.java | 41 +- .../rei/display/ShapelessDisplay.java | 10 +- .../protocol/rei/display/SmeltingDisplay.java | 4 +- .../protocol/rei/display/SmithingDisplay.java | 80 +- .../protocol/rei/display/SmokingDisplay.java | 4 +- .../rei/display/StoneCuttingDisplay.java | 10 +- .../rei/ingredient/EntryIngredient.java | 42 +- .../rei/payload/BufCustomPacketPayload.java | 32 - .../rei/payload/DisplaySyncPayload.java | 13 +- .../protocol/servux/PacketSplitter.java | 8 +- .../servux/ServuxEntityDataProtocol.java | 204 ++--- .../servux/ServuxHudDataProtocol.java | 154 ++-- .../servux/ServuxStructuresProtocol.java | 122 ++- .../litematics/LitematicaSchematic.java | 120 +-- .../servux/litematics/SchematicMetadata.java | 38 +- .../litematics/ServuxLitematicsProtocol.java | 272 +++--- .../container/LitematicaBitArray.java | 32 +- .../LitematicaBlockStateContainer.java | 18 +- .../LitematicaBlockStatePalette.java | 23 +- .../LitematicaBlockStatePaletteHashMap.java | 22 +- .../LitematicaBlockStatePaletteLinear.java | 22 +- .../placement/SchematicPlacement.java | 104 +-- .../servux/litematics/utils/EntityUtils.java | 9 +- .../litematics/utils/Int2ObjectBiMap.java | 16 +- .../servux/litematics/utils/NbtUtils.java | 51 +- .../servux/litematics/utils/Schema.java | 19 +- .../utils/SchematicPlacingUtils.java | 23 +- .../syncmatica/CommunicationManager.java | 51 +- .../protocol/syncmatica/FeatureSet.java | 19 +- .../protocol/syncmatica/ServerPlacement.java | 86 +- .../protocol/syncmatica/ServerPosition.java | 30 +- .../protocol/syncmatica/SubRegionData.java | 26 +- .../SubRegionPlacementModification.java | 32 +- .../syncmatica/SyncmaticaPayload.java | 24 +- .../syncmatica/SyncmaticaProtocol.java | 8 +- .../syncmatica/exchange/AbstractExchange.java | 16 +- .../syncmatica/exchange/DownloadExchange.java | 4 +- .../leavesmc/leaves/region/IRegionFile.java | 2 + .../region/linear/LinearRegionFile.java | 5 + .../org/leavesmc/leaves/replay/Recorder.java | 25 +- .../leavesmc/leaves/replay/ReplayFile.java | 20 +- .../leavesmc/leaves/util/ArrayConstants.java | 22 - .../leaves/util/ElytraAeronauticsHelper.java | 149 +++- .../leavesmc/leaves/util/HopperCounter.java | 1 + .../leaves/util/LeavesVersionFetcher.java | 2 +- .../leaves/util/ReturnPortalManager.java | 16 +- .../leavesmc/leaves/util/ShulkerBoxUtils.java | 39 +- .../leavesmc/leaves/util/TicketHelper.java | 28 +- .../assets/minecraft/lang/zh_cn.json | 225 ++++- ...turn-optimization-for-target-finding.patch | 30 - ...ve-ThreadUnsafeRandom-Initialization.patch | 68 -- ...ve-iterators-from-inventory-contains.patch | 134 --- ...hread-unsafe-random-for-mob-spawning.patch | 39 - ...reams-and-iterators-from-range-check.patch | 64 -- ...e-aging-cache-for-biome-temperatures.patch | 236 ----- ...0041-Improve-fluid-direction-caching.patch | 262 ------ ...0067-Cache-world-generator-sea-level.patch | 45 - .../0077-Cache-BlockStatePairKey-hash.patch | 52 -- ...0099-Disable-moved-wrongly-threshold.patch | 46 - ...n-GameEventListener-register-on-load.patch | 20 - ...timize-random-calls-in-chunk-ticking.patch | 51 -- .../server/0058-Spawn-ignore-lc.patch | 47 - scripts/PushToAPI.sh | 13 +- 379 files changed, 6930 insertions(+), 6288 deletions(-) create mode 100644 leaves-api/paper-patches/features/0009-Leaves-Config-API.patch create mode 100644 leaves-api/src/main/java/org/leavesmc/leaves/config/LeavesConfigProvider.java create mode 100644 leaves-api/src/main/java/org/leavesmc/leaves/config/LeavesConfigValue.java create mode 100644 leaves-api/src/main/java/org/leavesmc/leaves/plugin/FeatureManager.java create mode 100644 leaves-api/src/main/java/org/leavesmc/leaves/plugin/Features.java delete mode 100644 leaves-server/minecraft-patches/features/0003-Leaves-Protocol-Core.patch create mode 100644 leaves-server/minecraft-patches/features/0003-Leaves-entity-ex-data.patch create mode 100644 leaves-server/minecraft-patches/features/0004-Leaves-Protocol-Core.patch rename leaves-server/minecraft-patches/features/{0004-Fix-trading-with-the-void.patch => 0005-Fix-trading-with-the-void.patch} (90%) rename leaves-server/minecraft-patches/features/{0005-Make-snowball-and-egg-can-knockback-player.patch => 0006-Make-snowball-and-egg-can-knockback-player.patch} (90%) rename leaves-server/minecraft-patches/features/{0006-Leaves-Fakeplayer.patch => 0007-Leaves-Fakeplayer.patch} (81%) rename leaves-server/minecraft-patches/features/{0007-Make-shears-in-dispenser-can-unlimited-use.patch => 0008-Make-shears-in-dispenser-can-unlimited-use.patch} (87%) rename leaves-server/minecraft-patches/features/{0008-Redstone-Shears-Wrench.patch => 0009-Redstone-Shears-Wrench.patch} (95%) rename leaves-server/minecraft-patches/features/{0009-Add-isShrink-to-EntityResurrectEvent.patch => 0010-Add-isShrink-to-EntityResurrectEvent.patch} (91%) rename leaves-server/minecraft-patches/features/{0010-Budding-Amethyst-can-push-by-piston.patch => 0011-Budding-Amethyst-can-push-by-piston.patch} (85%) rename leaves-server/minecraft-patches/features/{0011-Spectator-dont-get-Advancement.patch => 0012-Spectator-dont-get-Advancement.patch} (91%) rename leaves-server/minecraft-patches/features/{0012-Stick-can-change-ArmorStand-arm-status.patch => 0013-Stick-can-change-ArmorStand-arm-status.patch} (83%) rename leaves-server/minecraft-patches/features/{0013-Configurable-MC-59471.patch => 0014-Configurable-MC-59471.patch} (61%) rename leaves-server/minecraft-patches/features/{0014-No-chat-sign.patch => 0015-No-chat-sign.patch} (93%) rename leaves-server/minecraft-patches/features/{0015-Dont-send-useless-entity-packets.patch => 0016-Dont-send-useless-entity-packets.patch} (83%) rename leaves-server/minecraft-patches/features/{0016-Optimize-suffocation.patch => 0017-Optimize-suffocation.patch} (54%) rename leaves-server/minecraft-patches/features/{0017-Only-check-for-spooky-season-once-an-hour.patch => 0018-Only-check-for-spooky-season-once-an-hour.patch} (92%) rename leaves-server/minecraft-patches/features/{0018-Config-to-disable-method-profiler.patch => 0019-Config-to-disable-method-profiler.patch} (91%) rename leaves-server/minecraft-patches/features/{0019-Throttle-goal-selector-during-inactive-ticking.patch => 0020-Throttle-goal-selector-during-inactive-ticking.patch} (88%) rename leaves-server/minecraft-patches/features/{0020-Reduce-entity-allocations.patch => 0021-Reduce-entity-allocations.patch} (91%) rename leaves-server/minecraft-patches/features/{0021-Remove-lambda-from-ticking-guard.patch => 0022-Remove-lambda-from-ticking-guard.patch} (94%) rename leaves-server/minecraft-patches/features/{0022-Cache-climbing-check-for-activation.patch => 0023-Cache-climbing-check-for-activation.patch} (89%) rename leaves-server/minecraft-patches/features/{0023-Reduce-chunk-loading-lookups.patch => 0024-Reduce-chunk-loading-lookups.patch} (92%) rename leaves-server/minecraft-patches/features/{0024-InstantBlockUpdater-Reintroduced.patch => 0025-InstantBlockUpdater-Reintroduced.patch} (86%) delete mode 100644 leaves-server/minecraft-patches/features/0026-BBOR-Protocol.patch rename leaves-server/minecraft-patches/features/{0025-Random-flatten-triangular-distribution.patch => 0026-Random-flatten-triangular-distribution.patch} (60%) create mode 100644 leaves-server/minecraft-patches/features/0027-BBOR-Protocol.patch rename leaves-server/minecraft-patches/features/{0027-PCA-sync-protocol.patch => 0028-PCA-sync-protocol.patch} (77%) rename leaves-server/minecraft-patches/features/{0028-Jade-Protocol.patch => 0030-Jade-Protocol.patch} (89%) rename leaves-server/minecraft-patches/features/{0030-Player-operation-limiter.patch => 0031-Player-operation-limiter.patch} (84%) rename leaves-server/minecraft-patches/features/{0031-Renewable-Elytra.patch => 0032-Renewable-Elytra.patch} (89%) rename leaves-server/minecraft-patches/features/{0032-Stackable-ShulkerBoxes.patch => 0034-Stackable-ShulkerBoxes.patch} (77%) rename leaves-server/minecraft-patches/features/{0034-Return-nether-portal-fix.patch => 0035-Return-nether-portal-fix.patch} (90%) rename leaves-server/minecraft-patches/features/{0035-Leaves-Extra-Yggdrasil-Service.patch => 0036-Leaves-Extra-Yggdrasil-Service.patch} (91%) rename leaves-server/minecraft-patches/features/{0036-Configurable-vanilla-random.patch => 0037-Configurable-vanilla-random.patch} (88%) rename leaves-server/minecraft-patches/features/{0037-Catch-update-suppression-crash.patch => 0038-Catch-update-suppression-crash.patch} (61%) rename leaves-server/minecraft-patches/features/{0038-Bedrock-break-list.patch => 0039-Bedrock-break-list.patch} (84%) rename leaves-server/minecraft-patches/features/{0039-Fix-trapdoor-feature.patch => 0040-Fix-trapdoor-feature.patch} (74%) rename leaves-server/minecraft-patches/features/{0040-Disable-distance-check-for-UseItemOnPacket.patch => 0041-Disable-distance-check-for-UseItemOnPacket.patch} (88%) rename leaves-server/minecraft-patches/features/{0041-No-feather-falling-trample.patch => 0042-No-feather-falling-trample.patch} (93%) rename leaves-server/minecraft-patches/features/{0119-Disable-packet-limit.patch => 0043-Disable-packet-limit.patch} (89%) delete mode 100644 leaves-server/minecraft-patches/features/0044-Redstone-wire-dont-connect-if-on-trapdoor.patch rename leaves-server/minecraft-patches/features/{0042-Syncmatica-Protocol.patch => 0044-Syncmatica-Protocol.patch} (89%) rename leaves-server/minecraft-patches/features/{0043-Shared-villager-discounts.patch => 0045-Shared-villager-discounts.patch} (90%) create mode 100644 leaves-server/minecraft-patches/features/0046-Redstone-ignore-upwards-update.patch rename leaves-server/minecraft-patches/features/{0045-Disable-check-out-of-order-command.patch => 0047-Disable-check-out-of-order-command.patch} (100%) rename leaves-server/minecraft-patches/features/{0046-Despawn-enderman-with-block.patch => 0048-Despawn-enderman-with-block.patch} (84%) rename leaves-server/minecraft-patches/features/{0048-Optimized-dragon-respawn.patch => 0049-Optimized-dragon-respawn.patch} (96%) rename leaves-server/minecraft-patches/features/{0047-Creative-fly-no-clip.patch => 0050-Creative-fly-no-clip.patch} (80%) delete mode 100644 leaves-server/minecraft-patches/features/0050-Elytra-aeronautics-no-chunk-load.patch rename leaves-server/minecraft-patches/features/{0049-Shave-snow-layers.patch => 0051-Shave-snow-layers.patch} (93%) create mode 100644 leaves-server/minecraft-patches/features/0052-Elytra-aeronautics-no-chunk-load.patch rename leaves-server/minecraft-patches/features/{0051-Cache-ignite-odds.patch => 0053-Cache-ignite-odds.patch} (65%) rename leaves-server/minecraft-patches/features/{0052-Lava-riptide.patch => 0054-Lava-riptide.patch} (87%) rename leaves-server/minecraft-patches/features/{0053-No-block-update-command.patch => 0055-No-block-update-command.patch} (78%) rename leaves-server/minecraft-patches/features/{0054-Raider-die-skip-self-raid-check.patch => 0056-Raider-die-skip-self-raid-check.patch} (85%) rename leaves-server/minecraft-patches/features/{0055-Container-open-passthrough.patch => 0057-Container-open-passthrough.patch} (94%) rename leaves-server/minecraft-patches/features/{0056-Dont-respond-ping-before-start-fully.patch => 0058-Dont-respond-ping-before-start-fully.patch} (100%) rename leaves-server/minecraft-patches/features/{0057-Faster-chunk-serialization.patch => 0059-Faster-chunk-serialization.patch} (99%) rename leaves-server/minecraft-patches/features/{0058-Skip-secondary-POI-sensor-if-absent.patch => 0060-Skip-secondary-POI-sensor-if-absent.patch} (87%) delete mode 100644 leaves-server/minecraft-patches/features/0061-Reduce-array-allocations.patch rename leaves-server/minecraft-patches/features/{0059-Store-mob-counts-in-an-array.patch => 0061-Store-mob-counts-in-an-array.patch} (100%) rename leaves-server/minecraft-patches/features/{0060-Optimize-noise-generation.patch => 0062-Optimize-noise-generation.patch} (100%) rename leaves-server/minecraft-patches/features/{0062-Optimize-sun-burn-tick.patch => 0063-Optimize-sun-burn-tick.patch} (63%) rename leaves-server/minecraft-patches/features/{0063-Reduce-lambda-and-Optional-allocation-in-EntityBased.patch => 0064-Reduce-lambda-and-Optional-allocation-in-EntityBased.patch} (100%) rename leaves-server/minecraft-patches/features/{0064-Avoid-Class-isAssignableFrom-call-in-ClassInstanceMu.patch => 0065-Avoid-Class-isAssignableFrom-call-in-ClassInstanceMu.patch} (100%) rename leaves-server/minecraft-patches/features/{0065-Optimized-CubePointRange.patch => 0066-Optimized-CubePointRange.patch} (100%) rename leaves-server/minecraft-patches/features/{0066-Check-frozen-ticks-before-landing-block.patch => 0067-Check-frozen-ticks-before-landing-block.patch} (89%) rename leaves-server/minecraft-patches/features/{0067-Skip-entity-move-if-movement-is-zero.patch => 0068-Skip-entity-move-if-movement-is-zero.patch} (86%) rename leaves-server/minecraft-patches/features/{0068-Skip-cloning-advancement-criteria.patch => 0069-Skip-cloning-advancement-criteria.patch} (88%) rename leaves-server/minecraft-patches/features/{0069-Fix-villagers-dont-release-memory.patch => 0070-Fix-villagers-dont-release-memory.patch} (80%) rename leaves-server/minecraft-patches/features/{0070-Avoid-anvil-too-expensive.patch => 0071-Avoid-anvil-too-expensive.patch} (67%) rename leaves-server/minecraft-patches/features/{0071-Bow-infinity-fix.patch => 0072-Bow-infinity-fix.patch} (54%) rename leaves-server/minecraft-patches/features/{0072-Zero-tick-plants.patch => 0073-Zero-tick-plants.patch} (83%) rename leaves-server/minecraft-patches/features/{0073-Force-peaceful-mode-switch.patch => 0074-Force-peaceful-mode-switch.patch} (88%) rename leaves-server/minecraft-patches/features/{0074-Replay-Mod-API.patch => 0075-Replay-Mod-API.patch} (94%) rename leaves-server/minecraft-patches/features/{0075-Leaves-I18n.patch => 0076-Leaves-I18n.patch} (94%) rename leaves-server/minecraft-patches/features/{0076-Fix-minecraft-hopper-not-work-without-player.patch => 0077-Fix-minecraft-hopper-not-work-without-player.patch} (80%) rename leaves-server/minecraft-patches/features/{0077-RNG-Fishing.patch => 0078-RNG-Fishing.patch} (88%) delete mode 100644 leaves-server/minecraft-patches/features/0079-Spider-jockeys-drop-gapples.patch rename leaves-server/minecraft-patches/features/{0078-Wool-Hopper-Counter.patch => 0079-Wool-Hopper-Counter.patch} (91%) create mode 100644 leaves-server/minecraft-patches/features/0080-Spider-jockeys-drop-gapples.patch rename leaves-server/minecraft-patches/features/{0080-Force-Void-Trade.patch => 0081-Force-Void-Trade.patch} (87%) rename leaves-server/minecraft-patches/features/{0081-Villager-infinite-discounts.patch => 0082-Villager-infinite-discounts.patch} (100%) rename leaves-server/minecraft-patches/features/{0082-CCE-update-suppression.patch => 0083-CCE-update-suppression.patch} (87%) rename leaves-server/minecraft-patches/features/{0083-Disable-offline-warn-if-use-proxy.patch => 0084-Disable-offline-warn-if-use-proxy.patch} (88%) rename leaves-server/minecraft-patches/features/{0084-Armor-stand-cant-kill-by-mob-projectile.patch => 0085-Armor-stand-cant-kill-by-mob-projectile.patch} (89%) rename leaves-server/minecraft-patches/features/{0085-Make-Item-tick-vanilla.patch => 0086-Make-Item-tick-vanilla.patch} (81%) rename leaves-server/minecraft-patches/features/{0086-Copper-Bulb-1-gt-delay.patch => 0087-Copper-Bulb-1-gt-delay.patch} (96%) rename leaves-server/minecraft-patches/features/{0087-Crafter-1-gt-delay.patch => 0088-Crafter-1-gt-delay.patch} (80%) rename leaves-server/minecraft-patches/features/{0088-More-Region-Format-Support.patch => 0089-More-Region-Format-Support.patch} (90%) delete mode 100644 leaves-server/minecraft-patches/features/0089-No-TNT-place-update.patch create mode 100644 leaves-server/minecraft-patches/features/0090-No-TNT-place-update.patch delete mode 100644 leaves-server/minecraft-patches/features/0091-Placing-locked-hopper-no-longer-send-NC-updates.patch rename leaves-server/minecraft-patches/features/{0090-Servux-Protocol.patch => 0091-Servux-Protocol.patch} (75%) create mode 100644 leaves-server/minecraft-patches/features/0092-Placing-locked-hopper-no-longer-send-NC-updates.patch rename leaves-server/minecraft-patches/features/{0092-Renewable-deepslate.patch => 0093-Renewable-deepslate.patch} (90%) rename leaves-server/minecraft-patches/features/{0093-Renewable-sponges.patch => 0094-Renewable-sponges.patch} (91%) rename leaves-server/minecraft-patches/features/{0094-Renewable-coral.patch => 0095-Renewable-coral.patch} (77%) rename leaves-server/minecraft-patches/features/{0095-Fast-resume.patch => 0096-Fast-resume.patch} (74%) rename leaves-server/minecraft-patches/features/{0096-Vanilla-hopper.patch => 0097-Vanilla-hopper.patch} (96%) rename leaves-server/minecraft-patches/features/{0097-Old-hopper-suckin-behavior.patch => 0098-Old-hopper-suckin-behavior.patch} (88%) rename leaves-server/minecraft-patches/features/{0098-Fix-falling-block-s-block-location.patch => 0099-Fix-falling-block-s-block-location.patch} (87%) rename leaves-server/minecraft-patches/features/{0099-Bytebuf-API.patch => 0100-Bytebuf-API.patch} (75%) rename leaves-server/minecraft-patches/features/{0100-Allow-grindstone-overstacking.patch => 0101-Allow-grindstone-overstacking.patch} (91%) rename leaves-server/minecraft-patches/features/{0101-Configurable-MC-67.patch => 0102-Configurable-MC-67.patch} (85%) rename leaves-server/minecraft-patches/features/{0102-Disable-end-gateway-portal-entity-ticking.patch => 0103-Disable-end-gateway-portal-entity-ticking.patch} (92%) rename leaves-server/minecraft-patches/features/{0103-Disable-crystal-portal-proximity-check.patch => 0104-Disable-crystal-portal-proximity-check.patch} (79%) rename leaves-server/minecraft-patches/features/{0104-Can-disable-LivingEntity-aiStep-alive-check.patch => 0105-Can-disable-LivingEntity-aiStep-alive-check.patch} (81%) delete mode 100644 leaves-server/minecraft-patches/features/0105-Fix-fortress-mob-spawn.patch create mode 100644 leaves-server/minecraft-patches/features/0107-Old-Block-remove-behaviour.patch delete mode 100644 leaves-server/minecraft-patches/features/0107-Old-BlockEntity-behaviour.patch create mode 100644 leaves-server/minecraft-patches/features/0110-Configurable-collision-behavior.patch delete mode 100644 leaves-server/minecraft-patches/features/0110-Fix-Incorrect-Collision-Behavior-for-Block-Shape.patch rename leaves-server/minecraft-patches/features/{0120-Fix-SculkCatalyst-exp-skip.patch => 0119-Fix-SculkCatalyst-exp-skip.patch} (83%) create mode 100644 leaves-server/minecraft-patches/features/0120-Vanilla-creative-pickup-behavior.patch create mode 100644 leaves-server/minecraft-patches/features/0121-Vanilla-portal-handle.patch create mode 100644 leaves-server/minecraft-patches/features/0122-Fix-chunk-reload-detector.patch create mode 100644 leaves-server/minecraft-patches/features/0123-Do-not-reset-placed-block-on-exception.patch create mode 100644 leaves-server/minecraft-patches/features/0124-Do-not-prevent-block-entity-and-entity-crash-at-Leve.patch create mode 100644 leaves-server/minecraft-patches/features/0125-Tripwire-behavior-modifier.patch create mode 100644 leaves-server/minecraft-patches/features/0126-Old-nether-portal-collision.patch create mode 100644 leaves-server/minecraft-patches/features/0127-Spawn-invulnerable-time.patch create mode 100644 leaves-server/minecraft-patches/features/0128-Old-zombie-reinforcement.patch create mode 100644 leaves-server/minecraft-patches/features/0129-Sound-update-suppression.patch create mode 100644 leaves-server/minecraft-patches/features/0130-Old-zombie-piglin-drop-behavior.patch create mode 100644 leaves-server/minecraft-patches/features/0131-Fast-exp-orb-absorb.patch delete mode 100644 leaves-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch rename leaves-server/paper-patches/features/{0011-Force-peaceful-mode-switch.patch => 0010-Force-peaceful-mode-switch.patch} (87%) delete mode 100644 leaves-server/paper-patches/features/0010-Reduce-array-allocations.patch rename leaves-server/paper-patches/features/{0012-Replay-Mod-API.patch => 0011-Replay-Mod-API.patch} (82%) rename leaves-server/paper-patches/features/{0013-Force-minecraft-command.patch => 0012-Force-minecraft-command.patch} (100%) rename leaves-server/paper-patches/features/{0014-Bytebuf-API.patch => 0013-Bytebuf-API.patch} (79%) create mode 100644 leaves-server/paper-patches/features/0014-Leaves-plugin.patch rename leaves-server/paper-patches/features/{0016-Fix-SculkCatalyst-exp-skip.patch => 0015-Fix-SculkCatalyst-exp-skip.patch} (87%) delete mode 100644 leaves-server/paper-patches/features/0015-Leaves-plugins.patch create mode 100644 leaves-server/paper-patches/features/0016-Leaves-Config-API.patch delete mode 100644 leaves-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch create mode 100644 leaves-server/src/main/java/co/aikar/timings/Timings.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ShootAction.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/config/InternalConfigProvider.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/FeaturesConfiguration.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/MixinConfiguration.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageIndex.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/AbstractInvokerHolder.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/BytebufReceiverInvokerHolder.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/EmptyInvokerHolder.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/InitInvokerHolder.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/MinecraftRegisterInvokerHolder.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/PayloadReceiverInvokerHolder.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/PlayerInvokerHolder.java create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/BlockNameProvider.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ObjectNameProvider.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/SimpleToolHandler.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/ToolHandler.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/payload/BufCustomPacketPayload.java delete mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/util/ArrayConstants.java delete mode 100644 patches/removed/server/0022-Early-return-optimization-for-target-finding.patch delete mode 100644 patches/removed/server/0024-Move-ThreadUnsafeRandom-Initialization.patch delete mode 100644 patches/removed/server/0026-Remove-iterators-from-inventory-contains.patch delete mode 100644 patches/removed/server/0026-Use-thread-unsafe-random-for-mob-spawning.patch delete mode 100644 patches/removed/server/0028-Remove-streams-and-iterators-from-range-check.patch delete mode 100644 patches/removed/server/0030-Use-aging-cache-for-biome-temperatures.patch delete mode 100644 patches/removed/server/0041-Improve-fluid-direction-caching.patch delete mode 100644 patches/removed/server/0067-Cache-world-generator-sea-level.patch delete mode 100644 patches/removed/server/0077-Cache-BlockStatePairKey-hash.patch delete mode 100644 patches/removed/server/0099-Disable-moved-wrongly-threshold.patch delete mode 100644 patches/removed/server/0115-Fix-Warden-GameEventListener-register-on-load.patch delete mode 100644 patches/removed/server/0131-Optimize-random-calls-in-chunk-ticking.patch delete mode 100644 patches/unapplied/server/0058-Spawn-ignore-lc.patch diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 462c8bb0..809a5ed7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: java-version: "21" distribution: "zulu" - name: Setup Gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: add-job-summary: never generate-job-summary: false diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f49cc820..a75ae17d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: java-version: "21" distribution: "zulu" - name: Setup Gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 with: add-job-summary: never generate-job-summary: false diff --git a/LICENSE.md b/LICENSE.md index cf7c19fd..17ec02d3 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -16,4 +16,5 @@ should submit a pull request to this project to add their name. ```text LittleChest +Helvetica Volubi ``` diff --git a/README.md b/README.md index 839809af..4e3136ed 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ maven { } dependencies { - compileOnly("org.leavesmc.leaves:leaves-api:1.21.4-R0.1-SNAPSHOT") + compileOnly("org.leavesmc.leaves:leaves-api:1.21.5-R0.1-SNAPSHOT") } ``` @@ -40,7 +40,7 @@ Each time you want to update your dependency, you must re-build Leaves. Leaves-Server: ```kotlin dependencies { - compileOnly("org.leavesmc.leaves:leaves:1.21.4-R0.1-SNAPSHOT") + compileOnly("org.leavesmc.leaves:leaves:1.21.5-R0.1-SNAPSHOT") } ``` diff --git a/README_cn.md b/README_cn.md index d364489e..15f131a8 100644 --- a/README_cn.md +++ b/README_cn.md @@ -30,7 +30,7 @@ maven { } dependencies { - compileOnly("org.leavesmc.leaves:leaves-api:1.21.4-R0.1-SNAPSHOT") + compileOnly("org.leavesmc.leaves:leaves-api:1.21.5-R0.1-SNAPSHOT") } ``` @@ -39,7 +39,7 @@ dependencies { Leaves-Server: ```kotlin dependencies { - compileOnly("org.leavesmc.leaves:leaves:1.21.4-R0.1-SNAPSHOT") + compileOnly("org.leavesmc.leaves:leaves:1.21.5-R0.1-SNAPSHOT") } ``` diff --git a/gradle.properties b/gradle.properties index 5fbbc59f..554b95ac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ group=org.leavesmc.leaves -version=1.21.4-R0.1-SNAPSHOT -mcVersion=1.21.4 -paperRef=9b1798d6438107fdf0d5939b79a8cf71f4d16e2c -preVersion=false +version=1.21.5-R0.1-SNAPSHOT +mcVersion=1.21.5 +paperRef=2ba1675c7506cadd8a540ea452e5dafb79ae8947 +preVersion=true org.gradle.caching=true org.gradle.parallel=true diff --git a/leaves-api/build.gradle.kts.patch b/leaves-api/build.gradle.kts.patch index 48fd6832..99e53e17 100644 --- a/leaves-api/build.gradle.kts.patch +++ b/leaves-api/build.gradle.kts.patch @@ -1,21 +1,21 @@ --- a/paper-api/build.gradle.kts +++ b/paper-api/build.gradle.kts -@@ -93,19 +_,33 @@ +@@ -90,19 +_,33 @@ testRuntimeOnly("org.junit.platform:junit-platform-launcher") } --val generatedApiPath: java.nio.file.Path = layout.projectDirectory.dir("src/generated/java").asFile.toPath() -+val generatedApiPath: java.nio.file.Path = rootProject.layout.projectDirectory.dir("paper-api/src/generated/java").asFile.toPath() // Leaves - build change +-val generatedDir: java.nio.file.Path = layout.projectDirectory.dir("src/generated/java").asFile.toPath() ++val generatedDir: java.nio.file.Path = rootProject.layout.projectDirectory.dir("paper-api/src/generated/java").asFile.toPath() // Leaves - build change idea { module { - generatedSourceDirs.add(generatedApiPath.toFile()) + generatedSourceDirs.add(generatedDir.toFile()) } } +// Leaves start - build change sourceSets { main { java { - srcDir(generatedApiPath) + srcDir(generatedDir) + srcDir(file("../paper-api/src/main/java")) + } + resources { @@ -35,7 +35,7 @@ val outgoingVariants = arrayOf("runtimeElements", "apiElements", "sourcesElements", "javadocElements") val mainCapability = "${project.group}:${project.name}:${project.version}" -@@ -150,6 +_,16 @@ +@@ -147,6 +_,16 @@ } } @@ -52,7 +52,7 @@ tasks.jar { from(generateApiVersioningFile.map { it.outputs.files.singleFile }) { into("META-INF/maven/${project.group}/${project.name}") -@@ -169,7 +_,7 @@ +@@ -166,7 +_,7 @@ tasks.withType { val options = options as StandardJavadocDocletOptions @@ -61,7 +61,7 @@ options.use() options.isDocFilesSubDirs = true options.links( -@@ -202,16 +_,18 @@ +@@ -199,16 +_,18 @@ } // workaround for https://github.com/gradle/gradle/issues/4046 diff --git a/leaves-api/paper-patches/features/0001-Delete-Timings.patch b/leaves-api/paper-patches/features/0001-Delete-Timings.patch index 0c42184f..4adb90ae 100644 --- a/leaves-api/paper-patches/features/0001-Delete-Timings.patch +++ b/leaves-api/paper-patches/features/0001-Delete-Timings.patch @@ -730,7 +730,7 @@ index 199789d56d22fcb1b77ebd56805cc28aa5a5ab0a..00000000000000000000000000000000 -} diff --git a/src/main/java/co/aikar/timings/TimingHistory.java b/src/main/java/co/aikar/timings/TimingHistory.java deleted file mode 100644 -index 6f6eb1a2e6c8d49014a7ae44540ee282bae5200e..0000000000000000000000000000000000000000 +index c8287776ad585d04fb4fa3290cd73d7097035ea0..0000000000000000000000000000000000000000 --- a/src/main/java/co/aikar/timings/TimingHistory.java +++ /dev/null @@ -1,357 +0,0 @@ @@ -1025,7 +1025,7 @@ index 6f6eb1a2e6c8d49014a7ae44540ee282bae5200e..00000000000000000000000000000000 - final TicksRecord ticksRecord = new TicksRecord(); - final PingRecord pingRecord = new PingRecord(); - final TimingData fst = TimingsManager.FULL_SERVER_TICK.minuteData.clone(); -- final double tps = 1E9 / ( System.nanoTime() - lastMinuteTime ) * ticksRecord.timed; +- final double tps = 1E9 / (System.nanoTime() - lastMinuteTime) * ticksRecord.timed; - final double usedMemory = TimingsManager.FULL_SERVER_TICK.avgUsedMemory; - final double freeMemory = TimingsManager.FULL_SERVER_TICK.avgFreeMemory; - final double loadAvg = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage(); @@ -1743,7 +1743,7 @@ index b83e5ff7ada8771fdf27ba9807c77ba6a4ce12da..00000000000000000000000000000000 -} diff --git a/src/main/java/co/aikar/timings/TimingsManager.java b/src/main/java/co/aikar/timings/TimingsManager.java deleted file mode 100644 -index e72ad05abada04426e32a73d02b21cb69079d268..0000000000000000000000000000000000000000 +index 83a70358e9b7d3d9ae76cf130915b3c33d09a793..0000000000000000000000000000000000000000 --- a/src/main/java/co/aikar/timings/TimingsManager.java +++ /dev/null @@ -1,192 +0,0 @@ @@ -1902,9 +1902,9 @@ index e72ad05abada04426e32a73d02b21cb69079d268..00000000000000000000000000000000 - public static Timing getCommandTiming(@Nullable String pluginName, @NotNull Command command) { - Plugin plugin = null; - final Server server = Bukkit.getServer(); -- if (!( server == null || pluginName == null || -- "minecraft".equals(pluginName) || "bukkit".equals(pluginName) || -- "spigot".equalsIgnoreCase(pluginName) || "paper".equals(pluginName) +- if (!(server == null || pluginName == null || +- "minecraft".equals(pluginName) || "bukkit".equals(pluginName) || +- "spigot".equalsIgnoreCase(pluginName) || "paper".equals(pluginName) - )) { - plugin = server.getPluginManager().getPlugin(pluginName); - } @@ -2141,10 +2141,10 @@ index dae84243804b4b076cafb3e1b29bdcf614efc93f..00000000000000000000000000000000 -} diff --git a/src/main/java/co/aikar/util/JSONUtil.java b/src/main/java/co/aikar/util/JSONUtil.java deleted file mode 100644 -index c105a1429ca58b37be265708ec345e00f0d43ed8..0000000000000000000000000000000000000000 +index 232bf09e1a7bc176bfd34b1acb5326a06a92fe79..0000000000000000000000000000000000000000 --- a/src/main/java/co/aikar/util/JSONUtil.java +++ /dev/null -@@ -1,141 +0,0 @@ +@@ -1,138 +0,0 @@ -package co.aikar.util; - -import com.google.common.base.Function; @@ -2152,10 +2152,7 @@ index c105a1429ca58b37be265708ec345e00f0d43ed8..00000000000000000000000000000000 -import com.google.common.collect.Maps; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; --import org.json.simple.JSONArray; --import org.json.simple.JSONObject; - --import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; @@ -2863,10 +2860,10 @@ index 3e61a926620a67daec3af54b72a1b911eaef2ed4..00000000000000000000000000000000 - } -} diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 71eb845a4d3b8b6ec3b816a0f20ec807e0f9a86d..a43419c23aa0f6fd809caf5a841cb138f350b7ba 100644 +index 27a7c69f23084e821d945d5e97e51a94ddd94e58..d645ee8470a2dd9f7b8eff2b7ff2211aba9c342f 100644 --- a/src/main/java/org/bukkit/command/Command.java +++ b/src/main/java/org/bukkit/command/Command.java -@@ -33,16 +33,6 @@ public abstract class Command { +@@ -32,16 +32,6 @@ public abstract class Command { protected String usageMessage; private String permission; private net.kyori.adventure.text.Component permissionMessage; // Paper @@ -2884,10 +2881,10 @@ index 71eb845a4d3b8b6ec3b816a0f20ec807e0f9a86d..a43419c23aa0f6fd809caf5a841cb138 protected Command(@NotNull String name) { this(name, "", "/" + name, new ArrayList()); diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java -index abe256e1e45ce28036da4aa1586715bc8a1a3414..9eab8024e0675865f17669847759a26d28f74f3a 100644 +index 59fada9b1eb78238d280c6bbb711f52facba52c6..eb4d78c6111a530d015a0b91d14c40ad0eec9ca7 100644 --- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java +++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java -@@ -12,7 +12,6 @@ public class FormattedCommandAlias extends Command { +@@ -14,7 +14,6 @@ public class FormattedCommandAlias extends Command { public FormattedCommandAlias(@NotNull String alias, @NotNull String[] formatStrings) { super(alias); @@ -2895,7 +2892,7 @@ index abe256e1e45ce28036da4aa1586715bc8a1a3414..9eab8024e0675865f17669847759a26d this.formatStrings = formatStrings; } -@@ -120,10 +119,6 @@ public class FormattedCommandAlias extends Command { +@@ -122,10 +121,6 @@ public class FormattedCommandAlias extends Command { return formatString.trim(); // Paper - Causes an extra space at the end, breaks with brig commands } @@ -2907,18 +2904,18 @@ index abe256e1e45ce28036da4aa1586715bc8a1a3414..9eab8024e0675865f17669847759a26d return i >= j && i <= k; } diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index 5df19bd701c67506689fc7f49d91f99ebfbc83f0..940565704d0e8914a76cf25daf7d1f5ecd99bad4 100644 +index 4acda947b7d69ab4133b4cc94e76d945e4d148d5..d356f1895e8f3fae14bbbe1f60e589af3856b9ec 100644 --- a/src/main/java/org/bukkit/command/SimpleCommandMap.java +++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java -@@ -39,7 +39,6 @@ public class SimpleCommandMap implements CommandMap { - register("bukkit", new VersionCommand("version")); +@@ -32,7 +32,6 @@ public class SimpleCommandMap implements CommandMap { + + private void setDefaultCommands() { register("bukkit", new ReloadCommand("reload")); - //register("bukkit", new PluginsCommand("plugins")); // Paper -- register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Paper +- register("bukkit", new co.aikar.timings.TimingsCommand("timings")); } public void setFallbackCommands() { -@@ -71,7 +70,6 @@ public class SimpleCommandMap implements CommandMap { +@@ -64,7 +63,6 @@ public class SimpleCommandMap implements CommandMap { */ @Override public boolean register(@NotNull String label, @NotNull String fallbackPrefix, @NotNull Command command) { @@ -2926,7 +2923,7 @@ index 5df19bd701c67506689fc7f49d91f99ebfbc83f0..940565704d0e8914a76cf25daf7d1f5e label = label.toLowerCase(Locale.ROOT).trim(); fallbackPrefix = fallbackPrefix.toLowerCase(Locale.ROOT).trim(); boolean registered = register(label, command, false, fallbackPrefix); -@@ -153,17 +151,9 @@ public class SimpleCommandMap implements CommandMap { +@@ -146,17 +144,9 @@ public class SimpleCommandMap implements CommandMap { return false; } @@ -2977,35 +2974,45 @@ index 001465eedafa51ac027a4db51cba6223edfe1171..dd98b4886d21ac92d9f9139450258754 // Paper start diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index b412aaf08901d169ac9fc89b36f9d6ccb95c53d3..b2257f3e51a754b7d3d946b434745f22e3305b0a 100644 +index 163e9a0e179dc88be93614ff66ee2be3eccc694f..f4f1a51a3b0c34b87270ba81b705a8ee5d615f8a 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -43,7 +43,6 @@ import org.bukkit.plugin.TimedRegisteredListener; - import org.bukkit.plugin.UnknownDependencyException; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; --import org.spigotmc.CustomTimingsHandler; // Spigot - import org.yaml.snakeyaml.error.YAMLException; - - /** -@@ -293,7 +292,7 @@ public final class JavaPluginLoader implements PluginLoader { +@@ -290,22 +290,22 @@ public final class JavaPluginLoader implements PluginLoader { } } - EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Paper -+ EventExecutor executor = new EventExecutor() { // Paper - @Override - public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper - try { -@@ -307,7 +306,7 @@ public final class JavaPluginLoader implements PluginLoader { - throw new EventException(t); +- @Override +- public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper +- try { +- if (!eventClass.isAssignableFrom(event.getClass())) { +- return; +- } +- method.invoke(listener, event); +- } catch (InvocationTargetException ex) { +- throw new EventException(ex.getCause()); +- } catch (Throwable t) { +- throw new EventException(t); ++ // Leaves start - Delete timings ++ // Paper ++ EventExecutor executor = (listener1, event) -> { // Paper ++ try { ++ if (!eventClass.isAssignableFrom(event.getClass())) { ++ return; } ++ method.invoke(listener1, event); ++ } catch (java.lang.reflect.InvocationTargetException ex) { ++ throw new org.bukkit.event.EventException(ex.getCause()); ++ } catch (Throwable t) { ++ throw new org.bukkit.event.EventException(t); } - }, plugin, method, eventClass); // Paper + }; // Paper - if (false) { // Spigot - RL handles useTimings check now - eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); - } else { + eventSet.add(new RegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); ++ // Leaves end - Delete timings + } + return ret; + } diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java deleted file mode 100644 index 5fbacfcf108432c5187aa9a4092d00d7d5b0fd53..0000000000000000000000000000000000000000 diff --git a/leaves-api/paper-patches/features/0002-Add-isShrink-to-EntityResurrectEvent.patch b/leaves-api/paper-patches/features/0002-Add-isShrink-to-EntityResurrectEvent.patch index 9b942579..20355983 100644 --- a/leaves-api/paper-patches/features/0002-Add-isShrink-to-EntityResurrectEvent.patch +++ b/leaves-api/paper-patches/features/0002-Add-isShrink-to-EntityResurrectEvent.patch @@ -5,38 +5,38 @@ Subject: [PATCH] Add isShrink to EntityResurrectEvent diff --git a/src/main/java/org/bukkit/event/entity/EntityResurrectEvent.java b/src/main/java/org/bukkit/event/entity/EntityResurrectEvent.java -index 2a7426c157f6a06f2491d95d67df95a0fb809926..8fe7d559ad6cbb8f15584c202067250dd55a8ede 100644 +index fa60c0ce5c79757952ad39932e1c5fac8b068811..71fd070aaebfd9fa0fbfd6eb7cd26c8b34120203 100644 --- a/src/main/java/org/bukkit/event/entity/EntityResurrectEvent.java +++ b/src/main/java/org/bukkit/event/entity/EntityResurrectEvent.java -@@ -16,20 +16,44 @@ import org.jetbrains.annotations.Nullable; - public class EntityResurrectEvent extends EntityEvent implements Cancellable { +@@ -17,22 +17,46 @@ public class EntityResurrectEvent extends EntityEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); -- // -+ + private static final HandlerList HANDLER_LIST = new HandlerList(); + +- private final EquipmentSlot hand; +- private boolean cancelled; + private boolean shrink; - - private final EquipmentSlot hand; ++ ++ private final EquipmentSlot hand; @ApiStatus.Internal -- public EntityResurrectEvent(@NotNull LivingEntity what, @Nullable EquipmentSlot hand) { -+ public EntityResurrectEvent(@NotNull LivingEntity what, @Nullable EquipmentSlot hand, boolean shrink) { - super(what); +- public EntityResurrectEvent(@NotNull LivingEntity livingEntity, @Nullable EquipmentSlot hand) { ++ public EntityResurrectEvent(@NotNull LivingEntity livingEntity, @Nullable EquipmentSlot hand, boolean shrink) { + super(livingEntity); + this.shrink = shrink; this.hand = hand; } -+ public EntityResurrectEvent(@NotNull LivingEntity what, @Nullable EquipmentSlot hand) { -+ this(what, hand, true); ++ public EntityResurrectEvent(@NotNull LivingEntity livingEntity, @Nullable EquipmentSlot hand) { ++ this(livingEntity, hand, true); + } + + @ApiStatus.Internal @Deprecated(since = "1.19.2", forRemoval = true) - public EntityResurrectEvent(@NotNull LivingEntity what) { -- this(what, null); -+ this(what, null, true); -+ } -+ + public EntityResurrectEvent(@NotNull LivingEntity livingEntity) { + this(livingEntity, null); + } + + /** + * Get is shrink item + * @@ -53,6 +53,8 @@ index 2a7426c157f6a06f2491d95d67df95a0fb809926..8fe7d559ad6cbb8f15584c202067250d + */ + public void setShrink(boolean shrink) { + this.shrink = shrink; - } - ++ } ++ @NotNull + @Override + public LivingEntity getEntity() { diff --git a/leaves-api/paper-patches/features/0003-Add-fakeplayer-api.patch b/leaves-api/paper-patches/features/0003-Add-fakeplayer-api.patch index 0e840f2c..c99fba4b 100644 --- a/leaves-api/paper-patches/features/0003-Add-fakeplayer-api.patch +++ b/leaves-api/paper-patches/features/0003-Add-fakeplayer-api.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add fakeplayer api diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 4eb723afaca049a816d16370b383fa37441eafd4..e1c6974cfd96b406314901862c2d92ad0a4ba8f2 100644 +index c9ea6559f809a6732588b8908001807be3d91196..fe30de1f0a7fc7112466b6eb2e5813f39259c3b6 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2996,4 +2996,15 @@ public final class Bukkit { +@@ -3007,4 +3007,15 @@ public final class Bukkit { public static void restart() { server.restart(); } @@ -25,18 +25,10 @@ index 4eb723afaca049a816d16370b383fa37441eafd4..e1c6974cfd96b406314901862c2d92ad + // Leaves end - Bot API } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 0c1f3053ecb415a6dfbbe283bae8c1f6d8477e9c..e42fa3dc7f70a5e4426564f26d471c5bfc3d57f2 100644 +index ed899c4cb4b5261ceff56bbc9ca806e20904508e..a5370832380e93cf029588caeb8e29e03cc52db8 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -66,6 +66,7 @@ import org.jetbrains.annotations.ApiStatus; - import org.jetbrains.annotations.Contract; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; -+import org.leavesmc.leaves.entity.BotManager; - - /** - * Represents a server implementation. -@@ -2698,4 +2699,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2716,4 +2716,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ void allowPausing(@NotNull org.bukkit.plugin.Plugin plugin, boolean value); // Paper end - API to check if the server is sleeping @@ -47,6 +39,6 @@ index 0c1f3053ecb415a6dfbbe283bae8c1f6d8477e9c..e42fa3dc7f70a5e4426564f26d471c5b + * + * @return Bot Manager + */ -+ @NotNull BotManager getBotManager(); ++ @NotNull org.leavesmc.leaves.entity.BotManager getBotManager(); + // Leaves end - Bot API } diff --git a/leaves-api/paper-patches/features/0004-Force-peaceful-mode-switch.patch b/leaves-api/paper-patches/features/0004-Force-peaceful-mode-switch.patch index fb121ba7..82945e86 100644 --- a/leaves-api/paper-patches/features/0004-Force-peaceful-mode-switch.patch +++ b/leaves-api/paper-patches/features/0004-Force-peaceful-mode-switch.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Force peaceful mode switch diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index bff01411f4b2d3ecd9e6d807c3f450d72c108323..aae996e55cfda36adcca50065e05b5ecc4129614 100644 +index a8b64f78bf3c453094074b4b4d3c8fd07b9eb273..ed2bcc30cec91d3266c3d184b89b96bac6fb1f67 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java -@@ -4351,6 +4351,12 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient +@@ -4358,6 +4358,12 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient void setSendViewDistance(int viewDistance); // Paper end - view distance api diff --git a/leaves-api/paper-patches/features/0005-Replay-Mod-API.patch b/leaves-api/paper-patches/features/0005-Replay-Mod-API.patch index 65ca9cf8..dd7ce446 100644 --- a/leaves-api/paper-patches/features/0005-Replay-Mod-API.patch +++ b/leaves-api/paper-patches/features/0005-Replay-Mod-API.patch @@ -1,14 +1,14 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> -Date: Sun, 26 Jan 2025 01:39:16 -0500 +Date: Sat, 17 May 2025 17:36:22 +0800 Subject: [PATCH] Replay Mod API diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index e1c6974cfd96b406314901862c2d92ad0a4ba8f2..27bd3867836744a6e10507d165215ebf8dd7da53 100644 +index fe30de1f0a7fc7112466b6eb2e5813f39259c3b6..23f3ab31bbc9d197f9a82f4ed5003e6de814fad7 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -3007,4 +3007,10 @@ public final class Bukkit { +@@ -3018,4 +3018,10 @@ public final class Bukkit { return server.getBotManager(); } // Leaves end - Bot API @@ -20,23 +20,15 @@ index e1c6974cfd96b406314901862c2d92ad0a4ba8f2..27bd3867836744a6e10507d165215ebf + // Leaves end - Photographer API } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index e42fa3dc7f70a5e4426564f26d471c5bfc3d57f2..f4f83b1534a90127a77420a1768cd4b255a04868 100644 +index a5370832380e93cf029588caeb8e29e03cc52db8..2531e82464e54e0c1b707e7c5a62ff0fd5ed8637 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -67,6 +67,7 @@ import org.jetbrains.annotations.Contract; - import org.jetbrains.annotations.NotNull; - import org.jetbrains.annotations.Nullable; - import org.leavesmc.leaves.entity.BotManager; -+import org.leavesmc.leaves.entity.PhotographerManager; - - /** - * Represents a server implementation. -@@ -2708,4 +2709,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2725,4 +2725,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ - @NotNull BotManager getBotManager(); + @NotNull org.leavesmc.leaves.entity.BotManager getBotManager(); // Leaves end - Bot API + + // Leaves start - Photographer API -+ @NotNull PhotographerManager getPhotographerManager(); ++ @NotNull org.leavesmc.leaves.entity.PhotographerManager getPhotographerManager(); + // Leaves end - Photographer API } diff --git a/leaves-api/paper-patches/features/0006-Bytebuf-API.patch b/leaves-api/paper-patches/features/0006-Bytebuf-API.patch index 4c84b72f..a08920f1 100644 --- a/leaves-api/paper-patches/features/0006-Bytebuf-API.patch +++ b/leaves-api/paper-patches/features/0006-Bytebuf-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Bytebuf API diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 27bd3867836744a6e10507d165215ebf8dd7da53..190e532fd3ddaf78eae3ea0ba2b4b986ab5f9540 100644 +index 23f3ab31bbc9d197f9a82f4ed5003e6de814fad7..30488f80b98d1dba485e53601edb5cb0e23b7591 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -3013,4 +3013,10 @@ public final class Bukkit { +@@ -3024,4 +3024,10 @@ public final class Bukkit { return server.getPhotographerManager(); } // Leaves end - Photographer API @@ -20,12 +20,12 @@ index 27bd3867836744a6e10507d165215ebf8dd7da53..190e532fd3ddaf78eae3ea0ba2b4b986 + // Leaves end - Bytebuf API } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index f4f83b1534a90127a77420a1768cd4b255a04868..8d4c10d7d8b3982a960ca2cee52ce069b1916c24 100644 +index 2531e82464e54e0c1b707e7c5a62ff0fd5ed8637..a1742e64232c949dc88deb5d6083c4bf62e6aae9 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2713,4 +2713,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2729,4 +2729,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi // Leaves start - Photographer API - @NotNull PhotographerManager getPhotographerManager(); + @NotNull org.leavesmc.leaves.entity.PhotographerManager getPhotographerManager(); // Leaves end - Photographer API + + // Leaves start - Bytebuf API @@ -33,10 +33,10 @@ index f4f83b1534a90127a77420a1768cd4b255a04868..8d4c10d7d8b3982a960ca2cee52ce069 + // Leaves end - Bytebuf API } diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 494dca2ee48a03953d47050b178496df12bc48c5..b429eb9a0326460a8841a1cfdfd6cd13c02ec2b7 100644 +index d34419693fc78b3f7e8f6bbf115f17f29e5e3377..ab45edbc10398d92ddfcfd16d12d49f5b4e87c4c 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -3853,6 +3853,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -3860,6 +3860,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM boolean isChunkSent(long chunkKey); // Paper end diff --git a/leaves-api/paper-patches/features/0007-Revert-raid-changes.patch b/leaves-api/paper-patches/features/0007-Revert-raid-changes.patch index 3526e298..32048e02 100644 --- a/leaves-api/paper-patches/features/0007-Revert-raid-changes.patch +++ b/leaves-api/paper-patches/features/0007-Revert-raid-changes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Revert raid changes diff --git a/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java b/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java -index f6218d317af4f4d83292a10abdf583fb01824232..3eb836575307116ce0668eadd6a6ee0a9aafc7cd 100644 +index 22e14ba522510d659c191d72536cde895458d9ed..253f937dbd130fac064963b4af7572e1302fee8f 100644 --- a/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java +++ b/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java -@@ -219,9 +219,7 @@ public class EntityPotionEffectEvent extends EntityEvent implements Cancellable +@@ -221,9 +221,7 @@ public class EntityPotionEffectEvent extends EntityEvent implements Cancellable /** * When a player gets bad omen after killing a patrol captain. * diff --git a/leaves-api/paper-patches/features/0008-Fix-SculkCatalyst-exp-skip.patch b/leaves-api/paper-patches/features/0008-Fix-SculkCatalyst-exp-skip.patch index e0d2db2c..97f865c0 100644 --- a/leaves-api/paper-patches/features/0008-Fix-SculkCatalyst-exp-skip.patch +++ b/leaves-api/paper-patches/features/0008-Fix-SculkCatalyst-exp-skip.patch @@ -5,36 +5,40 @@ Subject: [PATCH] Fix SculkCatalyst exp skip diff --git a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java -index 42ffb81708b327f765ba3235fdd1ab69cd7589fd..0a7e37420f8d024ffba1fd1c52edc50c10408e6e 100644 +index 76c08499b704a6cb0cb95ce69b9a9248d69cc127..316bbf8c95e4803190897d66a0c7d8b4316f4164 100644 --- a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java +++ b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java -@@ -25,17 +25,25 @@ public class EntityDeathEvent extends EntityEvent implements org.bukkit.event.Ca +@@ -28,6 +28,8 @@ public class EntityDeathEvent extends EntityEvent implements Cancellable { private float deathSoundVolume; private float deathSoundPitch; - // Paper end + + private int rewardExp; // Leaves - exp fix ++ + private boolean cancelled; - public EntityDeathEvent(@NotNull final LivingEntity entity, @NotNull DamageSource damageSource, @NotNull final List drops) { - this(entity, damageSource, drops, 0); - } + @ApiStatus.Internal +@@ -37,12 +39,19 @@ public class EntityDeathEvent extends EntityEvent implements Cancellable { - public EntityDeathEvent(@NotNull final LivingEntity what, @NotNull DamageSource damageSource, @NotNull final List drops, final int droppedExp) { -+ // Leaves start - exp fix -+ this(what, damageSource, drops, droppedExp, droppedExp); + @ApiStatus.Internal + public EntityDeathEvent(@NotNull final LivingEntity livingEntity, @NotNull DamageSource damageSource, @NotNull final List drops, final int droppedExp) { ++ // Leaves start - exp fix ++ this(livingEntity, damageSource, drops, droppedExp, droppedExp); + } + -+ public EntityDeathEvent(@NotNull final LivingEntity what, @NotNull DamageSource damageSource, @NotNull final List drops, final int droppedExp, final int rewardExp) { - super(what); ++ @ApiStatus.Internal ++ public EntityDeathEvent(@NotNull final LivingEntity livingEntity, @NotNull DamageSource damageSource, @NotNull final List drops, final int droppedExp, final int rewardExp) { + super(livingEntity); this.damageSource = damageSource; this.drops = drops; this.dropExp = droppedExp; + this.rewardExp = rewardExp; } +- + // Leaves end - exp fix - @NotNull @Override -@@ -75,6 +83,7 @@ public class EntityDeathEvent extends EntityEvent implements org.bukkit.event.Ca + public LivingEntity getEntity() { +@@ -81,6 +90,7 @@ public class EntityDeathEvent extends EntityEvent implements Cancellable { */ public void setDroppedExp(int exp) { this.dropExp = exp; @@ -42,11 +46,10 @@ index 42ffb81708b327f765ba3235fdd1ab69cd7589fd..0a7e37420f8d024ffba1fd1c52edc50c } /** -@@ -226,4 +235,14 @@ public class EntityDeathEvent extends EntityEvent implements org.bukkit.event.Ca +@@ -210,6 +220,16 @@ public class EntityDeathEvent extends EntityEvent implements Cancellable { this.deathSoundPitch = pitch; } - // Paper end -+ + + // Leaves start - exp fix + public int getRewardExp() { + return rewardExp; @@ -56,26 +59,28 @@ index 42ffb81708b327f765ba3235fdd1ab69cd7589fd..0a7e37420f8d024ffba1fd1c52edc50c + this.rewardExp = rewardExp; + } + // Leaves end - exp fix - } ++ + @Override + public boolean isCancelled() { + return this.cancelled; diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index ab7584873e46020148bceecbd42a43055684e6a0..7c99b1c6f5fc8e4ce442d111e7598ddb89d6ee05 100644 +index 6316a2f1d2dc0314397e33e6dbd354fb8bc50541..16d4e3d42710be5eb87372d31c0ea9935d441de0 100644 --- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -@@ -18,6 +18,7 @@ public class PlayerDeathEvent extends EntityDeathEvent { +@@ -23,6 +23,7 @@ public class PlayerDeathEvent extends EntityDeathEvent { + private Component deathMessage; + private Component deathScreenMessageOverride = null; + private boolean doExpDrop; ++ private boolean useApiExpDropStatus = false; // Leaves - exp fix private boolean keepLevel = false; private boolean keepInventory = false; - private boolean doExpDrop; // Paper - shouldDropExperience API -+ private boolean useApiExpDropStatus = false; // Leaves - exp fix - // Paper start - adventure - @org.jetbrains.annotations.ApiStatus.Internal - public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final @Nullable net.kyori.adventure.text.Component deathMessage) { -@@ -122,9 +123,16 @@ public class PlayerDeathEvent extends EntityDeathEvent { - */ - public void setShouldDropExperience(boolean doExpDrop) { + @Deprecated +@@ -82,8 +83,15 @@ public class PlayerDeathEvent extends EntityDeathEvent { + this.showDeathMessages = true; + this.deathMessage = LegacyComponentSerializer.legacySection().deserializeOrNull(deathMessage); this.doExpDrop = doExpDrop; + this.useApiExpDropStatus = true; // Leaves - exp fix } - // Paper end - shouldDropExperience API + // Leaves start - exp fix + public boolean forceUseEventDropStatus() { diff --git a/leaves-api/paper-patches/features/0009-Leaves-Config-API.patch b/leaves-api/paper-patches/features/0009-Leaves-Config-API.patch new file mode 100644 index 00000000..d1ad59e6 --- /dev/null +++ b/leaves-api/paper-patches/features/0009-Leaves-Config-API.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> +Date: Sun, 18 May 2025 19:59:11 +0800 +Subject: [PATCH] Leaves Config API + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 30488f80b98d1dba485e53601edb5cb0e23b7591..91fa30c1713795007faef73280713a33d2518487 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -3030,4 +3030,10 @@ public final class Bukkit { + return server.getBytebufManager(); + } + // Leaves end - Bytebuf API ++ ++ // Leaves start - Config API ++ public static org.leavesmc.leaves.config.LeavesConfigProvider getLeavesConfig() { ++ return server.getLeavesConfig(); ++ } ++ // Leaves end - Config API + } +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index a1742e64232c949dc88deb5d6083c4bf62e6aae9..75a1917d998bf8aa0b86a67ca0f0836804fad012 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -2733,4 +2733,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + // Leaves start - Bytebuf API + org.leavesmc.leaves.bytebuf.BytebufManager getBytebufManager(); + // Leaves end - Bytebuf API ++ ++ // Leaves start - Config API ++ org.leavesmc.leaves.config.LeavesConfigProvider getLeavesConfig(); ++ // Leaves End - Config API + } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/Bytebuf.java b/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/Bytebuf.java index 7038b2a5..fc34d446 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/Bytebuf.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/Bytebuf.java @@ -4,8 +4,8 @@ import com.google.gson.JsonElement; import org.bukkit.Bukkit; import org.bukkit.inventory.ItemStack; -import java.util.UUID; import java.util.List; +import java.util.UUID; public interface Bytebuf { @@ -103,5 +103,7 @@ public interface Bytebuf { Bytebuf copy(); + void retain(); + boolean release(); } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/BytebufManager.java b/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/BytebufManager.java index 8668e47d..f659eb34 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/BytebufManager.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/BytebufManager.java @@ -5,8 +5,10 @@ import org.leavesmc.leaves.bytebuf.packet.PacketListener; public interface BytebufManager { + @Deprecated void registerListener(Plugin plugin, PacketListener listener); + @Deprecated void unregisterListener(Plugin plugin, PacketListener listener); Bytebuf newBytebuf(int size); diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/Packet.java b/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/Packet.java index 8bb00c16..9342a7de 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/Packet.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/Packet.java @@ -2,5 +2,6 @@ package org.leavesmc.leaves.bytebuf.packet; import org.leavesmc.leaves.bytebuf.Bytebuf; +@Deprecated public record Packet(PacketType type, Bytebuf bytebuf) { } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketListener.java b/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketListener.java index e246c0a8..ba76b26a 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketListener.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketListener.java @@ -2,6 +2,7 @@ package org.leavesmc.leaves.bytebuf.packet; import org.bukkit.entity.Player; +@Deprecated public interface PacketListener { Packet onPacketIn(Player player, Packet packet); diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketType.java b/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketType.java index ceebd752..a0c28ae8 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketType.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketType.java @@ -1,5 +1,6 @@ package org.leavesmc.leaves.bytebuf.packet; +@Deprecated public enum PacketType { // ClientboundBundle, // ClientboundBundleDelimiter, diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/config/LeavesConfigProvider.java b/leaves-api/src/main/java/org/leavesmc/leaves/config/LeavesConfigProvider.java new file mode 100644 index 00000000..49e87d2a --- /dev/null +++ b/leaves-api/src/main/java/org/leavesmc/leaves/config/LeavesConfigProvider.java @@ -0,0 +1,8 @@ +package org.leavesmc.leaves.config; + +public interface LeavesConfigProvider { + + LeavesConfigValue getConfig(String configNode); + + void setConfig(String configNode, LeavesConfigValue value); +} diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/config/LeavesConfigValue.java b/leaves-api/src/main/java/org/leavesmc/leaves/config/LeavesConfigValue.java new file mode 100644 index 00000000..0180496d --- /dev/null +++ b/leaves-api/src/main/java/org/leavesmc/leaves/config/LeavesConfigValue.java @@ -0,0 +1,36 @@ +package org.leavesmc.leaves.config; + +public record LeavesConfigValue(Object value) { + + public int getInt() { + if (value instanceof Integer) { + return (Integer) value; + } + throw new ClassCastException("Value is not an integer"); + } + + public double getDouble() { + if (value instanceof Double) { + return (Double) value; + } + throw new ClassCastException("Value is not a double"); + } + + public boolean getBoolean() { + if (value instanceof Boolean) { + return (Boolean) value; + } + throw new ClassCastException("Value is not a boolean"); + } + + public String getString() { + if (value instanceof String) { + return (String) value; + } + throw new ClassCastException("Value is not a string"); + } + + public String toString() { + return value.toString(); + } +} diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/Bot.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/Bot.java index 7a1ee45d..1c8f7371 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/Bot.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/Bot.java @@ -17,31 +17,29 @@ public interface Bot extends Player { * * @return fakeplayer skin name */ - @Nullable - public String getSkinName(); + @Nullable String getSkinName(); /** * Gets the fakeplayer name without prefix and suffix * * @return fakeplayer real name */ - @NotNull - public String getRealName(); + @NotNull String getRealName(); /** * Gets the creator's UUID of the fakeplayer * * @return creator's UUID */ - @Nullable - public UUID getCreatePlayerUUID(); + @Nullable UUID getCreatePlayerUUID(); /** * Add an action to the fakeplayer * * @param action bot action */ - public void addAction(@NotNull LeavesBotAction action); + @org.jetbrains.annotations.ApiStatus.Experimental + void addAction(@NotNull LeavesBotAction action); /** * Get the copy action in giving index @@ -49,26 +47,27 @@ public interface Bot extends Player { * @param index index of actions * @return Action of that index */ - public LeavesBotAction getAction(int index); + @org.jetbrains.annotations.ApiStatus.Experimental + LeavesBotAction getAction(int index); /** * Get action size * * @return size */ - public int getActionSize(); + int getActionSize(); /** * Stop the action in giving index * * @param index index of actions */ - public void stopAction(int index); + void stopAction(int index); /** * Stop all the actions of the fakeplayer */ - public void stopAllActions(); + void stopAllActions(); /** * Remove the fakeplayer @@ -76,5 +75,5 @@ public interface Bot extends Player { * @param save should save * @return success */ - public boolean remove(boolean save); + boolean remove(boolean save); } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/BotCreator.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/BotCreator.java index e0a50b21..65df4ec5 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/BotCreator.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/BotCreator.java @@ -14,11 +14,11 @@ public interface BotCreator { return Bukkit.getBotManager().botCreator(realName, location); } - public BotCreator name(String name); + BotCreator name(String name); - public BotCreator skinName(String skinName); + BotCreator skinName(String skinName); - public BotCreator skin(String[] skin); + BotCreator skin(String[] skin); /** * Sets the skin of the bot using the Mojang API based on the provided skin name. @@ -27,19 +27,18 @@ public interface BotCreator { * * @return BotCreator */ - public BotCreator mojangAPISkin(); + BotCreator mojangAPISkin(); - public BotCreator location(@NotNull Location location); + BotCreator location(@NotNull Location location); - public BotCreator creator(@Nullable CommandSender creator); + BotCreator creator(@Nullable CommandSender creator); /** * Create a bot directly * * @return a bot, null spawn fail */ - @Nullable - public Bot spawn(); + @Nullable Bot spawn(); /** * Create a bot and apply skin of player names `skinName` from MojangAPI @@ -49,5 +48,5 @@ public interface BotCreator { * * @param consumer Consumer */ - public void spawnWithSkin(Consumer consumer); + void spawnWithSkin(Consumer consumer); } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/BotManager.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/BotManager.java index 105fc912..671e53f1 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/BotManager.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/BotManager.java @@ -19,8 +19,7 @@ public interface BotManager { * @param uuid the uuid to look up * @return a fakeplayer if one was found, null otherwise */ - @Nullable - public Bot getBot(@NotNull UUID uuid); + @Nullable Bot getBot(@NotNull UUID uuid); /** * Gets a fakeplayer object by the given name. @@ -28,15 +27,14 @@ public interface BotManager { * @param name the name to look up * @return a fakeplayer if one was found, null otherwise */ - @Nullable - public Bot getBot(@NotNull String name); + @Nullable Bot getBot(@NotNull String name); /** * Gets a view of all currently logged in fakeplayers. This view is a reused object, making some operations like Collection.size() zero-allocation. * * @return a view of fakeplayers. */ - public Collection getBots(); + Collection getBots(); /** * Register a custom bot action. @@ -45,7 +43,8 @@ public interface BotManager { * @param action action executor * @return true if success, or false */ - public boolean registerCustomBotAction(String name, CustomBotAction action); + @org.jetbrains.annotations.ApiStatus.Experimental + boolean registerCustomBotAction(String name, CustomBotAction action); /** * Unregister a custom bot action. @@ -53,7 +52,8 @@ public interface BotManager { * @param name action name * @return true if success, or false */ - public boolean unregisterCustomBotAction(String name); + @org.jetbrains.annotations.ApiStatus.Experimental + boolean unregisterCustomBotAction(String name); - public BotCreator botCreator(@NotNull String realName, @NotNull Location location); + BotCreator botCreator(@NotNull String realName, @NotNull Location location); } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/Photographer.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/Photographer.java index cc4226c5..6cc611c7 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/Photographer.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/Photographer.java @@ -8,20 +8,19 @@ import java.io.File; public interface Photographer extends Player { - @NotNull - public String getId(); + @NotNull String getId(); - public void setRecordFile(@NotNull File file); + void setRecordFile(@NotNull File file); - public void stopRecording(); + void stopRecording(); - public void stopRecording(boolean async); + void stopRecording(boolean async); - public void stopRecording(boolean async, boolean save); + void stopRecording(boolean async, boolean save); - public void pauseRecording(); + void pauseRecording(); - public void resumeRecording(); + void resumeRecording(); - public void setFollowPlayer(@Nullable Player player); + void setFollowPlayer(@Nullable Player player); } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/PhotographerManager.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/PhotographerManager.java index 492414e9..4a2b67f1 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/PhotographerManager.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/PhotographerManager.java @@ -1,33 +1,27 @@ package org.leavesmc.leaves.entity; import org.bukkit.Location; -import org.bukkit.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.entity.botaction.CustomBotAction; import org.leavesmc.leaves.replay.BukkitRecorderOption; import java.util.Collection; import java.util.UUID; public interface PhotographerManager { - @Nullable - public Photographer getPhotographer(@NotNull UUID uuid); + @Nullable Photographer getPhotographer(@NotNull UUID uuid); - @Nullable - public Photographer getPhotographer(@NotNull String id); + @Nullable Photographer getPhotographer(@NotNull String id); - @Nullable - public Photographer createPhotographer(@NotNull String id, @NotNull Location location); + @Nullable Photographer createPhotographer(@NotNull String id, @NotNull Location location); - @Nullable - public Photographer createPhotographer(@NotNull String id, @NotNull Location location, @NotNull BukkitRecorderOption recorderOption); + @Nullable Photographer createPhotographer(@NotNull String id, @NotNull Location location, @NotNull BukkitRecorderOption recorderOption); - public void removePhotographer(@NotNull String id); + void removePhotographer(@NotNull String id); - public void removePhotographer(@NotNull UUID uuid); + void removePhotographer(@NotNull UUID uuid); - public void removeAllPhotographers(); + void removeAllPhotographers(); - public Collection getPhotographers(); + Collection getPhotographers(); } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/BotActionType.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/BotActionType.java index f64aacc0..8a849c8a 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/BotActionType.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/BotActionType.java @@ -3,6 +3,8 @@ package org.leavesmc.leaves.entity.botaction; /** * A Leaves bot action enum */ + +@org.jetbrains.annotations.ApiStatus.Experimental public enum BotActionType { ATTACK("attack"), BREAK("break"), @@ -23,7 +25,7 @@ public enum BotActionType { private final String name; - private BotActionType(String name) { + BotActionType(String name) { this.name = name; } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/CustomBotAction.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/CustomBotAction.java index c952d7dd..88a57edb 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/CustomBotAction.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/CustomBotAction.java @@ -10,6 +10,7 @@ import java.util.List; /** * Represents a class which contains methods for a custom bot action */ +@org.jetbrains.annotations.ApiStatus.Experimental public interface CustomBotAction { /** @@ -18,37 +19,42 @@ public interface CustomBotAction { * @param bot bot of the action * @return true if once action finish, otherwise false */ - public boolean doTick(Bot bot); + boolean doTick(Bot bot); /** - * Created a new action instance. + * Created a new action instance. * * @param player player who create this action - * @param args passed action arguments + * @param args passed action arguments * @return a new action instance with given args */ - @Nullable - public CustomBotAction getNew(@Nullable Player player, String[] args); + @Nullable CustomBotAction getNew(@Nullable Player player, String[] args); /** * Requests a list of possible completions for a action argument. * * @return A List of a List of possible completions for the argument. */ - @NotNull - public List> getTabComplete(); + @NotNull List> getTabComplete(); /** - * Return a ticks to wait between {@link CustomBotAction#doTick(Bot)} + * Return the interval between {@link CustomBotAction#doTick(Bot)} * - * @return the ticks to wait between runs + * @return the tick interval */ - public int getTickDelay(); + int getInitialTickInterval(); + + /** + * Return the tick delay to the first {@link CustomBotAction#doTick(Bot)} + * + * @return the tick delay + */ + int getInitialTickDelay(); /** * Return a number of times {@link CustomBotAction#doTick(Bot)} can return true * * @return the number of times an action can be executed */ - public int getNumber(); + int getInitialNumber(); } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/LeavesBotAction.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/LeavesBotAction.java index 8a73f5cc..939ffa88 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/LeavesBotAction.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/botaction/LeavesBotAction.java @@ -5,61 +5,54 @@ import org.jetbrains.annotations.Nullable; import java.util.UUID; +@org.jetbrains.annotations.ApiStatus.Experimental public class LeavesBotAction { private final String actionName; - private int tickToExecute; - private int executeInterval; - private int remainingExecuteTime; private final UUID uuid; + private final int initialTickDelay; + private final int initialTickInterval; + private final int initialNumber; + private Player actionPlayer; + private int tickToNext; + private int numberRemaining; + private boolean cancel; - public LeavesBotAction(BotActionType type, int executeInterval, int remainingExecuteTime) { - this(type.getName(), executeInterval, remainingExecuteTime, UUID.randomUUID()); + public LeavesBotAction(BotActionType type, int initialTickInterval, int initialNumber) { + this(type.getName(), UUID.randomUUID(), 0, initialTickInterval, initialNumber); } - public LeavesBotAction(String name, int executeInterval, int remainingExecuteTime) { - this(name, executeInterval, remainingExecuteTime, UUID.randomUUID()); + public LeavesBotAction(BotActionType type, int initialTickDelay, int initialTickInterval, int initialNumber) { + this(type.getName(), UUID.randomUUID(), initialTickDelay, initialTickInterval, initialNumber); } - protected LeavesBotAction(String name, int executeInterval, int remainingExecuteTime, UUID actionUUID) { + protected LeavesBotAction(String name, UUID actionUUID, int initialTickDelay, int initialTickInterval, int initialNumber) { this.actionName = name; - this.remainingExecuteTime = remainingExecuteTime; - this.executeInterval = executeInterval; this.uuid = actionUUID; - this.tickToExecute = executeInterval; - } - - public void setTickToExecute(int tickToExecute) { - this.tickToExecute = tickToExecute; - } - - public int getTickToExecute() { - return tickToExecute; - } - - public void setExecuteInterval(int executeInterval) { - this.executeInterval = executeInterval; - } - - public int getExecuteInterval() { - return executeInterval; - } - - public void setRemainingExecuteTime(int remainingExecuteTime) { - this.remainingExecuteTime = remainingExecuteTime; - } - - public int getRemainingExecuteTime() { - return remainingExecuteTime; + this.initialTickDelay = initialTickDelay; + this.initialTickInterval = initialTickInterval; + this.initialNumber = initialNumber; } public String getActionName() { return actionName; } - public void setActionPlayer(@Nullable Player actionPlayer) { - this.actionPlayer = actionPlayer; + public UUID getUuid() { + return uuid; + } + + public int getInitialTickDelay() { + return initialTickDelay; + } + + public int getInitialTickInterval() { + return initialTickInterval; + } + + public int getInitialNumber() { + return initialNumber; } @Nullable @@ -67,7 +60,31 @@ public class LeavesBotAction { return actionPlayer; } - public UUID getUuid() { - return uuid; + public void setActionPlayer(@Nullable Player actionPlayer) { + this.actionPlayer = actionPlayer; + } + + public boolean isCancel() { + return cancel; + } + + public void setCancel(boolean cancel) { + this.cancel = cancel; + } + + public int getNumberRemaining() { + return numberRemaining; + } + + public void setNumberRemaining(int numberRemaining) { + this.numberRemaining = numberRemaining; + } + + public int getTickToNext() { + return tickToNext; + } + + public void setTickToNext(int tickToNext) { + this.tickToNext = tickToNext; } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionExecuteEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionExecuteEvent.java index 69a99679..d7a41717 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionExecuteEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionExecuteEvent.java @@ -10,18 +10,16 @@ import java.util.UUID; public class BotActionExecuteEvent extends BotActionEvent implements Cancellable { private static final HandlerList handlers = new HandlerList(); - - public enum Result { - PASS, SOFT_CANCEL, HARD_CANCEL; - - } - private Result result = Result.PASS; public BotActionExecuteEvent(@NotNull Bot who, String actionName, UUID actionUUID) { super(who, actionName, actionUUID); } + public static HandlerList getHandlerList() { + return handlers; + } + @Override public boolean isCancelled() { return result != Result.PASS; @@ -45,8 +43,9 @@ public class BotActionExecuteEvent extends BotActionEvent implements Cancellable return handlers; } - public static HandlerList getHandlerList() { - return handlers; + public enum Result { + PASS, SOFT_CANCEL, HARD_CANCEL + } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionScheduleEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionScheduleEvent.java index f1123d55..f92e29ce 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionScheduleEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionScheduleEvent.java @@ -12,15 +12,18 @@ import java.util.UUID; public class BotActionScheduleEvent extends BotActionEvent implements Cancellable { private static final HandlerList handlers = new HandlerList(); - - private boolean cancel = false; private final CommandSender sender; + private boolean cancel = false; public BotActionScheduleEvent(@NotNull Bot who, String actionName, UUID actionUUID, CommandSender sender) { super(who, actionName, actionUUID); this.sender = sender; } + public static HandlerList getHandlerList() { + return handlers; + } + @Override public boolean isCancelled() { return cancel; @@ -41,8 +44,4 @@ public class BotActionScheduleEvent extends BotActionEvent implements Cancellabl public HandlerList getHandlers() { return handlers; } - - public static HandlerList getHandlerList() { - return handlers; - } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionStopEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionStopEvent.java index 56822a94..1a4772ce 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionStopEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotActionStopEvent.java @@ -9,16 +9,11 @@ import org.leavesmc.leaves.entity.Bot; import java.util.UUID; -public class BotActionStopEvent extends BotActionEvent implements Cancellable{ +public class BotActionStopEvent extends BotActionEvent implements Cancellable { private static final HandlerList handlers = new HandlerList(); - private boolean cancel = false; private final CommandSender sender; - - public enum Reason { - DONE, COMMAND, PLUGIN, INTERNAL - } - private final Reason reason; + private boolean cancel = false; public BotActionStopEvent(@NotNull Bot who, String actionName, UUID actionUUID, Reason stopReason, CommandSender sender) { super(who, actionName, actionUUID); @@ -26,6 +21,10 @@ public class BotActionStopEvent extends BotActionEvent implements Cancellable{ this.sender = sender; } + public static HandlerList getHandlerList() { + return handlers; + } + public Reason getReason() { return reason; } @@ -35,10 +34,6 @@ public class BotActionStopEvent extends BotActionEvent implements Cancellable{ return handlers; } - public static HandlerList getHandlerList() { - return handlers; - } - @Override public boolean isCancelled() { return cancel; @@ -53,4 +48,8 @@ public class BotActionStopEvent extends BotActionEvent implements Cancellable{ public CommandSender getSender() { return sender; } + + public enum Reason { + DONE, COMMAND, PLUGIN, INTERNAL + } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotConfigModifyEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotConfigModifyEvent.java index 5afa2df3..4cee1ac5 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotConfigModifyEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotConfigModifyEvent.java @@ -12,8 +12,8 @@ public class BotConfigModifyEvent extends BotEvent implements Cancellable { private final String configName; private final String[] configValue; - private boolean cancel; private final CommandSender sender; + private boolean cancel; public BotConfigModifyEvent(@NotNull Bot who, String configName, String[] configValue, CommandSender sender) { super(who); @@ -22,6 +22,10 @@ public class BotConfigModifyEvent extends BotEvent implements Cancellable { this.sender = sender; } + public static HandlerList getHandlerList() { + return handlers; + } + @NotNull public String getConfigName() { return configName; @@ -46,8 +50,4 @@ public class BotConfigModifyEvent extends BotEvent implements Cancellable { public @NotNull HandlerList getHandlers() { return handlers; } - - public static HandlerList getHandlerList() { - return handlers; - } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotCreateEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotCreateEvent.java index 11e55a99..c7b22574 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotCreateEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotCreateEvent.java @@ -14,21 +14,12 @@ import org.jetbrains.annotations.Nullable; public class BotCreateEvent extends Event implements Cancellable { private static final HandlerList handlers = new HandlerList(); - - public enum CreateReason { - COMMAND, - PLUGIN, - INTERNAL, - UNKNOWN, - } - private final String bot; private final String skin; private final CreateReason reason; private final CommandSender creator; private Location createLocation; private boolean cancel = false; - public BotCreateEvent(@NotNull final String who, @NotNull final String skin, @NotNull final Location createLocation, @NotNull CreateReason reason, @Nullable CommandSender creator) { this.bot = who; this.skin = skin; @@ -37,6 +28,11 @@ public class BotCreateEvent extends Event implements Cancellable { this.creator = creator; } + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + /** * Gets the fakeplayer name * @@ -112,8 +108,10 @@ public class BotCreateEvent extends Event implements Cancellable { return handlers; } - @NotNull - public static HandlerList getHandlerList() { - return handlers; + public enum CreateReason { + COMMAND, + PLUGIN, + INTERNAL, + UNKNOWN, } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotDeathEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotDeathEvent.java index 3366b50c..2204863a 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotDeathEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotDeathEvent.java @@ -22,13 +22,13 @@ public class BotDeathEvent extends BotEvent implements Cancellable { this.sendDeathMessage = sendDeathMessage; } - @Override - public @NotNull HandlerList getHandlers() { + @NotNull + public static HandlerList getHandlerList() { return handlers; } - @NotNull - public static HandlerList getHandlerList() { + @Override + public @NotNull HandlerList getHandlers() { return handlers; } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotInventoryOpenEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotInventoryOpenEvent.java index 8191c0e1..f525ccdc 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotInventoryOpenEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotInventoryOpenEvent.java @@ -19,6 +19,11 @@ public class BotInventoryOpenEvent extends BotEvent implements Cancellable { this.player = player; } + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + @Override public boolean isCancelled() { return cancel; @@ -38,9 +43,4 @@ public class BotInventoryOpenEvent extends BotEvent implements Cancellable { public @NotNull HandlerList getHandlers() { return handlers; } - - @NotNull - public static HandlerList getHandlerList() { - return handlers; - } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotJoinEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotJoinEvent.java index 24e5f4d8..82b29aea 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotJoinEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotJoinEvent.java @@ -26,6 +26,11 @@ public class BotJoinEvent extends BotEvent { this.joinMessage = joinMessage != null ? LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null; } + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + public void joinMessage(@Nullable final Component joinMessage) { this.joinMessage = joinMessage; } @@ -59,9 +64,4 @@ public class BotJoinEvent extends BotEvent { public HandlerList getHandlers() { return handlers; } - - @NotNull - public static HandlerList getHandlerList() { - return handlers; - } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotLoadEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotLoadEvent.java index b5295bdd..2e2b034e 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotLoadEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotLoadEvent.java @@ -23,6 +23,11 @@ public class BotLoadEvent extends Event implements Cancellable { this.botUUID = uuid; } + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + /** * Gets the fakeplayer name * @@ -51,9 +56,4 @@ public class BotLoadEvent extends Event implements Cancellable { public HandlerList getHandlers() { return handlers; } - - @NotNull - public static HandlerList getHandlerList() { - return handlers; - } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotRemoveEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotRemoveEvent.java index 76909d03..9bf59445 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotRemoveEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotRemoveEvent.java @@ -15,20 +15,11 @@ import org.leavesmc.leaves.entity.Bot; public class BotRemoveEvent extends BotEvent implements Cancellable { private static final HandlerList handlers = new HandlerList(); - - public enum RemoveReason { - COMMAND, - PLUGIN, - DEATH, - INTERNAL - } - private final RemoveReason reason; private final CommandSender remover; private Component removeMessage; private boolean save; private boolean cancel = false; - public BotRemoveEvent(@NotNull final Bot who, @NotNull RemoveReason reason, @Nullable CommandSender remover, @Nullable Component removeMessage, boolean save) { super(who); this.reason = reason; @@ -37,6 +28,11 @@ public class BotRemoveEvent extends BotEvent implements Cancellable { this.save = save; } + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + /** * Gets the remove reason of the bot * @@ -99,8 +95,10 @@ public class BotRemoveEvent extends BotEvent implements Cancellable { return handlers; } - @NotNull - public static HandlerList getHandlerList() { - return handlers; + public enum RemoveReason { + COMMAND, + PLUGIN, + DEATH, + INTERNAL } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotSpawnLocationEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotSpawnLocationEvent.java index 46ab3e9b..b3c5afaf 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotSpawnLocationEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/bot/BotSpawnLocationEvent.java @@ -16,6 +16,11 @@ public class BotSpawnLocationEvent extends BotEvent { this.spawnLocation = spawnLocation; } + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + @NotNull public Location getSpawnLocation() { return spawnLocation; @@ -30,9 +35,4 @@ public class BotSpawnLocationEvent extends BotEvent { public HandlerList getHandlers() { return handlers; } - - @NotNull - public static HandlerList getHandlerList() { - return handlers; - } } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/event/player/PlayerOperationLimitEvent.java b/leaves-api/src/main/java/org/leavesmc/leaves/event/player/PlayerOperationLimitEvent.java index 1f5852eb..ef6bef27 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/event/player/PlayerOperationLimitEvent.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/event/player/PlayerOperationLimitEvent.java @@ -21,6 +21,11 @@ public class PlayerOperationLimitEvent extends PlayerEvent { this.operation = operation; } + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + /** * Gets the operated block * @@ -45,11 +50,6 @@ public class PlayerOperationLimitEvent extends PlayerEvent { return handlers; } - @NotNull - public static HandlerList getHandlerList() { - return handlers; - } - public enum Operation { MINE, PLACE } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/plugin/FeatureManager.java b/leaves-api/src/main/java/org/leavesmc/leaves/plugin/FeatureManager.java new file mode 100644 index 00000000..aeb89063 --- /dev/null +++ b/leaves-api/src/main/java/org/leavesmc/leaves/plugin/FeatureManager.java @@ -0,0 +1,10 @@ +// This file is licensed under the MIT license. +package org.leavesmc.leaves.plugin; + +import java.util.Set; + +public interface FeatureManager { + Set getAvailableFeatures(); + + boolean isFeatureAvailable(String feature); +} diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/plugin/Features.java b/leaves-api/src/main/java/org/leavesmc/leaves/plugin/Features.java new file mode 100644 index 00000000..00365c93 --- /dev/null +++ b/leaves-api/src/main/java/org/leavesmc/leaves/plugin/Features.java @@ -0,0 +1,9 @@ +// This file is licensed under the MIT license. +package org.leavesmc.leaves.plugin; + +public class Features { + public static final String MIXIN = "mixin"; + public static final String FAKEPLAYER = "fakeplayer"; + public static final String PHOTOGRAPHER = "photographer"; + public static final String RECORDER = "recorder"; +} diff --git a/leaves-server/build.gradle.kts.patch b/leaves-server/build.gradle.kts.patch index 0e42045c..0bec9579 100644 --- a/leaves-server/build.gradle.kts.patch +++ b/leaves-server/build.gradle.kts.patch @@ -1,26 +1,31 @@ --- a/paper-server/build.gradle.kts +++ b/paper-server/build.gradle.kts -@@ -5,14 +_,15 @@ - plugins { +@@ -9,25 +_,38 @@ `java-library` `maven-publish` + idea - id("io.papermc.paperweight.core") + id("org.leavesmc.leavesweight.core") // Leaves - build change } val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/" -+val leavesMavenPublicUrl = "https://repo.leavesmc.com/snapshots/" ++val leavesMavenPublicUrl = "https://repo.leavesmc.com/snapshots/" // Leaves - build change dependencies { - mache("io.papermc:mache:1.21.4+build.7") + mache("io.papermc:mache:1.21.5+build.2") - paperclip("io.papermc:paperclip:3.0.3") -+ leavesclip("org.leavesmc:leavesclip:2.0.1") // Leaves - build change ++ leavesclip("org.leavesmc:leavesclip:3.0.0") // Leaves - build change testRuntimeOnly("org.junit.platform:junit-platform-launcher") } -@@ -21,6 +_,18 @@ - // macheOldPath = file("F:\\Projects\\PaperTooling\\mache\\versions\\1.21.4\\src\\main\\java") - // gitFilePatches = true + paperweight { +- minecraftVersion = providers.gradleProperty("mcVersion") ++ minecraftVersion = rootProject.providers.gradleProperty("mcVersion") // Leaves - build change + gitFilePatches = false + + //updatingMinecraft { + // oldPaperCommit = "f4f275519f7c1fbe9db173b7144a4fe81440e365" + //} + // Leaves start - build change + val leaves = forks.register("leaves") { @@ -35,17 +40,17 @@ + // Leaves end - build change + spigot { - buildDataRef = "3edaf46ec1eed4115ce1b18d2846cded42577e42" - packageVersion = "v1_21_R3" // also needs to be updated in MappingEnvironment -@@ -43,6 +_,7 @@ + buildDataRef = "702e1a0a5072b2c4082371d5228cb30525687efc" + packageVersion = "v1_21_R4" // also needs to be updated in MappingEnvironment +@@ -50,6 +_,7 @@ libraryRepositories.addAll( "https://repo.maven.apache.org/maven2/", paperMavenPublicUrl, -+ leavesMavenPublicUrl ++ leavesMavenPublicUrl // Leaves - build change ) } -@@ -101,7 +_,21 @@ +@@ -108,7 +_,22 @@ } } @@ -65,10 +70,11 @@ + java { srcDir("../paper-server/src/log4jPlugins/java") } +} +// Leaves end - build change ++ configurations.named(log4jPlugins.compileClasspathConfigurationName) { extendsFrom(configurations.compileClasspath.get()) } -@@ -119,7 +_,13 @@ +@@ -130,7 +_,18 @@ } dependencies { @@ -79,12 +85,28 @@ + implementation("org.lz4:lz4-java:1.8.0") + implementation("net.openhft:zero-allocation-hashing:0.16") + // Leaves end - linear -+ implementation("org.spongepowered:configurate-hocon:4.2.0-SNAPSHOT") // Leaves - leaves plugins ++ // Leaves start - leaves plugin ++ implementation("org.spongepowered:configurate-gson:4.2.0-SNAPSHOT") { ++ exclude(group = "com.google.code.gson", module = "gson") ++ exclude(group = "com.google.guava", module = "guava") ++ } ++ // Leaves end - leaves plugin implementation("ca.spottedleaf:concurrentutil:0.0.3") implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+ implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21 -@@ -177,6 +_,16 @@ - implementation("me.lucko:spark-paper:1.10.119-20241121.092015-1") +@@ -157,9 +_,9 @@ + implementation("org.ow2.asm:asm-commons:9.8") + implementation("org.spongepowered:configurate-yaml:4.2.0-20250225.064233-199") + implementation("org.spongepowered:configurate-core:4.2.0-20250225.064233-204") // Pinned dependency of above pinned yaml snapshot. ++ implementation("commons-lang:commons-lang:2.6") // Leaves + + // Deps that were previously in the API but have now been moved here for backwards compat, eventually to be removed +- runtimeOnly("commons-lang:commons-lang:2.6") + runtimeOnly("org.xerial:sqlite-jdbc:3.49.1.0") + runtimeOnly("com.mysql:mysql-connector-j:9.2.0") + runtimeOnly("com.lmax:disruptor:3.4.4") +@@ -194,6 +_,16 @@ + implementation("me.lucko:spark-paper:1.10.133-20250413.112336-1") } +// Leaves start - hide irrelevant compilation warnings @@ -100,7 +122,7 @@ tasks.jar { manifest { val git = Git(rootProject.layout.projectDirectory.path) -@@ -189,14 +_,14 @@ +@@ -206,14 +_,14 @@ val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim() attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", @@ -120,7 +142,16 @@ "Build-Number" to (build ?: ""), "Build-Time" to buildTime.toString(), "Git-Branch" to gitBranch, -@@ -317,13 +_,23 @@ +@@ -267,7 +_,7 @@ + jvmArgumentProviders.add(provider) + } + +-val generatedDir: java.nio.file.Path = layout.projectDirectory.dir("src/generated/java").asFile.toPath() ++val generatedDir: java.nio.file.Path = rootProject.layout.projectDirectory.dir("paper-server/src/generated/java").asFile.toPath() + idea { + module { + generatedSourceDirs.add(generatedDir.toFile()) +@@ -360,13 +_,26 @@ classpath(tasks.createReobfBundlerJar.flatMap { it.outputZip }) mainClass.set(null as String?) } @@ -134,15 +165,18 @@ - classpath(tasks.createReobfPaperclipJar.flatMap { it.outputZip }) - mainClass.set(null as String?) -} ++ +// Leaves start - build change +tasks.registerRunTask("runLeavesclip") { + description = "Spin up a test server from the Mojang mapped Leavesclip jar" ++ systemProperty("leavesclip.enable.mixin", true) + classpath(tasks.createMojmapLeavesclipJar.flatMap { it.outputZip }) + mainClass.set(null as String?) +} +tasks.registerRunTask("runReobfLeavesclip") { + description = "Spin up a test server from the reobf Leavesclip jar" -+ classpath(tasks.createReobfLeavesclipJar.flatMap { it.outputZip }) ++ systemProperty("leavesclip.enable.mixin", true) ++ classpath(tasks.createMojmapLeavesclipJar.flatMap { it.outputZip }) + mainClass.set(null as String?) +} +// Leaves end - build change diff --git a/leaves-server/minecraft-patches/features/0001-Build-changes.patch b/leaves-server/minecraft-patches/features/0001-Build-changes.patch index 20426224..b63bea7a 100644 --- a/leaves-server/minecraft-patches/features/0001-Build-changes.patch +++ b/leaves-server/minecraft-patches/features/0001-Build-changes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Build changes diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java -index 4d344559a20a0c35c181e297e81788c747363ec9..9d25c263508da5b6a027132e6cc071b675e4af44 100644 +index b9b774a3ca600cee3d0e967063ea2f72c7ab184f..dfc582444cd7273afb78b250d9fa12317591d8aa 100644 --- a/ca/spottedleaf/moonrise/paper/PaperHooks.java +++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java -@@ -28,7 +28,7 @@ import net.minecraft.world.phys.AABB; +@@ -29,7 +29,7 @@ import net.minecraft.world.phys.AABB; import java.util.List; import java.util.function.Predicate; @@ -18,10 +18,10 @@ index 4d344559a20a0c35c181e297e81788c747363ec9..9d25c263508da5b6a027132e6cc071b6 @Override public String getBrand() { diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index ae220a732c78ab076261f20b5a54c71d7fceb407..5dfdf76c8de5eda9a02f9a5fa1c3bada8ec7dcde 100644 +index f1373fd5fdebb9f4600ba7f32a5df6188de3a0e9..4e5b27f2d00a6be6da6db461471395a515dc9b38 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1192,7 +1192,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Sun, 2 Feb 2025 13:08:32 +0800 -Subject: [PATCH] Leaves Protocol Core - - -diff --git a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java -index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..7e19dfe90a63ff26f03b95891dacb7360bba5a3c 100644 ---- a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java -+++ b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java -@@ -40,13 +40,23 @@ public interface CustomPacketPayload { - - @Override - public void encode(B buffer, CustomPacketPayload value) { -+ // Leaves start - protocol core -+ if (value instanceof org.leavesmc.leaves.protocol.core.LeavesCustomPayload payload) { -+ buffer.writeResourceLocation(payload.id()); -+ payload.write(buffer); -+ return; -+ } -+ // Leaves end - protocol core - this.writeCap(buffer, value.type(), value); - } - - @Override - public CustomPacketPayload decode(B buffer) { - ResourceLocation resourceLocation = buffer.readResourceLocation(); -- return (CustomPacketPayload)this.findCodec(resourceLocation).decode(buffer); -+ // Leaves start - protocol core -+ var payload = org.leavesmc.leaves.protocol.core.LeavesProtocolManager.decode(resourceLocation, buffer); -+ return java.util.Objects.requireNonNullElseGet(payload, () -> this.findCodec(resourceLocation).decode(buffer)); -+ // Leaves end - protocol core - } - }; - } -diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 5dfdf76c8de5eda9a02f9a5fa1c3bada8ec7dcde..bde8ddadd3930100d1e31e630f809e77d6a70dac 100644 ---- a/net/minecraft/server/MinecraftServer.java -+++ b/net/minecraft/server/MinecraftServer.java -@@ -1744,6 +1744,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop leavesPayload) { -+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePayload(player, leavesPayload); -+ } -+ // Leaves end - protocol -+ - // Paper start - if (packet.payload() instanceof net.minecraft.network.protocol.common.custom.BrandPayload(String brand)) { - this.player.clientBrandName = brand; -@@ -189,6 +195,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack - final String channel = new String(data, from, length, java.nio.charset.StandardCharsets.US_ASCII); - if (register) { - this.getCraftPlayer().addChannel(channel); -+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleMinecraftRegister(channel, player); // Leaves - protocol - } else { - this.getCraftPlayer().removeChannel(channel); - } -diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index c9dbe659374e3ce140316116e05110567e44b810..f88b3b3d0f8e56f17de491fa9d312dadad364a42 100644 ---- a/net/minecraft/server/players/PlayerList.java -+++ b/net/minecraft/server/players/PlayerList.java -@@ -330,6 +330,8 @@ public abstract class PlayerList { - return; - } - -+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol -+ - final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); - - if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure -@@ -500,6 +502,7 @@ public abstract class PlayerList { - return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName()))); - } - public net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) { -+ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerLeave(player); // Leaves - protocol - // Paper end - Fix kick event leave message not being sent - ServerLevel serverLevel = player.serverLevel(); - player.awardStat(Stats.LEAVE_GAME); diff --git a/leaves-server/minecraft-patches/features/0003-Leaves-entity-ex-data.patch b/leaves-server/minecraft-patches/features/0003-Leaves-entity-ex-data.patch new file mode 100644 index 00000000..759d8af8 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0003-Leaves-entity-ex-data.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> +Date: Tue, 22 Apr 2025 23:32:41 +0800 +Subject: [PATCH] Leaves entity ex data + + +diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java +index 81a18b8e605bd4c28b48a32c80be231609182970..f8d45c1076852a0553c3dd7c5512f76a6891e2cb 100644 +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -351,6 +351,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + public boolean isTemporarilyActive; + public long activatedImmunityTick = Integer.MIN_VALUE; + ++ private CompoundTag leavesData = new CompoundTag(); // Leaves - Leaves ex data ++ + public void inactiveTick() { + } + // Paper end - EAR 2 +@@ -2516,6 +2518,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + compound.putBoolean("Paper.FreezeLock", true); + } + // Paper end ++ compound.put("Leaves.Data", leavesData); // Leaves - leaves ex data + return compound; + } catch (Throwable var8) { + CrashReport crashReport = CrashReport.forThrowable(var8, "Saving entity NBT"); +@@ -2646,6 +2649,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + freezeLocked = compound.getBooleanOr("Paper.FreezeLock", false); + } + // Paper end ++ // Leaves start - leaves ex data ++ if (compound.contains("Leaves.Data")) { ++ leavesData = compound.getCompoundOrEmpty("Leaves.Data"); ++ } ++ // Leaves end - leaves ex data + } catch (Throwable var8) { + CrashReport crashReport = CrashReport.forThrowable(var8, "Loading entity NBT"); + CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded"); +@@ -5114,4 +5122,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + return ((ServerLevel) this.level()).isPositionEntityTicking(this.blockPosition()); + } + // Paper end - Expose entity id counter ++ // Leaves start - leaves ex data ++ public CompoundTag getLeavesData() { ++ return leavesData; ++ } ++ // Leaves end - leaves ex data + } diff --git a/leaves-server/minecraft-patches/features/0004-Leaves-Protocol-Core.patch b/leaves-server/minecraft-patches/features/0004-Leaves-Protocol-Core.patch new file mode 100644 index 00000000..bfbfaf4e --- /dev/null +++ b/leaves-server/minecraft-patches/features/0004-Leaves-Protocol-Core.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: violetc <58360096+s-yh-china@users.noreply.github.com> +Date: Sun, 2 Feb 2025 13:08:32 +0800 +Subject: [PATCH] Leaves Protocol Core + + +diff --git a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java +index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f934939d563 100644 +--- a/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java ++++ b/net/minecraft/network/protocol/common/custom/CustomPacketPayload.java +@@ -40,13 +40,22 @@ public interface CustomPacketPayload { + + @Override + public void encode(B buffer, CustomPacketPayload value) { ++ // Leaves start - protocol core ++ if (value instanceof org.leavesmc.leaves.protocol.core.LeavesCustomPayload payload) { ++ org.leavesmc.leaves.protocol.core.LeavesProtocolManager.encode(buffer, payload); ++ return; ++ } ++ // Leaves end - protocol core + this.writeCap(buffer, value.type(), value); + } + + @Override + public CustomPacketPayload decode(B buffer) { + ResourceLocation resourceLocation = buffer.readResourceLocation(); +- return (CustomPacketPayload)this.findCodec(resourceLocation).decode(buffer); ++ // Leaves start - protocol core ++ var payload = org.leavesmc.leaves.protocol.core.LeavesProtocolManager.decode(resourceLocation, buffer); ++ return java.util.Objects.requireNonNullElseGet(payload, () -> this.findCodec(resourceLocation).decode(buffer)); ++ // Leaves end - protocol core + } + }; + } +diff --git a/net/minecraft/network/protocol/common/custom/DiscardedPayload.java b/net/minecraft/network/protocol/common/custom/DiscardedPayload.java +index 62b9d9486c15a1ec6527f786df4e9fc483390bcb..5384bbc6bb3dbe5481f9d8cb10282551a0f78ec1 100644 +--- a/net/minecraft/network/protocol/common/custom/DiscardedPayload.java ++++ b/net/minecraft/network/protocol/common/custom/DiscardedPayload.java +@@ -4,12 +4,12 @@ import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.codec.StreamCodec; + import net.minecraft.resources.ResourceLocation; + +-public record DiscardedPayload(ResourceLocation id, byte[] data) implements CustomPacketPayload { // Paper - store data ++public record DiscardedPayload(ResourceLocation id, byte @org.jetbrains.annotations.Nullable [] data) implements CustomPacketPayload { // Paper - store data // Leaves - nullable + public static StreamCodec codec(ResourceLocation id, int maxSize) { + return CustomPacketPayload.codec((value, output) -> { + // Paper start + // Always write data +- output.writeBytes(value.data); ++ if (value.data != null) output.writeBytes(value.data); // Leaves - nullable + }, buffer -> { + int i = buffer.readableBytes(); + if (i >= 0 && i <= maxSize) { +diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java +index 4e5b27f2d00a6be6da6db461471395a515dc9b38..d48581353661799e5e031a512227d5e651fa2996 100644 +--- a/net/minecraft/server/MinecraftServer.java ++++ b/net/minecraft/server/MinecraftServer.java +@@ -1742,6 +1742,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation + private org.leavesmc.leaves.bot.BotList botList; // Leaves - fakeplayer + public static S spin(Function threadFunction) { - ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system AtomicReference atomicReference = new AtomicReference<>(); -@@ -740,6 +742,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop atomicReference.get().runServer(), "Server thread"); +@@ -738,6 +740,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop realPlayers; // Leaves - skip - public LevelChunk getChunkIfLoaded(int x, int z) { - return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately -@@ -681,6 +682,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + @Override + public @Nullable LevelChunk getChunkIfLoaded(int x, int z) { +@@ -671,6 +672,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler); // Paper end - rewrite chunk system this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit @@ -150,7 +150,7 @@ index 60425aade859c03ec21669b33d6b5096e444f6e9..9fba04e8a8e95546f7d7cc1210b4b324 } // Paper start -@@ -2206,6 +2208,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2204,6 +2206,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe return this.players; } @@ -161,9 +161,9 @@ index 60425aade859c03ec21669b33d6b5096e444f6e9..9fba04e8a8e95546f7d7cc1210b4b324 + // Leaves end - fakeplayer skip + @Override - public void onBlockStateChange(BlockPos pos, BlockState blockState, BlockState newState) { - Optional> optional = PoiTypes.forState(blockState); -@@ -2621,6 +2629,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + public void updatePOIOnBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) { + Optional> optional = PoiTypes.forState(oldState); +@@ -2616,6 +2624,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true if (entity instanceof ServerPlayer serverPlayer) { ServerLevel.this.players.add(serverPlayer); @@ -175,7 +175,7 @@ index 60425aade859c03ec21669b33d6b5096e444f6e9..9fba04e8a8e95546f7d7cc1210b4b324 ServerLevel.this.updateSleepingPlayerList(); } -@@ -2687,6 +2700,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2682,6 +2695,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe ServerLevel.this.getChunkSource().removeEntity(entity); if (entity instanceof ServerPlayer serverPlayer) { ServerLevel.this.players.remove(serverPlayer); @@ -188,11 +188,11 @@ index 60425aade859c03ec21669b33d6b5096e444f6e9..9fba04e8a8e95546f7d7cc1210b4b324 } diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 3de65c4025be91d938a350c884975cb6edc234d3..339cec1f040d47bb37834c6ebe0633b7c991e0cd 100644 +index 443bfb06951f0ffe6af8724b53e150cd0907e68d..01687ea3acf449c49cbc615887a7dbdd3a693613 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -197,7 +197,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - ); +@@ -208,7 +208,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + private static final boolean DEFAULT_SPAWN_EXTRA_PARTICLES_ON_FALL = false; public ServerGamePacketListenerImpl connection; public final MinecraftServer server; - public final ServerPlayerGameMode gameMode; @@ -200,7 +200,7 @@ index 3de65c4025be91d938a350c884975cb6edc234d3..339cec1f040d47bb37834c6ebe0633b7 private final PlayerAdvancements advancements; private final ServerStatsCounter stats; private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE; -@@ -1469,6 +1469,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1413,6 +1413,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.lastSentHealth = -1.0F; this.lastSentFood = -1; @@ -213,10 +213,10 @@ index 3de65c4025be91d938a350c884975cb6edc234d3..339cec1f040d47bb37834c6ebe0633b7 // CraftBukkit start org.bukkit.event.player.PlayerChangedWorldEvent changeEvent = new org.bukkit.event.player.PlayerChangedWorldEvent(this.getBukkitEntity(), serverLevel.getWorld()); diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index f88b3b3d0f8e56f17de491fa9d312dadad364a42..bd7ae7aba1802f202ea09cb1064832092da30c4b 100644 +index d24c61c34427aa526c16ffc8aa43ec9ec1232589..012574f56d9d7e6340c8b7bf7bee43e36d99df65 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -332,6 +332,19 @@ public abstract class PlayerList { +@@ -336,6 +336,19 @@ public abstract class PlayerList { org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol @@ -236,7 +236,7 @@ index f88b3b3d0f8e56f17de491fa9d312dadad364a42..bd7ae7aba1802f202ea09cb106483209 final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure -@@ -852,6 +865,12 @@ public abstract class PlayerList { +@@ -867,6 +880,12 @@ public abstract class PlayerList { } // Paper end - Add PlayerPostRespawnEvent @@ -249,7 +249,7 @@ index f88b3b3d0f8e56f17de491fa9d312dadad364a42..bd7ae7aba1802f202ea09cb106483209 // CraftBukkit end return serverPlayer; -@@ -957,11 +976,16 @@ public abstract class PlayerList { +@@ -971,11 +990,16 @@ public abstract class PlayerList { } public String[] getPlayerNamesArray() { @@ -267,7 +267,7 @@ index f88b3b3d0f8e56f17de491fa9d312dadad364a42..bd7ae7aba1802f202ea09cb106483209 return strings; } -@@ -1045,7 +1069,14 @@ public abstract class PlayerList { +@@ -1061,7 +1085,14 @@ public abstract class PlayerList { @Nullable public ServerPlayer getPlayerByName(String username) { @@ -283,7 +283,7 @@ index f88b3b3d0f8e56f17de491fa9d312dadad364a42..bd7ae7aba1802f202ea09cb106483209 } public void broadcast(@Nullable Player except, double x, double y, double z, double radius, ResourceKey dimension, Packet packet) { -@@ -1361,7 +1392,13 @@ public abstract class PlayerList { +@@ -1377,7 +1408,13 @@ public abstract class PlayerList { @Nullable public ServerPlayer getPlayer(UUID playerUUID) { @@ -299,10 +299,10 @@ index f88b3b3d0f8e56f17de491fa9d312dadad364a42..bd7ae7aba1802f202ea09cb106483209 public boolean canBypassPlayerLimit(GameProfile profile) { diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index e6bbcfed42233a31b72533c1f45b88b401b273a3..c599b8196d0eb72290081a533e5651448269d8ca 100644 +index f8d45c1076852a0553c3dd7c5512f76a6891e2cb..1f50aca05ff1adf8f2e16cab2fac757a7094e1b8 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -1432,7 +1432,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1454,7 +1454,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } // Paper start - optimise collisions @@ -312,10 +312,10 @@ index e6bbcfed42233a31b72533c1f45b88b401b273a3..c599b8196d0eb72290081a533e565144 final boolean yZero = movement.y == 0.0; final boolean zZero = movement.z == 0.0; diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index a0813aa9ebf5b32375b1bc9f294d8fc34cc867fe..4ff40881c2d58881497794d2abb6efbfcd53d524 100644 +index 2046c4d3ad5ea3254ad6bc83e6437e5c237c92b6..2fe76bc1c26423ed5e39453ac1b27a2cc66b1f2e 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java -@@ -186,7 +186,7 @@ public abstract class Player extends LivingEntity { +@@ -196,7 +196,7 @@ public abstract class Player extends LivingEntity { private int lastLevelUpTime; public GameProfile gameProfile; private boolean reducedDebugInfo; @@ -324,7 +324,7 @@ index a0813aa9ebf5b32375b1bc9f294d8fc34cc867fe..4ff40881c2d58881497794d2abb6efbf private final ItemCooldowns cooldowns = this.createItemCooldowns(); private Optional lastDeathLocation = Optional.empty(); @Nullable -@@ -347,6 +347,12 @@ public abstract class Player extends LivingEntity { +@@ -362,6 +362,12 @@ public abstract class Player extends LivingEntity { } } @@ -337,7 +337,7 @@ index a0813aa9ebf5b32375b1bc9f294d8fc34cc867fe..4ff40881c2d58881497794d2abb6efbf @Override protected float getMaxHeadRotationRelativeToBody() { return this.isBlocking() ? 15.0F : super.getMaxHeadRotationRelativeToBody(); -@@ -658,7 +664,7 @@ public abstract class Player extends LivingEntity { +@@ -664,7 +670,7 @@ public abstract class Player extends LivingEntity { } } @@ -346,7 +346,7 @@ index a0813aa9ebf5b32375b1bc9f294d8fc34cc867fe..4ff40881c2d58881497794d2abb6efbf entity.playerTouch(this); } -@@ -1347,7 +1353,7 @@ public abstract class Player extends LivingEntity { +@@ -1287,7 +1293,7 @@ public abstract class Player extends LivingEntity { this.sweepAttack(); } @@ -356,7 +356,7 @@ index a0813aa9ebf5b32375b1bc9f294d8fc34cc867fe..4ff40881c2d58881497794d2abb6efbf boolean cancelled = false; org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity(); diff --git a/net/minecraft/world/entity/projectile/FishingHook.java b/net/minecraft/world/entity/projectile/FishingHook.java -index 1e012c7ef699a64ff3f1b00f897bb893ab25ecbd..f2bf0cdbd29438ca51b74ae2fcdf49dba0d52804 100644 +index ca5cd9354d53c6c05bd7ba50c6e1dbd1ed548f67..f82f37d498f99ce38f72a63d051721c6dab9f2ca 100644 --- a/net/minecraft/world/entity/projectile/FishingHook.java +++ b/net/minecraft/world/entity/projectile/FishingHook.java @@ -55,7 +55,7 @@ public class FishingHook extends Projectile { @@ -369,10 +369,10 @@ index 1e012c7ef699a64ff3f1b00f897bb893ab25ecbd..f2bf0cdbd29438ca51b74ae2fcdf49db public int timeUntilHooked; public float fishAngle; diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index acca8c51d2030c675c157b10d0bbc6af631afe61..b4721c4e81cc2ae989765d86bd51ebf0be41758c 100644 +index 813417a09b4acc7d57e80a53d970767e230d75b1..2a4763c951ddc78c9d8a39e661e59bbffc5cf109 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -375,6 +375,7 @@ public abstract class AbstractContainerMenu { +@@ -376,6 +376,7 @@ public abstract class AbstractContainerMenu { private void doClick(int slotId, int button, ClickType clickType, Player player) { Inventory inventory = player.getInventory(); @@ -380,7 +380,7 @@ index acca8c51d2030c675c157b10d0bbc6af631afe61..b4721c4e81cc2ae989765d86bd51ebf0 if (clickType == ClickType.QUICK_CRAFT) { int i = this.quickcraftStatus; this.quickcraftStatus = getQuickcraftHeader(button); -@@ -651,6 +652,22 @@ public abstract class AbstractContainerMenu { +@@ -652,6 +653,22 @@ public abstract class AbstractContainerMenu { } } @@ -394,7 +394,7 @@ index acca8c51d2030c675c157b10d0bbc6af631afe61..b4721c4e81cc2ae989765d86bd51ebf0 + ItemStack itemStack = slot.getItem(); + net.minecraft.world.item.component.CustomData customData = itemStack.get(net.minecraft.core.component.DataComponents.CUSTOM_DATA); + if (customData != null && customData.contains("Leaves.Gui.Placeholder")) { -+ return !customData.copyTag().getBoolean("Leaves.Gui.Placeholder"); ++ return !customData.copyTag().getBoolean("Leaves.Gui.Placeholder").orElse(false); + } + return true; + } @@ -404,10 +404,10 @@ index acca8c51d2030c675c157b10d0bbc6af631afe61..b4721c4e81cc2ae989765d86bd51ebf0 FeatureFlagSet featureFlagSet = player.level().enabledFeatures(); return carriedItem.isItemEnabled(featureFlagSet) && carriedItem.overrideStackedOnOther(slot, action, player) diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index ee2f8e8deb35059824b5730a1442f383dc79f01c..190377ccd52458c6b490fad25983fe992b0aa0da 100644 +index 1669b76800756000a2f620610b3c8c8b6c48dd4a..8449545bd5278f5558567dd6b7c1522f63045f22 100644 --- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -@@ -132,7 +132,7 @@ public class PistonMovingBlockEntity extends BlockEntity { +@@ -136,7 +136,7 @@ public class PistonMovingBlockEntity extends BlockEntity { break; } @@ -417,23 +417,21 @@ index ee2f8e8deb35059824b5730a1442f383dc79f01c..190377ccd52458c6b490fad25983fe99 double d1 = deltaMovement.x; double d2 = deltaMovement.y; diff --git a/net/minecraft/world/level/levelgen/PhantomSpawner.java b/net/minecraft/world/level/levelgen/PhantomSpawner.java -index 11d25e64349b27bf54dc1620e4cce444c79f581c..82d9d53ef0aa57342173af29d14d00e4039fb583 100644 +index d2e674b046bcf82a239b4706c3b89197ec6749c8..8e2c18fdb76ae6ea7402e6862a64c96db03f191a 100644 --- a/net/minecraft/world/level/levelgen/PhantomSpawner.java +++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java -@@ -57,6 +57,13 @@ public class PhantomSpawner implements CustomSpawner { - ServerStatsCounter stats = serverPlayer.getStats(); - int i1 = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE); - int i2 = 24000; -+ -+ // Leaves start - fakeplayer spawn -+ if (serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot bot && bot.getConfigValue(org.leavesmc.leaves.bot.agent.Configs.SPAWN_PHANTOM)) { -+ i1 = Math.max(bot.notSleepTicks, 1); -+ } -+ // Leaves end - fakeplayer spawn -+ - if (randomSource.nextInt(i1) >= level.paperConfig().entities.behavior.playerInsomniaStartTicks) { // Paper - Ability to control player's insomnia and phantoms - BlockPos blockPos1 = blockPos.above(20 + randomSource.nextInt(15)) - .east(-10 + randomSource.nextInt(21)) +@@ -48,6 +48,11 @@ public class PhantomSpawner implements CustomSpawner { + ServerStatsCounter stats = serverPlayer.getStats(); + int i = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE); + int i1 = 24000; ++ // Leaves start - fakeplayer spawn ++ if (serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot bot && bot.getConfigValue(org.leavesmc.leaves.bot.agent.Configs.SPAWN_PHANTOM)) { ++ i1 = Math.max(bot.notSleepTicks, 1); ++ } ++ // Leaves end - fakeplayer spawn + if (randomSource.nextInt(i) >= 72000) { + BlockPos blockPos1 = blockPos.above(20 + randomSource.nextInt(15)) + .east(-10 + randomSource.nextInt(21)) diff --git a/net/minecraft/world/level/storage/LevelResource.java b/net/minecraft/world/level/storage/LevelResource.java index bef794c3f58c41d910aa0bcc63fbdeea7225fddf..a601da588e6973cc5b87d3e3eeba49b53f6d9a6d 100644 --- a/net/minecraft/world/level/storage/LevelResource.java @@ -448,11 +446,11 @@ index bef794c3f58c41d910aa0bcc63fbdeea7225fddf..a601da588e6973cc5b87d3e3eeba49b5 } diff --git a/net/minecraft/world/level/storage/PlayerDataStorage.java b/net/minecraft/world/level/storage/PlayerDataStorage.java -index c44110b123ba5912af18faf0065e9ded780da9b7..e9da7206f9508bb2597f1b6ba8e52fa81e993a10 100644 +index ab9282c04c1996b037567d07f95e2b150bcfcd38..91f2e0abd1e6d5ad1613b8f750a900bfc39b2f9e 100644 --- a/net/minecraft/world/level/storage/PlayerDataStorage.java +++ b/net/minecraft/world/level/storage/PlayerDataStorage.java -@@ -20,7 +20,7 @@ import net.minecraft.world.entity.player.Player; - import org.bukkit.craftbukkit.entity.CraftPlayer; +@@ -18,7 +18,7 @@ import net.minecraft.util.datafix.DataFixTypes; + import net.minecraft.world.entity.player.Player; import org.slf4j.Logger; -public class PlayerDataStorage { diff --git a/leaves-server/minecraft-patches/features/0007-Make-shears-in-dispenser-can-unlimited-use.patch b/leaves-server/minecraft-patches/features/0008-Make-shears-in-dispenser-can-unlimited-use.patch similarity index 87% rename from leaves-server/minecraft-patches/features/0007-Make-shears-in-dispenser-can-unlimited-use.patch rename to leaves-server/minecraft-patches/features/0008-Make-shears-in-dispenser-can-unlimited-use.patch index 8427b759..d6405a52 100644 --- a/leaves-server/minecraft-patches/features/0007-Make-shears-in-dispenser-can-unlimited-use.patch +++ b/leaves-server/minecraft-patches/features/0008-Make-shears-in-dispenser-can-unlimited-use.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make shears in dispenser can unlimited use diff --git a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -index 626e9feb6a6e7a2cbc7c63e30ba4fb6b923e85c7..e8622aed7c59c15ecf73901e610688778dee56fc 100644 +index c1bd6d91cf9828ccc7275efe0f5c959c0f457c13..34eef95855032655a97f246cc56eb3006eebae19 100644 --- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -@@ -46,7 +46,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { +@@ -44,7 +44,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { if (!serverLevel.isClientSide()) { BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearLivingEntity(serverLevel, blockPos, item, bukkitBlock, craftItem)); // CraftBukkit diff --git a/leaves-server/minecraft-patches/features/0008-Redstone-Shears-Wrench.patch b/leaves-server/minecraft-patches/features/0009-Redstone-Shears-Wrench.patch similarity index 95% rename from leaves-server/minecraft-patches/features/0008-Redstone-Shears-Wrench.patch rename to leaves-server/minecraft-patches/features/0009-Redstone-Shears-Wrench.patch index 14887474..0a3aaf74 100644 --- a/leaves-server/minecraft-patches/features/0008-Redstone-Shears-Wrench.patch +++ b/leaves-server/minecraft-patches/features/0009-Redstone-Shears-Wrench.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Redstone Shears Wrench diff --git a/net/minecraft/world/item/ShearsItem.java b/net/minecraft/world/item/ShearsItem.java -index 9140b41f2ffef897b74792c916e8320a9a7afb7c..0f4f970071a289209eb8131d289e23426d53e818 100644 +index 8cf3e51e12f9cf98836657e722edb23943f9e866..813a6d2bfe99ad8ddf81d7dfca51a7544b5fef0d 100644 --- a/net/minecraft/world/item/ShearsItem.java +++ b/net/minecraft/world/item/ShearsItem.java -@@ -23,6 +23,22 @@ import net.minecraft.world.level.block.GrowingPlantHeadBlock; +@@ -24,6 +24,22 @@ import net.minecraft.world.level.block.GrowingPlantHeadBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; @@ -31,7 +31,7 @@ index 9140b41f2ffef897b74792c916e8320a9a7afb7c..0f4f970071a289209eb8131d289e2342 public class ShearsItem extends Item { public ShearsItem(Item.Properties properties) { super(properties); -@@ -81,7 +97,68 @@ public class ShearsItem extends Item { +@@ -80,7 +96,68 @@ public class ShearsItem extends Item { return InteractionResult.SUCCESS; } else { diff --git a/leaves-server/minecraft-patches/features/0009-Add-isShrink-to-EntityResurrectEvent.patch b/leaves-server/minecraft-patches/features/0010-Add-isShrink-to-EntityResurrectEvent.patch similarity index 91% rename from leaves-server/minecraft-patches/features/0009-Add-isShrink-to-EntityResurrectEvent.patch rename to leaves-server/minecraft-patches/features/0010-Add-isShrink-to-EntityResurrectEvent.patch index 5fb38ca0..50e14445 100644 --- a/leaves-server/minecraft-patches/features/0009-Add-isShrink-to-EntityResurrectEvent.patch +++ b/leaves-server/minecraft-patches/features/0010-Add-isShrink-to-EntityResurrectEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add isShrink to EntityResurrectEvent diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index d87e31572aa85bffc62dc017520dd408560f79b4..e34f50a5f488ab676622b6c922577009c3a7f4c8 100644 +index 3e8f4f3c3d43c6875108295187023c48eece2788..5fc4d97ef421a37158b01864b035385bb7bf5f5f 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -1595,14 +1595,14 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1701,14 +1701,14 @@ public abstract class LivingEntity extends Entity implements Attackable { } final org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null; diff --git a/leaves-server/minecraft-patches/features/0010-Budding-Amethyst-can-push-by-piston.patch b/leaves-server/minecraft-patches/features/0011-Budding-Amethyst-can-push-by-piston.patch similarity index 85% rename from leaves-server/minecraft-patches/features/0010-Budding-Amethyst-can-push-by-piston.patch rename to leaves-server/minecraft-patches/features/0011-Budding-Amethyst-can-push-by-piston.patch index ac65330b..f714beb9 100644 --- a/leaves-server/minecraft-patches/features/0010-Budding-Amethyst-can-push-by-piston.patch +++ b/leaves-server/minecraft-patches/features/0011-Budding-Amethyst-can-push-by-piston.patch @@ -5,12 +5,12 @@ Subject: [PATCH] Budding Amethyst can push by piston diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java -index 976de81d65b6494cdad20f4ec5125fceec86f951..37f561ae2eca0d118c63f519fabdcfe9cb710826 100644 +index ae3e6e31171b1bcfba1ae51a0941b52dda270acd..f289e37f77e1c9d3b0f6c29da1b99f0d5f156e37 100644 --- a/net/minecraft/world/level/block/Block.java +++ b/net/minecraft/world/level/block/Block.java -@@ -557,6 +557,13 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -610,6 +610,13 @@ public class Block extends BlockBehaviour implements ItemLike { } - // Spigot end + // CraftBukkit end + // Leaves start - reset push reaction + @org.jetbrains.annotations.Nullable @@ -23,7 +23,7 @@ index 976de81d65b6494cdad20f4ec5125fceec86f951..37f561ae2eca0d118c63f519fabdcfe9 @Override public boolean equals(Object other) { diff --git a/net/minecraft/world/level/block/BuddingAmethystBlock.java b/net/minecraft/world/level/block/BuddingAmethystBlock.java -index f6850d3ab54a6eb4ff718d861f39aac2facd3a88..5f51b4689b0ea92eb7e4e5e42e9eb5538930d60d 100644 +index 9fc8e9e2b168954c8377bd1a8cf57f49fa137213..18b3ab3bfa4effed9ff22e5156349d86c7881849 100644 --- a/net/minecraft/world/level/block/BuddingAmethystBlock.java +++ b/net/minecraft/world/level/block/BuddingAmethystBlock.java @@ -58,4 +58,12 @@ public class BuddingAmethystBlock extends AmethystBlock { @@ -40,10 +40,10 @@ index f6850d3ab54a6eb4ff718d861f39aac2facd3a88..5f51b4689b0ea92eb7e4e5e42e9eb553 + // Leaves end - budding amethyst can push by piston } diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java -index 5473b4006f7e0266ea11a7b05cef78a113c30d97..a37a5528b36ebade8b0e3fe570c6d4819ab1cfbf 100644 +index 834e27ef2f7b342b074ff9e1e390e02f3ca1c399..bbb1abfbfe7afd7b631cf269c1e338697cd016d2 100644 --- a/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -766,7 +766,7 @@ public abstract class BlockBehaviour implements FeatureElement { +@@ -763,7 +763,7 @@ public abstract class BlockBehaviour implements FeatureElement { } public PushReaction getPistonPushReaction() { diff --git a/leaves-server/minecraft-patches/features/0011-Spectator-dont-get-Advancement.patch b/leaves-server/minecraft-patches/features/0012-Spectator-dont-get-Advancement.patch similarity index 91% rename from leaves-server/minecraft-patches/features/0011-Spectator-dont-get-Advancement.patch rename to leaves-server/minecraft-patches/features/0012-Spectator-dont-get-Advancement.patch index 2cec735d..364f917c 100644 --- a/leaves-server/minecraft-patches/features/0011-Spectator-dont-get-Advancement.patch +++ b/leaves-server/minecraft-patches/features/0012-Spectator-dont-get-Advancement.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Spectator dont get Advancement diff --git a/net/minecraft/server/PlayerAdvancements.java b/net/minecraft/server/PlayerAdvancements.java -index 459e59c370a729dfeed3872f3a5984dd3da96abe..4e9ce0c8b459ef41a6945182401c47c61b16b1f7 100644 +index f56a3fb47aa34c39cbd0e0e4e47d924da1488d7a..82fb9c61ce97c2e88a3252068bb28eb40bda0273 100644 --- a/net/minecraft/server/PlayerAdvancements.java +++ b/net/minecraft/server/PlayerAdvancements.java @@ -168,6 +168,11 @@ public class PlayerAdvancements { diff --git a/leaves-server/minecraft-patches/features/0012-Stick-can-change-ArmorStand-arm-status.patch b/leaves-server/minecraft-patches/features/0013-Stick-can-change-ArmorStand-arm-status.patch similarity index 83% rename from leaves-server/minecraft-patches/features/0012-Stick-can-change-ArmorStand-arm-status.patch rename to leaves-server/minecraft-patches/features/0013-Stick-can-change-ArmorStand-arm-status.patch index 6c98dc39..7f218e64 100644 --- a/leaves-server/minecraft-patches/features/0012-Stick-can-change-ArmorStand-arm-status.patch +++ b/leaves-server/minecraft-patches/features/0013-Stick-can-change-ArmorStand-arm-status.patch @@ -5,16 +5,17 @@ Subject: [PATCH] Stick can change ArmorStand arm status diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java -index a3cc0001a949597e345d7919c3f6109fa4a949ad..dfae614a67476d649be2a8c2cd8258abe12842e3 100644 +index 6f601a0a300bbf01f77d835576d15e25c8ba10b8..9ef422c34a70367f4dcee50b51a17143d14f131c 100644 --- a/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -341,6 +341,12 @@ public class ArmorStand extends LivingEntity { +@@ -270,6 +270,13 @@ public class ArmorStand extends LivingEntity { return InteractionResult.SUCCESS_SERVER; } } else { + // Leaves start - stick can change ArmorStand arm status + if (org.leavesmc.leaves.LeavesConfig.modify.stickChangeArmorStandArmStatus && itemInHand.is(Items.STICK) && player.isShiftKeyDown()) { + setShowArms(!showArms()); ++ return InteractionResult.FAIL; + } + // Leaves end - stick can change ArmorStand arm status + diff --git a/leaves-server/minecraft-patches/features/0013-Configurable-MC-59471.patch b/leaves-server/minecraft-patches/features/0014-Configurable-MC-59471.patch similarity index 61% rename from leaves-server/minecraft-patches/features/0013-Configurable-MC-59471.patch rename to leaves-server/minecraft-patches/features/0014-Configurable-MC-59471.patch index 45909399..716f3a4f 100644 --- a/leaves-server/minecraft-patches/features/0013-Configurable-MC-59471.patch +++ b/leaves-server/minecraft-patches/features/0014-Configurable-MC-59471.patch @@ -5,32 +5,24 @@ Subject: [PATCH] Configurable MC-59471 diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java -index 9aace993c6c18f1a50610e4766225485984b8167..dee8bd2a22be8639f8faec428a5ca3a1ecc1d356 100644 +index 8a3a8b0fdf9545a41501dc992c6982d9c8ce7b66..a92462c76a648e6c175b8c2ef3e925aba81ba774 100644 --- a/net/minecraft/world/level/block/TripWireHookBlock.java +++ b/net/minecraft/world/level/block/TripWireHookBlock.java -@@ -201,7 +201,6 @@ public class TripWireHookBlock extends Block { - if (!cancelledEmitterHook) { // Paper - Call BlockRedstoneEvent - emitState(level, pos, flag2, flag3, flag, flag1); - if (!attaching) { -- if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.skipTripwireHookPlacementValidation || level.getBlockState(pos).is(Blocks.TRIPWIRE_HOOK)) // Paper - Validate tripwire hook placement before update - level.setBlock(pos, blockState1.setValue(FACING, direction), 3); - if (shouldNotifyNeighbours) { - notifyNeighbors(block, level, pos, direction); -@@ -214,10 +213,17 @@ public class TripWireHookBlock extends Block { +@@ -200,10 +200,17 @@ public class TripWireHookBlock extends Block { BlockPos blockPos1 = pos.relative(direction, i2); BlockState blockState2 = blockStates[i2]; if (blockState2 != null) { - BlockState blockState3 = level.getBlockState(blockPos1); - if (blockState3.is(Blocks.TRIPWIRE) || blockState3.is(Blocks.TRIPWIRE_HOOK)) { -- if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates || !blockState3.is(Blocks.TRIPWIRE)) level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, Boolean.valueOf(flag2)), 3); // Paper - prevent tripwire from updating +- if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates || !blockState3.is(Blocks.TRIPWIRE)) level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, flag2), 3); // Paper - prevent tripwire from updating + // Leaves start - MC-59471 -+ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.stringTripwireHookDuplicate) { ++ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.tripwire.stringTripwireHookDuplicate) { + level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, flag2), 3); + level.getBlockState(blockPos1); + } else { + BlockState blockState3 = level.getBlockState(blockPos1); + if (blockState3.is(Blocks.TRIPWIRE) || blockState3.is(Blocks.TRIPWIRE_HOOK)) { -+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates || !blockState3.is(Blocks.TRIPWIRE)) level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, Boolean.valueOf(flag2)), 3); // Paper - prevent tripwire from updating ++ if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates || !blockState3.is(Blocks.TRIPWIRE)) level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, flag2), 3); // Paper - prevent tripwire from updating + } } + // Leaves end - MC-59471 diff --git a/leaves-server/minecraft-patches/features/0014-No-chat-sign.patch b/leaves-server/minecraft-patches/features/0015-No-chat-sign.patch similarity index 93% rename from leaves-server/minecraft-patches/features/0014-No-chat-sign.patch rename to leaves-server/minecraft-patches/features/0015-No-chat-sign.patch index 0ef87c29..eaa5a64a 100644 --- a/leaves-server/minecraft-patches/features/0014-No-chat-sign.patch +++ b/leaves-server/minecraft-patches/features/0015-No-chat-sign.patch @@ -28,7 +28,7 @@ index 47cb25aa9c37bd84d156288c397321009f1d9ae2..a94981882ac37ea215df3a71117d4a9b buffer.writeCollection(this.entries, (buffer1, entry) -> entry.write(buffer1)); } diff --git a/net/minecraft/network/FriendlyByteBuf.java b/net/minecraft/network/FriendlyByteBuf.java -index d1daa3443446f47e2215f0c7c5823da58e053bab..60b39a320b795a320a28fd9c003ee948a0cc0208 100644 +index 7da7d645f83f351e8c964da01734f3074a877ca1..a9d37c540397b5e24721b3eba47e2d5b2577579f 100644 --- a/net/minecraft/network/FriendlyByteBuf.java +++ b/net/minecraft/network/FriendlyByteBuf.java @@ -118,6 +118,14 @@ public class FriendlyByteBuf extends ByteBuf { @@ -91,10 +91,10 @@ index 1df628ac0b414511aaed6e09d78f884c4170f730..b92081d70ffeec47c304e553ce1aea0a } } diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 529a2caa2cde82bfdea7c173768fee32f5f21e49..a8775acd67db19ad671d2de252c0c553ee9f90ca 100644 +index e56f26fc504538d88bfa1954e929ee44fd31d657..e4946438d0c1fb9d2be616cb95768f890b32f286 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -616,7 +616,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -574,7 +574,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface // Paper start - Add setting for proxy online mode status return properties.enforceSecureProfile && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() @@ -104,10 +104,10 @@ index 529a2caa2cde82bfdea7c173768fee32f5f21e49..a8775acd67db19ad671d2de252c0c553 } diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -index ba6338037f04a35a9f8c93cdb1e4b9d53c1a7925..888cecc9a91587ddb01deac698ff4c25b1242516 100644 +index ac5ef04fae4bc19bae9007c0ffd8f688434d22d7..649aeec6954d26cb67827e99c4b5b736f4f5bef4 100644 --- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -@@ -288,10 +288,24 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -294,10 +294,24 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } public void send(Packet packet) { @@ -133,13 +133,13 @@ index ba6338037f04a35a9f8c93cdb1e4b9d53c1a7925..888cecc9a91587ddb01deac698ff4c25 if (packet == null || this.processedDisconnect) { // Spigot return; diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index bd7ae7aba1802f202ea09cb1064832092da30c4b..43759c08630fce13199cc3dda1841c52088b615e 100644 +index 012574f56d9d7e6340c8b7bf7bee43e36d99df65..ffa92892ab4e1e079fa058a270877a9654624875 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -1320,7 +1320,7 @@ public abstract class PlayerList { +@@ -1336,7 +1336,7 @@ public abstract class PlayerList { } - public boolean verifyChatTrusted(PlayerChatMessage message) { // Paper - private -> public + public boolean verifyChatTrusted(PlayerChatMessage message) { - return message.hasSignature() && !message.hasExpiredServer(Instant.now()); + return org.leavesmc.leaves.LeavesConfig.mics.noChatSign || (message.hasSignature() && !message.hasExpiredServer(Instant.now())); // Leaves - No Not Secure } diff --git a/leaves-server/minecraft-patches/features/0015-Dont-send-useless-entity-packets.patch b/leaves-server/minecraft-patches/features/0016-Dont-send-useless-entity-packets.patch similarity index 83% rename from leaves-server/minecraft-patches/features/0015-Dont-send-useless-entity-packets.patch rename to leaves-server/minecraft-patches/features/0016-Dont-send-useless-entity-packets.patch index f5f77e39..e042b851 100644 --- a/leaves-server/minecraft-patches/features/0015-Dont-send-useless-entity-packets.patch +++ b/leaves-server/minecraft-patches/features/0016-Dont-send-useless-entity-packets.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Dont send useless entity packets This patch is Powered by Purpur(https://github.com/PurpurMC/Purpur) diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java -index 0fb253aa55a24b56b17f524b3261c5b75c7d7e59..f2974a0f49711d17c349fdfa8f57d3a4706ff0ca 100644 +index b118e91f1e0b5a8b8c0b2a4a32faabc5a34a5954..7681195587d361acf524d09ad3958e628aad73b6 100644 --- a/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java -@@ -186,6 +186,11 @@ public class ServerEntity { +@@ -196,6 +196,11 @@ public class ServerEntity { } else if (flag) { packet = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), b, b1, this.entity.onGround()); flag4 = true; @@ -21,8 +21,8 @@ index 0fb253aa55a24b56b17f524b3261c5b75c7d7e59..f2974a0f49711d17c349fdfa8f57d3a4 } } else { packet = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short)l, (short)l1, (short)l2, b, b1, this.entity.onGround()); -@@ -302,6 +307,21 @@ public class ServerEntity { - return currentPassengers.stream().filter(entity -> !initialPassengers.contains(entity)); +@@ -315,6 +320,21 @@ public class ServerEntity { + this.positionCodec.setBase(this.entity.position()); } + // Leaves start - dont send useless entity packets @@ -31,9 +31,9 @@ index 0fb253aa55a24b56b17f524b3261c5b75c7d7e59..f2974a0f49711d17c349fdfa8f57d3a4 + if (possibleUselessPacket instanceof ClientboundMoveEntityPacket.Pos) { + return packet.getXa() == 0 && packet.getYa() == 0 && packet.getZa() == 0; + } else if (possibleUselessPacket instanceof ClientboundMoveEntityPacket.PosRot) { -+ return packet.getXa() == 0 && packet.getYa() == 0 && packet.getZa() == 0 && packet.getyRot() == 0 && packet.getxRot() == 0; ++ return packet.getXa() == 0 && packet.getYa() == 0 && packet.getZa() == 0 && packet.getYRot() == 0 && packet.getXRot() == 0; + } else if (possibleUselessPacket instanceof ClientboundMoveEntityPacket.Rot) { -+ return packet.getyRot() == 0 && packet.getxRot() == 0; ++ return packet.getYRot() == 0 && packet.getXRot() == 0; + } + } + return false; diff --git a/leaves-server/minecraft-patches/features/0016-Optimize-suffocation.patch b/leaves-server/minecraft-patches/features/0017-Optimize-suffocation.patch similarity index 54% rename from leaves-server/minecraft-patches/features/0016-Optimize-suffocation.patch rename to leaves-server/minecraft-patches/features/0017-Optimize-suffocation.patch index 6c27f4fa..16211a72 100644 --- a/leaves-server/minecraft-patches/features/0016-Optimize-suffocation.patch +++ b/leaves-server/minecraft-patches/features/0017-Optimize-suffocation.patch @@ -6,19 +6,19 @@ Subject: [PATCH] Optimize suffocation This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 985a6428f91c5834f36b5cea632af83f50f49f2d..144b756fede8afcb42015a4b155801d6c3715a45 100644 +index 5fc4d97ef421a37158b01864b035385bb7bf5f5f..b5f6a76c977bbb5dbb06fb3dd654f0b01aaba692 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -452,7 +452,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - if (this.isAlive()) { +@@ -423,7 +423,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + + if (this.isAlive() && this.level() instanceof ServerLevel serverLevel1) { boolean flag = this instanceof Player; - if (this.level() instanceof ServerLevel serverLevel1) { -- if (this.isInWall()) { -+ if ((!org.leavesmc.leaves.LeavesConfig.performance.enableSuffocationOptimization || this instanceof WitherBoss || (tickCount % 10 == 0 && couldPossiblyBeHurt(1.0F))) && this.isInWall()) { // Leaves - optimize suffocation - this.hurtServer(serverLevel1, this.damageSources().inWall(), 1.0F); - } else if (flag && !this.level().getWorldBorder().isWithinBounds(this.getBoundingBox())) { - double d = this.level().getWorldBorder().getDistanceToBorder(this) + this.level().getWorldBorder().getDamageSafeZone(); -@@ -1359,6 +1359,12 @@ public abstract class LivingEntity extends Entity implements Attackable { +- if (this.isInWall()) { ++ if ((!org.leavesmc.leaves.LeavesConfig.performance.enableSuffocationOptimization || this instanceof WitherBoss || (tickCount % 10 == 0 && couldPossiblyBeHurt(1.0F))) && this.isInWall()) { // Leaves - optimize suffocation + this.hurtServer(serverLevel1, this.damageSources().inWall(), 1.0F); + } else if (flag && !serverLevel1.getWorldBorder().isWithinBounds(this.getBoundingBox())) { + double d = serverLevel1.getWorldBorder().getDistanceToBorder(this) + serverLevel1.getWorldBorder().getDamageSafeZone(); +@@ -1372,6 +1372,12 @@ public abstract class LivingEntity extends Entity implements Attackable { return this.getHealth() <= 0.0F; } diff --git a/leaves-server/minecraft-patches/features/0017-Only-check-for-spooky-season-once-an-hour.patch b/leaves-server/minecraft-patches/features/0018-Only-check-for-spooky-season-once-an-hour.patch similarity index 92% rename from leaves-server/minecraft-patches/features/0017-Only-check-for-spooky-season-once-an-hour.patch rename to leaves-server/minecraft-patches/features/0018-Only-check-for-spooky-season-once-an-hour.patch index e2bce914..13e39bd9 100644 --- a/leaves-server/minecraft-patches/features/0017-Only-check-for-spooky-season-once-an-hour.patch +++ b/leaves-server/minecraft-patches/features/0018-Only-check-for-spooky-season-once-an-hour.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Only check for spooky season once an hour This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/net/minecraft/world/entity/ambient/Bat.java b/net/minecraft/world/entity/ambient/Bat.java -index 5ebe7b1dce367d5c5e1136b97b2b9f6737595201..54e59c1fdc9c189b9c6fb620444aeb3d08fde67a 100644 +index eb9fb57440f498079182030a46034008d3f6b5e8..5f0ddf96e8ca1bb32c773f11232dedd1a981fde9 100644 --- a/net/minecraft/world/entity/ambient/Bat.java +++ b/net/minecraft/world/entity/ambient/Bat.java -@@ -243,12 +243,30 @@ public class Bat extends AmbientCreature { +@@ -244,12 +244,30 @@ public class Bat extends AmbientCreature { } } diff --git a/leaves-server/minecraft-patches/features/0018-Config-to-disable-method-profiler.patch b/leaves-server/minecraft-patches/features/0019-Config-to-disable-method-profiler.patch similarity index 91% rename from leaves-server/minecraft-patches/features/0018-Config-to-disable-method-profiler.patch rename to leaves-server/minecraft-patches/features/0019-Config-to-disable-method-profiler.patch index cfdabb7b..3f69e9d2 100644 --- a/leaves-server/minecraft-patches/features/0018-Config-to-disable-method-profiler.patch +++ b/leaves-server/minecraft-patches/features/0019-Config-to-disable-method-profiler.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Config to disable method profiler This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 073d4a57f78dc18e4cf95bdb852877b8624ec3f8..09fc1c1923f7cc4470cca3b703810fb165c4ca15 100644 +index 940e6cb4b8f990e3c4ae8a5efc7adc56ffae28de..105c207b8db2c505f256f4104642af5929b50aa9 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1249,7 +1249,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop attributesToSync = new ObjectOpenHashSet<>(); private final Set attributesToUpdate = new ObjectOpenHashSet<>(); private final AttributeSupplier supplier; @@ -21,7 +21,7 @@ index 4c808c7ef336de74048f40bd1cc8b14131a9325d..22c315f936982e496d26a2846351969b } private void onAttributeModified(AttributeInstance instance) { -@@ -49,7 +51,13 @@ public class AttributeMap { +@@ -44,7 +46,13 @@ public class AttributeMap { @Nullable public AttributeInstance getInstance(Holder attribute) { diff --git a/leaves-server/minecraft-patches/features/0021-Remove-lambda-from-ticking-guard.patch b/leaves-server/minecraft-patches/features/0022-Remove-lambda-from-ticking-guard.patch similarity index 94% rename from leaves-server/minecraft-patches/features/0021-Remove-lambda-from-ticking-guard.patch rename to leaves-server/minecraft-patches/features/0022-Remove-lambda-from-ticking-guard.patch index 757d1a68..5581ba66 100644 --- a/leaves-server/minecraft-patches/features/0021-Remove-lambda-from-ticking-guard.patch +++ b/leaves-server/minecraft-patches/features/0022-Remove-lambda-from-ticking-guard.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Remove lambda from ticking guard This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 9fba04e8a8e95546f7d7cc1210b4b324c86d2b87..30a543de1d8b454ffec0c6cd668aad3504cdf95d 100644 +index b1821dc6bfdda93431e2f43d5de6ecc60901c757..26a20dea38628c7acd88f172a09b12af02a82d09 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -816,7 +816,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -806,7 +806,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } profilerFiller.push("tick"); diff --git a/leaves-server/minecraft-patches/features/0022-Cache-climbing-check-for-activation.patch b/leaves-server/minecraft-patches/features/0023-Cache-climbing-check-for-activation.patch similarity index 89% rename from leaves-server/minecraft-patches/features/0022-Cache-climbing-check-for-activation.patch rename to leaves-server/minecraft-patches/features/0023-Cache-climbing-check-for-activation.patch index 8906559a..22af2ac6 100644 --- a/leaves-server/minecraft-patches/features/0022-Cache-climbing-check-for-activation.patch +++ b/leaves-server/minecraft-patches/features/0023-Cache-climbing-check-for-activation.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Cache climbing check for activation This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java -index bd888ef719b9bfc93bace0b1d0fb771ac659f515..4b552eca363396c7e4ccfbf25d7b826f1c8163bb 100644 +index 2ebee223085fe7926c7f3e555df19ae69f36157e..40f83551c74b594aa5fda82ac67eec72c3cd4942 100644 --- a/io/papermc/paper/entity/activation/ActivationRange.java +++ b/io/papermc/paper/entity/activation/ActivationRange.java @@ -215,7 +215,7 @@ public final class ActivationRange { @@ -19,10 +19,10 @@ index bd888ef719b9bfc93bace0b1d0fb771ac659f515..4b552eca363396c7e4ccfbf25d7b826f } if (entity instanceof final Mob mob && mob.getTarget() != null) { diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 144b756fede8afcb42015a4b155801d6c3715a45..2dd370bf00b5ddf133c946b6e4d37b00be3ca5a5 100644 +index b5f6a76c977bbb5dbb06fb3dd654f0b01aaba692..108430b3934a6f9757e7be50d77e760bbade669c 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -2026,6 +2026,22 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2094,6 +2094,22 @@ public abstract class LivingEntity extends Entity implements Attackable { return this.lastClimbablePos; } diff --git a/leaves-server/minecraft-patches/features/0023-Reduce-chunk-loading-lookups.patch b/leaves-server/minecraft-patches/features/0024-Reduce-chunk-loading-lookups.patch similarity index 92% rename from leaves-server/minecraft-patches/features/0023-Reduce-chunk-loading-lookups.patch rename to leaves-server/minecraft-patches/features/0024-Reduce-chunk-loading-lookups.patch index 43f7e419..1c0e6bff 100644 --- a/leaves-server/minecraft-patches/features/0023-Reduce-chunk-loading-lookups.patch +++ b/leaves-server/minecraft-patches/features/0024-Reduce-chunk-loading-lookups.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Reduce chunk loading & lookups This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java -index 4b5ffd278e0e9d47100e5452949e8d757bbfece4..e2f1623b977889d31407d060b8e0bf911a80049e 100644 +index ab7f7846d3fc0252c6f71277b3e67d7a785a96b5..8ac90690bd3fb7b5bf8798a4ca5c900e8bc7acb3 100644 --- a/net/minecraft/world/entity/monster/EnderMan.java +++ b/net/minecraft/world/entity/monster/EnderMan.java -@@ -309,11 +309,28 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -300,11 +300,28 @@ public class EnderMan extends Monster implements NeutralMob { private boolean teleport(double x, double y, double z) { BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(x, y, z); diff --git a/leaves-server/minecraft-patches/features/0024-InstantBlockUpdater-Reintroduced.patch b/leaves-server/minecraft-patches/features/0025-InstantBlockUpdater-Reintroduced.patch similarity index 86% rename from leaves-server/minecraft-patches/features/0024-InstantBlockUpdater-Reintroduced.patch rename to leaves-server/minecraft-patches/features/0025-InstantBlockUpdater-Reintroduced.patch index f02a1443..497b98e0 100644 --- a/leaves-server/minecraft-patches/features/0024-InstantBlockUpdater-Reintroduced.patch +++ b/leaves-server/minecraft-patches/features/0025-InstantBlockUpdater-Reintroduced.patch @@ -6,10 +6,10 @@ Subject: [PATCH] InstantBlockUpdater Reintroduced This patch is Powered by Carpet-TIS-Addition(https://github.com/plusls/Carpet-TIS-Addition) diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 2bbebb4335d927f240abcac67a5b423e38dc33d7..1c7f7747725f95fe3cb92d26745ada7a9784b407 100644 +index 013ed7dbe2309f562f63e66203179a90566e8115..12a63f75d878fcdad83847b20f5a57f7936c7779 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java -@@ -888,7 +888,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -873,7 +873,13 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl this.thread = Thread.currentThread(); this.biomeManager = new BiomeManager(this, biomeZoomSeed); this.isDebug = isDebug; diff --git a/leaves-server/minecraft-patches/features/0026-BBOR-Protocol.patch b/leaves-server/minecraft-patches/features/0026-BBOR-Protocol.patch deleted file mode 100644 index eb5b927c..00000000 --- a/leaves-server/minecraft-patches/features/0026-BBOR-Protocol.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Mon, 3 Feb 2025 13:03:42 +0800 -Subject: [PATCH] BBOR Protocol - - -diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 43759c08630fce13199cc3dda1841c52088b615e..a79f83991aa50d45695beeeb018f203c6d7ae6d8 100644 ---- a/net/minecraft/server/players/PlayerList.java -+++ b/net/minecraft/server/players/PlayerList.java -@@ -1443,6 +1443,7 @@ public abstract class PlayerList { - serverPlayer.connection.send(clientboundUpdateRecipesPacket); - serverPlayer.getRecipeBook().sendInitialRecipeBook(serverPlayer); - } -+ org.leavesmc.leaves.protocol.BBORProtocol.onDataPackReload(); // Leaves - bbor - } - - public boolean isAllowCommandsForAllPlayers() { -diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index 761fdcd4a4e18f45547afd8edff44f61c6eeacb4..1776b79309ffd9a8a52f27a144606ed9a441251e 100644 ---- a/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/net/minecraft/world/level/chunk/LevelChunk.java -@@ -739,6 +739,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - - public void setLoaded(boolean loaded) { - this.loaded = loaded; -+ // Leaves start - bbor -+ if (loaded) { -+ org.leavesmc.leaves.protocol.BBORProtocol.onChunkLoaded(this); -+ } -+ // Leaves end - bbor - } - - public Level getLevel() { diff --git a/leaves-server/minecraft-patches/features/0025-Random-flatten-triangular-distribution.patch b/leaves-server/minecraft-patches/features/0026-Random-flatten-triangular-distribution.patch similarity index 60% rename from leaves-server/minecraft-patches/features/0025-Random-flatten-triangular-distribution.patch rename to leaves-server/minecraft-patches/features/0026-Random-flatten-triangular-distribution.patch index 4643919e..4e0ddd6e 100644 --- a/leaves-server/minecraft-patches/features/0025-Random-flatten-triangular-distribution.patch +++ b/leaves-server/minecraft-patches/features/0026-Random-flatten-triangular-distribution.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Random flatten triangular distribution This patch is Powered by Carpet-TIS-Addition(https://github.com/plusls/Carpet-TIS-Addition) diff --git a/net/minecraft/util/RandomSource.java b/net/minecraft/util/RandomSource.java -index 98a54bc4de251014342cda6d0951b7fea79ce553..17a79cef7dac1b407e4e62883b4a943d172fa6b9 100644 +index 8516d47b0ba79d91638837199e7ae0fb6cb44a79..49a70e860eafdeca28ca3684a75bd3c8c4668b9c 100644 --- a/net/minecraft/util/RandomSource.java +++ b/net/minecraft/util/RandomSource.java @@ -52,13 +52,25 @@ public interface RandomSource { @@ -14,23 +14,23 @@ index 98a54bc4de251014342cda6d0951b7fea79ce553..17a79cef7dac1b407e4e62883b4a943d double nextGaussian(); + // Leaves start - flattenTriangularDistribution - default double triangle(double center, double maxDeviation) { -- return center + maxDeviation * (this.nextDouble() - this.nextDouble()); + default double triangle(double min, double max) { +- return min + max * (this.nextDouble() - this.nextDouble()); + if (org.leavesmc.leaves.LeavesConfig.modify.flattenTriangularDistribution) { + this.nextDouble(); -+ return center + maxDeviation * (-1 + this.nextDouble() * 2); ++ return min + max * (-1 + this.nextDouble() * 2); + } else { -+ return center + maxDeviation * (this.nextDouble() - this.nextDouble()); ++ return min + max * (this.nextDouble() - this.nextDouble()); + } } - default float triangle(float center, float maxDeviation) { -- return center + maxDeviation * (this.nextFloat() - this.nextFloat()); + default float triangle(float min, float max) { +- return min + max * (this.nextFloat() - this.nextFloat()); + if (org.leavesmc.leaves.LeavesConfig.modify.flattenTriangularDistribution) { + this.nextFloat(); -+ return center + maxDeviation * (-1 + this.nextFloat() * 2); ++ return min + max * (-1 + this.nextFloat() * 2); + } else { -+ return center + maxDeviation * (this.nextFloat() - this.nextFloat()); ++ return min + max * (this.nextFloat() - this.nextFloat()); + } } + // Leaves end - flattenTriangularDistribution diff --git a/leaves-server/minecraft-patches/features/0027-BBOR-Protocol.patch b/leaves-server/minecraft-patches/features/0027-BBOR-Protocol.patch new file mode 100644 index 00000000..51256fda --- /dev/null +++ b/leaves-server/minecraft-patches/features/0027-BBOR-Protocol.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: violetc <58360096+s-yh-china@users.noreply.github.com> +Date: Mon, 3 Feb 2025 13:03:42 +0800 +Subject: [PATCH] BBOR Protocol + + +diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java +index 5d3fc807221392d378fec283bfdefb8747fb8376..bf731da711ce629c0f9250a7bd4025d363623773 100644 +--- a/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/net/minecraft/world/level/chunk/LevelChunk.java +@@ -743,6 +743,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p + + public void setLoaded(boolean loaded) { + this.loaded = loaded; ++ // Leaves start - bbor ++ if (loaded) { ++ org.leavesmc.leaves.protocol.BBORProtocol.onChunkLoaded(this); ++ } ++ // Leaves end - bbor + } + + public Level getLevel() { diff --git a/leaves-server/minecraft-patches/features/0027-PCA-sync-protocol.patch b/leaves-server/minecraft-patches/features/0028-PCA-sync-protocol.patch similarity index 77% rename from leaves-server/minecraft-patches/features/0027-PCA-sync-protocol.patch rename to leaves-server/minecraft-patches/features/0028-PCA-sync-protocol.patch index 51713f20..97714888 100644 --- a/leaves-server/minecraft-patches/features/0027-PCA-sync-protocol.patch +++ b/leaves-server/minecraft-patches/features/0028-PCA-sync-protocol.patch @@ -6,26 +6,28 @@ Subject: [PATCH] PCA sync protocol This patch is Powered by plusls-carpet-addition(https://github.com/plusls/plusls-carpet-addition) diff --git a/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index d52a8315f1e6876c26c732f4c4caa47bc6bebf6e..8f287d11ab9ce493d34bf70780964c0f9a7faaa0 100644 +index 7c473eea481f5e055cc70512027726f41f0c6f67..3165d1eaa46f2adceba28d4aef95fda3f05ee5e3 100644 --- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java +++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -422,6 +422,11 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, - - @Override - public void containerChanged(Container invBasic) { +@@ -303,6 +303,13 @@ public abstract class AbstractHorse extends Animal implements HasCustomInventory + public void createInventory() { + SimpleContainer simpleContainer = this.inventory; + this.inventory = new SimpleContainer(this.getInventorySize(), (org.bukkit.entity.AbstractHorse) this.getBukkitEntity()); // CraftBukkit + // Leaves start - pca -+ if (org.leavesmc.leaves.LeavesConfig.protocol.pca.enable) { -+ org.leavesmc.leaves.protocol.PcaSyncProtocol.syncEntityToClient(this); -+ } ++ this.inventory.addListener(inv -> { ++ if (org.leavesmc.leaves.LeavesConfig.protocol.pca.enable) { ++ org.leavesmc.leaves.protocol.PcaSyncProtocol.syncEntityToClient(this); ++ } ++ }); + // Leaves end - pca - boolean isSaddled = this.isSaddled(); - this.syncSaddleToClients(); - if (this.tickCount > 20 && !isSaddled && this.isSaddled()) { + if (simpleContainer != null) { + int min = Math.min(simpleContainer.getContainerSize(), this.inventory.getContainerSize()); + diff --git a/net/minecraft/world/entity/npc/AbstractVillager.java b/net/minecraft/world/entity/npc/AbstractVillager.java -index a71d16d968bb90fd7aca6f01a3dd56df4f9a7ce6..18a087a52070b9bdee4d02ff3fc6a3c063e444d4 100644 +index 1d3381f1481bb2b192bb78462c85c2a185d94ad5..a375fad192cc09ba83775d5e37c1bb351730e6c4 100644 --- a/net/minecraft/world/entity/npc/AbstractVillager.java +++ b/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -65,6 +65,15 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa +@@ -48,6 +48,15 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa super(entityType, level); this.setPathfindingMalus(PathType.DANGER_FIRE, 16.0F); this.setPathfindingMalus(PathType.DAMAGE_FIRE, -1.0F); @@ -42,7 +44,7 @@ index a71d16d968bb90fd7aca6f01a3dd56df4f9a7ce6..18a087a52070b9bdee4d02ff3fc6a3c0 @Override diff --git a/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java -index 516b230769fb9ddaa49adca9b6aa64d4510810da..c279e2cdafbb710b799a730e5cf7056dd2142d3b 100644 +index a7e2f23ed3279801504f99fc3c5f972e8c1b984f..4509b1a68273effa30d1befafc9104220d02fe8b 100644 --- a/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +++ b/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java @@ -64,6 +64,11 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme @@ -58,10 +60,10 @@ index 516b230769fb9ddaa49adca9b6aa64d4510810da..c279e2cdafbb710b799a730e5cf7056d @Override diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index cb4b8567c029e3a53aafda2755e3773ea8b95af7..77e7188180cce9ef881de64b263c704b219b610a 100644 +index c5b3b5e5f621f8db152aa190374ae0fe567d6828..7729c33cad94cf2b4162324be75713650fc9d378 100644 --- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -434,6 +434,16 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -429,6 +429,16 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit } } @@ -79,10 +81,10 @@ index cb4b8567c029e3a53aafda2755e3773ea8b95af7..77e7188180cce9ef881de64b263c704b public void setRecipeUsed(@Nullable RecipeHolder recipe) { if (recipe != null) { diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -index 0f808855f58281578c2758513787f0f7330c9291..e31f55ad12160c8406c0ab719f593d4c35ac9100 100644 +index 027502d0af5512c31878978c4d05c52fa3029cca..b3da250aa326d05a4e95c7b749c8ae8975dfd804 100644 --- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -@@ -120,6 +120,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { +@@ -121,6 +121,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { this.items = items; } @@ -100,10 +102,10 @@ index 0f808855f58281578c2758513787f0f7330c9291..e31f55ad12160c8406c0ab719f593d4c protected Component getDefaultName() { return Component.translatable("container.barrel"); diff --git a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -index fbde2680b405b9fa7ed2fe70046b77e971b53e48..c3d02d115282bd6dff8b5616f1ce5571e678949d 100644 +index 331eb5416307378162e39e20192ba06a047b70ea..69419e74c308e46509cc40fde9ed05583964a1ca 100644 --- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -@@ -151,6 +151,11 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -144,6 +144,11 @@ public class BeehiveBlockEntity extends BlockEntity { super.setChanged(); } @@ -115,7 +117,7 @@ index fbde2680b405b9fa7ed2fe70046b77e971b53e48..c3d02d115282bd6dff8b5616f1ce5571 return list; } -@@ -208,6 +213,11 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -201,6 +206,11 @@ public class BeehiveBlockEntity extends BlockEntity { this.level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(bee, this.getBlockState())); } @@ -127,7 +129,7 @@ index fbde2680b405b9fa7ed2fe70046b77e971b53e48..c3d02d115282bd6dff8b5616f1ce5571 bee.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.ENTER_BLOCK); // CraftBukkit - add Bukkit remove cause super.setChanged(); } -@@ -329,6 +339,11 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -322,6 +332,11 @@ public class BeehiveBlockEntity extends BlockEntity { if (releaseOccupant(level, pos, state, beeData.toOccupant(), null, beeReleaseStatus, savedFlowerPos)) { flag = true; iterator.remove(); @@ -139,10 +141,10 @@ index fbde2680b405b9fa7ed2fe70046b77e971b53e48..c3d02d115282bd6dff8b5616f1ce5571 } // Paper start - Fix bees aging inside; use exitTickCounter to keep actual bee life else if (level.paperConfig().entities.behavior.cooldownFailedBeehiveReleases) { -@@ -372,6 +387,11 @@ public class BeehiveBlockEntity extends BlockEntity { - this.maxBees = tag.getInt("Bukkit.MaxEntities"); - } - // CraftBukkit end +@@ -355,6 +370,11 @@ public class BeehiveBlockEntity extends BlockEntity { + tag.read("bees", BeehiveBlockEntity.Occupant.LIST_CODEC).orElse(List.of()).forEach(this::storeBee); + this.savedFlowerPos = tag.read("flower_pos", BlockPos.CODEC).orElse(null); + this.maxBees = tag.getIntOr("Bukkit.MaxEntities", MAX_OCCUPANTS); // Paper - persist max bukkit occupants + // Leaves start - pca + if (org.leavesmc.leaves.LeavesConfig.protocol.pca.enable) { + org.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this); @@ -152,10 +154,10 @@ index fbde2680b405b9fa7ed2fe70046b77e971b53e48..c3d02d115282bd6dff8b5616f1ce5571 @Override diff --git a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java -index 94f9477e78600eded6eecc4c961576501001d187..a9a85655aac78a0be91100e8b411a28eb066162d 100644 +index 2e369167d4d1664df1f0b375597bb12b728c5c62..e13a2845efc88bd68ee96cbc1b58bf4f7fb77845 100644 --- a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java -@@ -324,4 +324,14 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements +@@ -331,4 +331,14 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements protected AbstractContainerMenu createMenu(int id, Inventory player) { return new BrewingStandMenu(id, player, this, this.dataAccess); } @@ -171,10 +173,10 @@ index 94f9477e78600eded6eecc4c961576501001d187..a9a85655aac78a0be91100e8b411a28e + // Leaves end - pca } diff --git a/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/net/minecraft/world/level/block/entity/ChestBlockEntity.java -index fd1075eadf39359c55162cf28cad2e3b08086d4a..4489db4f765a6154246be6127ff376244e8889a7 100644 +index a7a095cc0ffdf7b0daf7b4d19c3e78bc4399fa7c..faac046a95a7db5f5fd456bd8f768b0aaab1db5e 100644 --- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java -@@ -198,6 +198,16 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement +@@ -202,6 +202,16 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement otherChest.setItems(items); } @@ -192,11 +194,11 @@ index fd1075eadf39359c55162cf28cad2e3b08086d4a..4489db4f765a6154246be6127ff37624 protected AbstractContainerMenu createMenu(int id, Inventory player) { return ChestMenu.threeRows(id, player, this); diff --git a/net/minecraft/world/level/block/entity/ComparatorBlockEntity.java b/net/minecraft/world/level/block/entity/ComparatorBlockEntity.java -index d3bff18645f4d3c5b71a9ee232b8e51fa8aaaaa0..2922ce789b7ae5bcd4adb70ab153ecb19355e030 100644 +index d0119f3df52fe26c85d8b67ee59e24adf7b427ac..18ff2cd322168f57f3a1b3b4c0e9a02560cb9965 100644 --- a/net/minecraft/world/level/block/entity/ComparatorBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ComparatorBlockEntity.java -@@ -24,6 +24,16 @@ public class ComparatorBlockEntity extends BlockEntity { - this.output = tag.getInt("OutputSignal"); +@@ -25,6 +25,16 @@ public class ComparatorBlockEntity extends BlockEntity { + this.output = tag.getIntOr("OutputSignal", 0); } + // Leaves start - pca @@ -213,10 +215,10 @@ index d3bff18645f4d3c5b71a9ee232b8e51fa8aaaaa0..2922ce789b7ae5bcd4adb70ab153ecb1 return this.output; } diff --git a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java -index 33ca79c5713961a657d3a7af1f53b89e9449eba9..3c62662e626d3f0e309d2a973c73e6ac1055cae3 100644 +index 3fb7a7b9f182062ebed778e7bb9ba239ae9f179c..a8256fd0d14655fe480b6e04ce32814e54f9d9c6 100644 --- a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java +++ b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java -@@ -99,6 +99,16 @@ public class DispenserBlockEntity extends RandomizableContainerBlockEntity { +@@ -104,6 +104,16 @@ public class DispenserBlockEntity extends RandomizableContainerBlockEntity { return stack; } @@ -234,10 +236,10 @@ index 33ca79c5713961a657d3a7af1f53b89e9449eba9..3c62662e626d3f0e309d2a973c73e6ac protected Component getDefaultName() { return Component.translatable("container.dispenser"); diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 5cd1326ad5d046c88b2b3449d610a78fa880b4cd..42a29e700d2549de7cd905c373212e9757bcfcf1 100644 +index 15d4f60942c0cc612c1468b4c0fda886867a67cb..212a1a1410550a2456a88a948f377048447a1fc8 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -118,6 +118,16 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -122,6 +122,16 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen this.facing = blockState.getValue(HopperBlock.FACING); } @@ -254,7 +256,7 @@ index 5cd1326ad5d046c88b2b3449d610a78fa880b4cd..42a29e700d2549de7cd905c373212e97 @Override protected Component getDefaultName() { return Component.translatable("container.hopper"); -@@ -194,6 +204,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -198,6 +208,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen if (flag) { blockEntity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot setChanged(level, pos, state); @@ -267,10 +269,10 @@ index 5cd1326ad5d046c88b2b3449d610a78fa880b4cd..42a29e700d2549de7cd905c373212e97 } } diff --git a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java -index a2ae4b47d742e7fb9809cfc4575517c06400ec61..cc8781c0a357eebc2bff936b4e7be53cc316716d 100644 +index 87ebdb6deb66662a38b3eec0dae27eaf859ecabb..5e58113b3401268e0432235dc10b2734dbbd8b71 100644 --- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java -@@ -258,6 +258,16 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl +@@ -267,6 +267,16 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl this.itemStacks = items; } diff --git a/leaves-server/minecraft-patches/features/0029-Alternative-block-placement-Protocol.patch b/leaves-server/minecraft-patches/features/0029-Alternative-block-placement-Protocol.patch index 979f9139..5485cb1e 100644 --- a/leaves-server/minecraft-patches/features/0029-Alternative-block-placement-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0029-Alternative-block-placement-Protocol.patch @@ -9,10 +9,10 @@ MasaGadget(https://github.com/plusls/MasaGadget) litematica(https://github.com/maruohon/litematica) diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java -index 68e50c6ade879d263424f244070677cb81c34c33..e619a872d51bf0be64ff594c916c89a5bbf1d3fc 100644 +index 2fbbbac9f1472354bd507926a85c25f48291edfe..98c94e0957933828be79e6326d782af6aa738dd9 100644 --- a/net/minecraft/world/item/BlockItem.java +++ b/net/minecraft/world/item/BlockItem.java -@@ -158,6 +158,27 @@ public class BlockItem extends Item { +@@ -151,6 +151,27 @@ public class BlockItem extends Item { @Nullable protected BlockState getPlacementState(BlockPlaceContext context) { BlockState stateForPlacement = this.getBlock().getStateForPlacement(context); @@ -62,10 +62,10 @@ index 12c6c8aeec89a0a55633c62fe98f5a3aa75fd476..1f0e7c391d02b18e2c89700025713ec3 blockState = blockState1; break; diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java -index 37f561ae2eca0d118c63f519fabdcfe9cb710826..43e338e75b7ded9f80e4ff2ce1a7dac043c93ea1 100644 +index f289e37f77e1c9d3b0f6c29da1b99f0d5f156e37..848409f44e766ce2a5b74563bf2fd4a6b5d63d33 100644 --- a/net/minecraft/world/level/block/Block.java +++ b/net/minecraft/world/level/block/Block.java -@@ -392,6 +392,33 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -439,6 +439,33 @@ public class Block extends BlockBehaviour implements ItemLike { public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { } diff --git a/leaves-server/minecraft-patches/features/0028-Jade-Protocol.patch b/leaves-server/minecraft-patches/features/0030-Jade-Protocol.patch similarity index 89% rename from leaves-server/minecraft-patches/features/0028-Jade-Protocol.patch rename to leaves-server/minecraft-patches/features/0030-Jade-Protocol.patch index 5f2caac8..cbf25c5e 100644 --- a/leaves-server/minecraft-patches/features/0028-Jade-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0030-Jade-Protocol.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Jade Protocol This patch is Powered by Jade(https://github.com/Snownee/Jade) diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java -index dfdbcb31458095a71c187efc2774ecc4945dd11b..cbcd0b7d2107f7ddd353b2bc2d51a0af32450c57 100644 +index b72e07ad954efa7f26f876a59f428086b40d9bb2..102746fc84ca9c8899db971fc1490060ea016b7e 100644 --- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java +++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java -@@ -61,7 +61,7 @@ public class Armadillo extends Animal { +@@ -62,7 +62,7 @@ public class Armadillo extends Animal { public final AnimationState rollOutAnimationState = new AnimationState(); public final AnimationState rollUpAnimationState = new AnimationState(); public final AnimationState peekAnimationState = new AnimationState(); @@ -19,10 +19,10 @@ index dfdbcb31458095a71c187efc2774ecc4945dd11b..cbcd0b7d2107f7ddd353b2bc2d51a0af public Armadillo(EntityType entityType, Level level) { diff --git a/net/minecraft/world/entity/animal/frog/Tadpole.java b/net/minecraft/world/entity/animal/frog/Tadpole.java -index 97adf8142cdd322c4873c420ed760e9dee34da23..cd04199fa8861025e92884f9ec2d3c721c50ad75 100644 +index ebdfd3fb6c0de48982d392bb2aa415f3676c6056..9d5acb2559143358b1258cbb674191bdddb331e3 100644 --- a/net/minecraft/world/entity/animal/frog/Tadpole.java +++ b/net/minecraft/world/entity/animal/frog/Tadpole.java -@@ -253,7 +253,7 @@ public class Tadpole extends AbstractFish { +@@ -252,7 +252,7 @@ public class Tadpole extends AbstractFish { } } @@ -45,11 +45,11 @@ index 29ad43245a310756c4227acd7532e905f7f8b8ee..ad422817593449b8e914628b51d760e7 private final Predicate compositeCondition; private final List functions; diff --git a/net/minecraft/world/level/storage/loot/LootTable.java b/net/minecraft/world/level/storage/loot/LootTable.java -index f95d0f2da3d958519d28278079555c800aad02f8..bebffd07047e41c53b9e4f1ad5917680b8e8c796 100644 +index 7a8eb1e8b07647e1124594f78652d34731e4fda6..6cfe7ef8c81f506bce9c971b597cc4e902bcabbe 100644 --- a/net/minecraft/world/level/storage/loot/LootTable.java +++ b/net/minecraft/world/level/storage/loot/LootTable.java -@@ -45,7 +45,7 @@ public class LootTable { - public static final Codec> CODEC = RegistryFileCodec.create(Registries.LOOT_TABLE, DIRECT_CODEC); +@@ -49,7 +49,7 @@ public class LootTable { + public static final LootTable EMPTY = new LootTable(LootContextParamSets.EMPTY, Optional.empty(), List.of(), List.of()); private final ContextKeySet paramSet; private final Optional randomSequence; - private final List pools; @@ -84,10 +84,10 @@ index e0e933245e038b7229eeddbda272b081161ab603..c5e3834fa970ac909cefea4342037839 protected LootPoolEntryContainer(List conditions) { diff --git a/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java b/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java -index d5e697a0cf6091a7f37c68e3c2a52851535735b1..a8a5a872a8647896e80f91cb5a89adead4005cf7 100644 +index f7b647e81ca99040bae8161a2bc0dcacf5bd537f..069df530b1db72bd4a2b1b80b2570dca545dfd20 100644 --- a/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java +++ b/net/minecraft/world/level/storage/loot/entries/NestedLootTable.java -@@ -25,7 +25,7 @@ public class NestedLootTable extends LootPoolSingletonContainer { +@@ -22,7 +22,7 @@ public class NestedLootTable extends LootPoolSingletonContainer { .and(singletonFields(instance)) .apply(instance, NestedLootTable::new) ); diff --git a/leaves-server/minecraft-patches/features/0030-Player-operation-limiter.patch b/leaves-server/minecraft-patches/features/0031-Player-operation-limiter.patch similarity index 84% rename from leaves-server/minecraft-patches/features/0030-Player-operation-limiter.patch rename to leaves-server/minecraft-patches/features/0031-Player-operation-limiter.patch index be0fc72e..6204cd0b 100644 --- a/leaves-server/minecraft-patches/features/0030-Player-operation-limiter.patch +++ b/leaves-server/minecraft-patches/features/0031-Player-operation-limiter.patch @@ -6,13 +6,13 @@ Subject: [PATCH] Player operation limiter This patch is Powered by plusls-carpet-addition(https://github.com/plusls/plusls-carpet-addition) diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 339cec1f040d47bb37834c6ebe0633b7c991e0cd..b18a818e4d795b6fb269ad57ffb49840c8d879ab 100644 +index 01687ea3acf449c49cbc615887a7dbdd3a693613..988992a181e35a3856817419cb4941c73a9c31f2 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -400,6 +400,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent +@@ -420,6 +420,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + public @Nullable com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent public @Nullable String clientBrandName = null; // Paper - Brand support - public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event + public @Nullable org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event + // Leaves start - player operation limiter + private int instaBreakCountPerTick = 0; + private int placeBlockCountPerTick = 0; @@ -20,7 +20,7 @@ index 339cec1f040d47bb37834c6ebe0633b7c991e0cd..b18a818e4d795b6fb269ad57ffb49840 // Paper start - rewrite chunk system private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader; -@@ -805,6 +809,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -744,6 +748,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc } // CraftBukkit end this.tickClientLoadTimeout(); @@ -28,7 +28,7 @@ index 339cec1f040d47bb37834c6ebe0633b7c991e0cd..b18a818e4d795b6fb269ad57ffb49840 this.gameMode.tick(); this.wardenSpawnTracker.tick(); if (this.invulnerableTime > 0) { -@@ -3090,4 +3095,31 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -2933,4 +2938,31 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc return (org.bukkit.craftbukkit.entity.CraftPlayer) super.getBukkitEntity(); } // CraftBukkit end @@ -61,10 +61,10 @@ index 339cec1f040d47bb37834c6ebe0633b7c991e0cd..b18a818e4d795b6fb269ad57ffb49840 + // Leaves end - player operation limiter } diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java -index 623c069f1fe079e020c6391a3db1a3d95cd3dbf5..d2b2290c73826278a89eb02ab81ee503ee41a4a2 100644 +index b604cba2490a747661d6819251bc3b9a1d35c7d4..5e54d6de0430cd137fbe13ca8f17dc487ce52ff3 100644 --- a/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -303,6 +303,19 @@ public class ServerPlayerGameMode { +@@ -300,6 +300,19 @@ public class ServerPlayerGameMode { } public void destroyAndAck(BlockPos pos, int sequence, String message) { @@ -85,10 +85,10 @@ index 623c069f1fe079e020c6391a3db1a3d95cd3dbf5..d2b2290c73826278a89eb02ab81ee503 this.debugLogging(pos, true, sequence, message); } else { diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java -index e619a872d51bf0be64ff594c916c89a5bbf1d3fc..1f4a3d2610abfa2ea2b1d5feba9606b806d6d416 100644 +index 3f58574069f22d83298a77f253255b25724890ad..0c67e5481a43bf7c02bb54a8ea1abca77d53a292 100644 --- a/net/minecraft/world/item/BlockItem.java +++ b/net/minecraft/world/item/BlockItem.java -@@ -72,6 +72,21 @@ public class BlockItem extends Item { +@@ -65,6 +65,21 @@ public class BlockItem extends Item { final org.bukkit.block.BlockState oldBukkitState = bukkitState != null ? bukkitState : org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockPlaceContext.getLevel(), blockPlaceContext.getClickedPos()); // Paper - Reset placed block on exception // CraftBukkit end diff --git a/leaves-server/minecraft-patches/features/0031-Renewable-Elytra.patch b/leaves-server/minecraft-patches/features/0032-Renewable-Elytra.patch similarity index 89% rename from leaves-server/minecraft-patches/features/0031-Renewable-Elytra.patch rename to leaves-server/minecraft-patches/features/0032-Renewable-Elytra.patch index 2e7e5e7f..e4540336 100644 --- a/leaves-server/minecraft-patches/features/0031-Renewable-Elytra.patch +++ b/leaves-server/minecraft-patches/features/0032-Renewable-Elytra.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Renewable Elytra This patch is Powered by Carpet-TIS-Addition(https://github.com/plusls/Carpet-TIS-Addition) diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java -index a91aba11ecda561d117c9d8db85c92cdcd81887e..d4123b93cec95daeb9991cf20b1d2c8701474606 100644 +index 483b0499f1f70b3aa8862e6cd8e512748492bee0..896c6fe4ee76708f09022934056cd9de74c5e851 100644 --- a/net/minecraft/world/entity/monster/Phantom.java +++ b/net/minecraft/world/entity/monster/Phantom.java -@@ -242,6 +242,20 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -231,6 +231,20 @@ public class Phantom extends FlyingMob implements Enemy { return targetingConditions.test(level, this, entity); } diff --git a/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch b/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch index cac80e2a..207dd868 100644 --- a/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch +++ b/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch @@ -6,10 +6,10 @@ Subject: [PATCH] MC Technical Survival Mode Will automatically overwrite some configuration after startup diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index b18a818e4d795b6fb269ad57ffb49840c8d879ab..0df1160ce4e027cc1c1bf7071a4d8730aaa7fde6 100644 +index 988992a181e35a3856817419cb4941c73a9c31f2..66110486725de7967e55839043b9fc9690e4c0f5 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -1687,7 +1687,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1614,7 +1614,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public boolean isInvulnerableTo(ServerLevel level, DamageSource damageSource) { return (super.isInvulnerableTo(level, damageSource) // Paper - disable player cramming; || this.isChangingDimension() && !damageSource.is(DamageTypes.ENDER_PEARL) @@ -19,7 +19,7 @@ index b18a818e4d795b6fb269ad57ffb49840c8d879ab..0df1160ce4e027cc1c1bf7071a4d8730 @Override diff --git a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java -index ff1c84d37db48e1bd0283a900e199647c0e8eba1..cefa4c03b1d3722bb3a7872eb75a9f47517fe040 100644 +index d813427cf20117014bc42af0eb7cdee037fbcd9c..35f8644a9b4704363f6fe1ca19135566a45ef835 100644 --- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java @@ -64,7 +64,7 @@ public class EndCrystal extends Entity { @@ -28,14 +28,14 @@ index ff1c84d37db48e1bd0283a900e199647c0e8eba1..cefa4c03b1d3722bb3a7872eb75a9f47 // Paper start - Fix invulnerable end crystals - if (this.level().paperConfig().unsupportedSettings.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) { + if (!org.leavesmc.leaves.LeavesConfig.modify.mcTechnicalMode && this.level().paperConfig().unsupportedSettings.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) { // Leaves - mc technical survival mode - if (!java.util.Objects.equals(((ServerLevel) this.level()).uuid, this.getOriginWorld()) + if (!java.util.Objects.equals(((ServerLevel) this.level()).uuid, this.originWorld) || ((ServerLevel) this.level()).getDragonFight() == null || ((ServerLevel) this.level()).getDragonFight().respawnStage == null diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java -index 40da052e7fea1306a007b3cb5c9daa33e0ef523e..583864d73999e4e25f6c26920c0bf9a7504d8463 100644 +index 5d23d8754b304d5e2fd54400cc81c7fe5c14a804..0f28b1befd42a85ffa5462e86d5cde142f9d1196 100644 --- a/net/minecraft/world/entity/item/PrimedTnt.java +++ b/net/minecraft/world/entity/item/PrimedTnt.java -@@ -98,7 +98,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { +@@ -101,7 +101,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { @Override public void tick() { @@ -45,10 +45,10 @@ index 40da052e7fea1306a007b3cb5c9daa33e0ef523e..583864d73999e4e25f6c26920c0bf9a7 this.applyGravity(); this.move(MoverType.SELF, this.getDeltaMovement()); diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java -index 17ce115e887cbbb06ad02ab7ddb488e27342c0e4..8fd9c191e5b14fc7dd90e8f7229acd6de97e0f9e 100644 +index 14a2514a408a66a83f7b5fb43b4c4dc8f23fd5f4..5427f5e1f0416a8dfa3e9c38c3ce69d6e2bd37a6 100644 --- a/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java -@@ -88,7 +88,7 @@ public final class NaturalSpawner { +@@ -82,7 +82,7 @@ public final class NaturalSpawner { MobCategory category = entity.getType().getCategory(); if (category != MobCategory.MISC) { // Paper start - Only count natural spawns @@ -58,10 +58,10 @@ index 17ce115e887cbbb06ad02ab7ddb488e27342c0e4..8fd9c191e5b14fc7dd90e8f7229acd6d entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { continue; diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 3122753c96e98e57fa900cd15005ab4874e4b1db..50bc72f736e9e7a9839a853254a81f9add03bacf 100644 +index 212a1a1410550a2456a88a948f377048447a1fc8..2d979850378c05ce569782d8e04a452f986612a7 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -271,7 +271,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -275,7 +275,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen origItemStack.setCount(originalItemCount); } } @@ -70,7 +70,7 @@ index 3122753c96e98e57fa900cd15005ab4874e4b1db..50bc72f736e9e7a9839a853254a81f9a hopper.setCooldown(level.spigotConfig.hopperTransfer); } return false; -@@ -312,7 +312,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -316,7 +316,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } origItemStack.setCount(originalItemCount); diff --git a/leaves-server/minecraft-patches/features/0032-Stackable-ShulkerBoxes.patch b/leaves-server/minecraft-patches/features/0034-Stackable-ShulkerBoxes.patch similarity index 77% rename from leaves-server/minecraft-patches/features/0032-Stackable-ShulkerBoxes.patch rename to leaves-server/minecraft-patches/features/0034-Stackable-ShulkerBoxes.patch index ccbf6310..0c56ec9c 100644 --- a/leaves-server/minecraft-patches/features/0032-Stackable-ShulkerBoxes.patch +++ b/leaves-server/minecraft-patches/features/0034-Stackable-ShulkerBoxes.patch @@ -26,7 +26,7 @@ index 643797124fe5a4489d0b7419b7e600c04f283ef2..51971a4ef18ab048dc576c26652982d5 public String serialize(HolderLookup.Provider levelRegistry) { diff --git a/net/minecraft/server/commands/GiveCommand.java b/net/minecraft/server/commands/GiveCommand.java -index 8b7af734ca4ed3cafa810460b2cea6c1e6342a69..10d20e945a8f9e676137e752e357ad71b2ab1122 100644 +index b81f98738ef166336e4cc3092b6ba63f385b68e3..e800abc1149db77bc9b7ee1aabd17526ebda377c 100644 --- a/net/minecraft/server/commands/GiveCommand.java +++ b/net/minecraft/server/commands/GiveCommand.java @@ -52,7 +52,7 @@ public class GiveCommand { @@ -39,19 +39,19 @@ index 8b7af734ca4ed3cafa810460b2cea6c1e6342a69..10d20e945a8f9e676137e752e357ad71 if (count > i) { source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", i, itemStack.getDisplayName())); diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 876d207996724727ca26b139af759eab2e6f4131..c1d55857e4238e78703eebf62af8bf59c660e9ea 100644 +index 9041830c19e2899479e1519488faba5c416ccd88..ca814ebdb05ca3af138bf087f26d2cf50baf3b9c 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2987,7 +2987,7 @@ public class ServerGamePacketListenerImpl +@@ -2974,7 +2974,7 @@ public class ServerGamePacketListenerImpl } else if (slot.mayPlace(cursor)) { if (ItemStack.isSameItemSameComponents(clickedItem, cursor)) { - int toPlace = packet.getButtonNum() == 0 ? cursor.getCount() : 1; + int toPlace = packet.buttonNum() == 0 ? cursor.getCount() : 1; - toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount()); + toPlace = Math.min(toPlace, org.leavesmc.leaves.util.ShulkerBoxUtils.getItemStackMaxCount(clickedItem) - clickedItem.getCount()); // Leaves - stackable shulker boxes toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount()); if (toPlace == 1) { action = InventoryAction.PLACE_ONE; -@@ -3023,7 +3023,7 @@ public class ServerGamePacketListenerImpl +@@ -3010,7 +3010,7 @@ public class ServerGamePacketListenerImpl } } else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) { if (clickedItem.getCount() >= 0) { @@ -60,15 +60,15 @@ index 876d207996724727ca26b139af759eab2e6f4131..c1d55857e4238e78703eebf62af8bf59 // As of 1.5, this is result slots only action = InventoryAction.PICKUP_ALL; } -@@ -3283,6 +3283,7 @@ public class ServerGamePacketListenerImpl +@@ -3269,6 +3269,7 @@ public class ServerGamePacketListenerImpl this.player.containerMenu.broadcastFullState(); } else { this.player.containerMenu.broadcastChanges(); -+ this.player.containerMenu.broadcastCarriedItem(); // Leaves - stackable shulker boxes - force send carried item ++ if (org.leavesmc.leaves.LeavesConfig.modify.shulkerBoxStackSize > 1) this.player.containerMenu.broadcastCarriedItem(); // Leaves - stackable shulker boxes - force send carried item } - if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdatesPublic(); // Paper - Force update attributes. + if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes. } -@@ -3395,7 +3396,7 @@ public class ServerGamePacketListenerImpl +@@ -3381,7 +3382,7 @@ public class ServerGamePacketListenerImpl } boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45; @@ -76,12 +76,20 @@ index 876d207996724727ca26b139af759eab2e6f4131..c1d55857e4238e78703eebf62af8bf59 + boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= org.leavesmc.leaves.util.ShulkerBoxUtils.getItemStackMaxCount(itemStack); // Leaves - stackable shulker boxes if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.slotNum()).getItem(), packet.itemStack()))) { // Insist on valid slot // CraftBukkit start - Call click event - InventoryView inventory = this.player.inventoryMenu.getBukkitView(); + org.bukkit.inventory.InventoryView inventory = this.player.inventoryMenu.getBukkitView(); +@@ -3423,6 +3424,7 @@ public class ServerGamePacketListenerImpl + this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack); + this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack); + this.player.inventoryMenu.broadcastChanges(); ++ if (org.leavesmc.leaves.LeavesConfig.modify.shulkerBoxStackSize > 1) this.player.containerMenu.sendSingleSlot(packet.slotNum(), itemStack); // Leaves - stackable shulker boxes - force send carried item + if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes. + } else if (flag && flag2) { + if (this.dropSpamThrottler.isUnderThreshold()) { diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java -index 2d3721e311851c1801b090e99d4f9d0daf4e5f99..f779d27603e6d81435c061214a2db3a14a31c11e 100644 +index b382665cc125b8b5c0938e5e55984e4bf91d37ff..f575b464a8ce430646cb872ae6206a9a0677736b 100644 --- a/net/minecraft/world/Container.java +++ b/net/minecraft/world/Container.java -@@ -30,6 +30,12 @@ public interface Container extends Clearable { +@@ -32,6 +32,12 @@ public interface Container extends Clearable, Iterable { return Math.min(this.getMaxStackSize(), stack.getMaxStackSize()); } @@ -95,10 +103,10 @@ index 2d3721e311851c1801b090e99d4f9d0daf4e5f99..f779d27603e6d81435c061214a2db3a1 boolean stillValid(Player player); diff --git a/net/minecraft/world/SimpleContainer.java b/net/minecraft/world/SimpleContainer.java -index 190190463086f2fcbe28f00fa2f23795bf11f279..f6ec7accba090aac87eeefba333440ceaf7e7c20 100644 +index 133e042371bcf84f1935903ec57d204e3b7abd84..201599988e20219b6a99bf1594ad6c0c19e09038 100644 --- a/net/minecraft/world/SimpleContainer.java +++ b/net/minecraft/world/SimpleContainer.java -@@ -205,7 +205,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible { +@@ -211,7 +211,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible { @Override public void setItem(int index, ItemStack stack) { this.items.set(index, stack); @@ -107,7 +115,7 @@ index 190190463086f2fcbe28f00fa2f23795bf11f279..f6ec7accba090aac87eeefba333440ce this.setChanged(); } -@@ -280,7 +280,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible { +@@ -286,7 +286,7 @@ public class SimpleContainer implements Container, StackedContentsCompatible { } private void moveItemsBetweenStacks(ItemStack stack, ItemStack other) { @@ -117,10 +125,10 @@ index 190190463086f2fcbe28f00fa2f23795bf11f279..f6ec7accba090aac87eeefba333440ce if (min > 0) { other.grow(min); diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java -index 52a7ed0d991758bad0dcedcb7f97fb15ac6c6d04..d2d258246e7f7332c0420077e33c05e222bda46d 100644 +index 6c0ebfb2be4e8b884456a2aa3d5fdc87e45a0e3c..b0e60d1d2a44bb35c87c35e82a172a38406b6c54 100644 --- a/net/minecraft/world/entity/item/ItemEntity.java +++ b/net/minecraft/world/entity/item/ItemEntity.java -@@ -274,10 +274,52 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -281,10 +281,52 @@ public class ItemEntity extends Entity implements TraceableEntity { private boolean isMergable() { ItemStack item = this.getItem(); @@ -175,10 +183,10 @@ index 52a7ed0d991758bad0dcedcb7f97fb15ac6c6d04..d2d258246e7f7332c0420077e33c05e2 ItemStack item1 = itemEntity.getItem(); if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) { diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java -index 839cbb67d3d38960d9114a4db5bab911b66a573c..9b628d553d3206a4881ed5e07fa6d2552b710cea 100644 +index d9cb4f0ed0c4f63362c837aeef3c4194911455c9..57bf2819271b3293a065b58d31b609f8463811b4 100644 --- a/net/minecraft/world/entity/player/Inventory.java +++ b/net/minecraft/world/entity/player/Inventory.java -@@ -97,10 +97,12 @@ public class Inventory implements Container, Nameable { +@@ -148,10 +148,12 @@ public class Inventory implements Container, Nameable { } private boolean hasRemainingSpaceForItem(ItemStack destination, ItemStack origin) { @@ -193,7 +201,7 @@ index 839cbb67d3d38960d9114a4db5bab911b66a573c..9b628d553d3206a4881ed5e07fa6d255 } // CraftBukkit start - Watch method above! :D -@@ -113,7 +115,7 @@ public class Inventory implements Container, Nameable { +@@ -164,7 +166,7 @@ public class Inventory implements Container, Nameable { } if (this.hasRemainingSpaceForItem(itemInSlot, itemStack)) { @@ -202,16 +210,16 @@ index 839cbb67d3d38960d9114a4db5bab911b66a573c..9b628d553d3206a4881ed5e07fa6d255 } if (remains <= 0) { return itemStack.getCount(); -@@ -122,7 +124,7 @@ public class Inventory implements Container, Nameable { +@@ -173,7 +175,7 @@ public class Inventory implements Container, Nameable { - ItemStack itemInOffhand = this.getItem(this.items.size() + this.armor.size()); + ItemStack itemInOffhand = this.equipment.get(EquipmentSlot.OFFHAND); if (this.hasRemainingSpaceForItem(itemInOffhand, itemStack)) { - remains -= (itemInOffhand.getMaxStackSize() < this.getMaxStackSize() ? itemInOffhand.getMaxStackSize() : this.getMaxStackSize()) - itemInOffhand.getCount(); + remains -= (org.leavesmc.leaves.util.ShulkerBoxUtils.getItemStackMaxCount(itemInOffhand) < this.getMaxStackSize() ? org.leavesmc.leaves.util.ShulkerBoxUtils.getItemStackMaxCount(itemInOffhand) : this.getMaxStackSize()) - itemInOffhand.getCount(); // Leaves - stackable shulker boxes } if (remains <= 0) { return itemStack.getCount(); -@@ -252,7 +254,7 @@ public class Inventory implements Container, Nameable { +@@ -297,7 +299,7 @@ public class Inventory implements Container, Nameable { this.setItem(slot, item); } @@ -220,7 +228,7 @@ index 839cbb67d3d38960d9114a4db5bab911b66a573c..9b628d553d3206a4881ed5e07fa6d255 int min = Math.min(count, i); if (min == 0) { return count; -@@ -359,7 +361,7 @@ public class Inventory implements Container, Nameable { +@@ -403,7 +405,7 @@ public class Inventory implements Container, Nameable { break; } @@ -243,10 +251,10 @@ index 83ccde54c625d40dc595e000c533f60aa929bd5a..1b92676459468d42931b84e5ceb19e8d public void accountStack(ItemStack stack, int maxStackSize) { diff --git a/net/minecraft/world/entity/vehicle/ContainerEntity.java b/net/minecraft/world/entity/vehicle/ContainerEntity.java -index c18aea2bb5ddddadbc858b253ff4c08d82178a18..6a24b442a21298ef3bdbcb76de9bdcf006890c5d 100644 +index feebd1610ebd3c26a337259c14f5c774dc72b937..7df6ff842e41763aec2d88d1f8a5f7503932d905 100644 --- a/net/minecraft/world/entity/vehicle/ContainerEntity.java +++ b/net/minecraft/world/entity/vehicle/ContainerEntity.java -@@ -164,7 +164,7 @@ public interface ContainerEntity extends Container, MenuProvider { +@@ -163,7 +163,7 @@ public interface ContainerEntity extends Container, MenuProvider { default void setChestVehicleItem(int slot, ItemStack stack) { this.unpackChestVehicleLootTable(null); this.getItemStacks().set(slot, stack); @@ -256,10 +264,24 @@ index c18aea2bb5ddddadbc858b253ff4c08d82178a18..6a24b442a21298ef3bdbcb76de9bdcf0 default SlotAccess getChestVehicleSlot(final int index) { diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index b4721c4e81cc2ae989765d86bd51ebf0be41758c..d03348c8139c398b65a2f4e4f960832c797e0443 100644 +index 2a4763c951ddc78c9d8a39e661e59bbffc5cf109..8aa689129334f75986fb7a18895e2c3fb3c365c8 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java -@@ -427,7 +427,7 @@ public abstract class AbstractContainerMenu { +@@ -271,6 +271,13 @@ public abstract class AbstractContainerMenu { + this.sendAllDataToRemote(); + } + ++ // Leaves start - stackable shulker boxes ++ public void sendSingleSlot(int slotIndex, ItemStack item) { ++ if (this.synchronizer != null) { ++ this.synchronizer.sendSlotChange(this, slotIndex, item); ++ } ++ } ++ // Leaves end - stackable shulker boxes + private void updateDataSlotListeners(int slotIndex, int value) { + for (ContainerListener containerListener : this.containerListeners) { + containerListener.dataChanged(this, slotIndex, value); +@@ -428,7 +435,7 @@ public abstract class AbstractContainerMenu { && (this.quickcraftType == 2 || carried1.getCount() >= this.quickcraftSlots.size()) && this.canDragTo(slot1)) { int i2 = slot1.hasItem() ? slot1.getItem().getCount() : 0; @@ -268,16 +290,16 @@ index b4721c4e81cc2ae989765d86bd51ebf0be41758c..d03348c8139c398b65a2f4e4f960832c int min1 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemStack) + i2, min); count -= min1 - i2; // slot1.setByPlayer(itemStack.copyWithCount(min1)); -@@ -541,7 +541,7 @@ public abstract class AbstractContainerMenu { +@@ -542,7 +549,7 @@ public abstract class AbstractContainerMenu { slot.setByPlayer(carried2); } } else if (ItemStack.isSameItemSameComponents(carried, carried2)) { - Optional optional1 = slot.tryRemove(carried.getCount(), carried2.getMaxStackSize() - carried2.getCount(), player); + Optional optional1 = slot.tryRemove(carried.getCount(), org.leavesmc.leaves.util.ShulkerBoxUtils.getItemStackMaxCount(carried2) - carried2.getCount(), player); // Leaves - stackable shulker boxes - optional1.ifPresent(stack -> { - carried2.grow(stack.getCount()); - slot.onTake(player, stack); -@@ -603,7 +603,7 @@ public abstract class AbstractContainerMenu { + optional1.ifPresent(itemStack2 -> { + carried2.grow(itemStack2.getCount()); + slot.onTake(player, itemStack2); +@@ -604,7 +611,7 @@ public abstract class AbstractContainerMenu { Slot slot2 = this.slots.get(slotId); if (slot2.hasItem()) { ItemStack itemStack = slot2.getItem(); @@ -286,7 +308,7 @@ index b4721c4e81cc2ae989765d86bd51ebf0be41758c..d03348c8139c398b65a2f4e4f960832c } } else if (clickType == ClickType.THROW && this.getCarried().isEmpty() && slotId >= 0) { Slot slot2 = this.slots.get(slotId); -@@ -634,15 +634,15 @@ public abstract class AbstractContainerMenu { +@@ -635,15 +642,15 @@ public abstract class AbstractContainerMenu { int maxStackSize = button == 0 ? 1 : -1; for (int i3 = 0; i3 < 2; i3++) { @@ -305,7 +327,7 @@ index b4721c4e81cc2ae989765d86bd51ebf0be41758c..d03348c8139c398b65a2f4e4f960832c itemStack.grow(itemStack1.getCount()); } } -@@ -760,7 +760,7 @@ public abstract class AbstractContainerMenu { +@@ -761,7 +768,7 @@ public abstract class AbstractContainerMenu { i = endIndex - 1; } @@ -314,7 +336,7 @@ index b4721c4e81cc2ae989765d86bd51ebf0be41758c..d03348c8139c398b65a2f4e4f960832c while (!stack.isEmpty() && (reverseDirection ? i >= startIndex : i < endIndex)) { Slot slot = this.slots.get(i); ItemStack item = slot.getItem(); -@@ -861,7 +861,7 @@ public abstract class AbstractContainerMenu { +@@ -862,7 +869,7 @@ public abstract class AbstractContainerMenu { public static boolean canItemQuickReplace(@Nullable Slot slot, ItemStack stack, boolean stackSizeMatters) { boolean flag = slot == null || !slot.hasItem(); return !flag && ItemStack.isSameItemSameComponents(stack, slot.getItem()) @@ -323,7 +345,7 @@ index b4721c4e81cc2ae989765d86bd51ebf0be41758c..d03348c8139c398b65a2f4e4f960832c : flag; } -@@ -869,7 +869,7 @@ public abstract class AbstractContainerMenu { +@@ -870,7 +877,7 @@ public abstract class AbstractContainerMenu { return switch (type) { case 0 -> Mth.floor((float)stack.getCount() / slots.size()); case 1 -> 1; @@ -332,7 +354,7 @@ index b4721c4e81cc2ae989765d86bd51ebf0be41758c..d03348c8139c398b65a2f4e4f960832c default -> stack.getCount(); }; } -@@ -891,7 +891,7 @@ public abstract class AbstractContainerMenu { +@@ -892,7 +899,7 @@ public abstract class AbstractContainerMenu { for (int i = 0; i < container.getContainerSize(); i++) { ItemStack item = container.getItem(i); if (!item.isEmpty()) { @@ -342,7 +364,7 @@ index b4721c4e81cc2ae989765d86bd51ebf0be41758c..d03348c8139c398b65a2f4e4f960832c } diff --git a/net/minecraft/world/inventory/MerchantContainer.java b/net/minecraft/world/inventory/MerchantContainer.java -index a1576c3be00bdb19d02d52658c4b1818ea5c32db..be2f047bf1daab82473105865cd95955d4661a2a 100644 +index 1e5dfb1f9e371fa23cdfa9280797aa0e183d4cd2..cf87267130c0aebd38206556261929d6f6383bc9 100644 --- a/net/minecraft/world/inventory/MerchantContainer.java +++ b/net/minecraft/world/inventory/MerchantContainer.java @@ -109,7 +109,7 @@ public class MerchantContainer implements Container { @@ -368,34 +390,10 @@ index 5ceb8964476b40db4511bec91ff13c4f522a1357..371bad86218971d6e031c6d74307b2ab @Nullable diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index 76f50437396f8f856381d0fbef52953ef7c263f6..889a947cec81683cb7caa447dbf28b701fb38d0b 100644 +index 24ecca78dc1140b6fc47d59f2acefca6bc2b0220..649d17dcd7856e3b1344192d8ea4b2e9f73fc03b 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java -@@ -151,16 +151,19 @@ public final class ItemStack implements DataComponentHolder { - if (value.isEmpty() || value.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem() - buffer.writeVarInt(0); - } else { -- buffer.writeVarInt(io.papermc.paper.util.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.ItemObfuscationSession.currentSession(), value, value.getCount())); // Paper - potentially sanitize count -- ITEM_STREAM_CODEC.encode(buffer, value.getItemHolder()); -+ // Leaves start - stackable shulker boxes -+ final ItemStack itemStack = org.leavesmc.leaves.util.ShulkerBoxUtils.correctItemStackMaxStackSize(value.copy()); -+ buffer.writeVarInt(io.papermc.paper.util.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.ItemObfuscationSession.currentSession(), itemStack, itemStack.getCount())); // Paper - potentially sanitize count -+ ITEM_STREAM_CODEC.encode(buffer, itemStack.getItemHolder()); - // Spigot start - filter - // value = value.copy(); - // CraftItemStack.setItemMeta(value, CraftItemStack.getItemMeta(value)); // Paper - This is no longer with raw NBT being handled in metadata - // Paper start - adventure; conditionally render translatable components - boolean prev = net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.get(); -- try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.ItemObfuscationSession.withContext(c -> c.itemStack(value))) { // pass the itemstack as context to the obfuscation session -+ try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.ItemObfuscationSession.withContext(c -> c.itemStack(itemStack))) { // pass the itemstack as context to the obfuscation session // Leaves - stackable shulker boxes - net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true); -- DataComponentPatch.STREAM_CODEC.encode(buffer, value.components.asPatch()); -+ DataComponentPatch.STREAM_CODEC.encode(buffer, itemStack.components.asPatch()); -+ // Leaves end - stackable shulker boxes - } finally { - net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev); - } -@@ -199,7 +202,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -165,7 +165,7 @@ public final class ItemStack implements DataComponentHolder { @Deprecated @Nullable private Item item; @@ -404,7 +402,37 @@ index 76f50437396f8f856381d0fbef52953ef7c263f6..889a947cec81683cb7caa447dbf28b70 @Nullable private Entity entityRepresentation; -@@ -299,7 +302,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -192,7 +192,8 @@ public final class ItemStack implements DataComponentHolder { + } else { + Holder holder = Item.STREAM_CODEC.decode(buffer); + DataComponentPatch dataComponentPatch = codec.decode(buffer); +- return new ItemStack(holder, varInt, dataComponentPatch); ++ ItemStack itemStack = new ItemStack(holder, varInt, dataComponentPatch); ++ return org.leavesmc.leaves.util.ShulkerBoxUtils.decodeMaxStackSize(itemStack); + } + } + +@@ -201,13 +202,15 @@ public final class ItemStack implements DataComponentHolder { + if (value.isEmpty() || value.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem() + buffer.writeVarInt(0); + } else { +- buffer.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), value, value.getCount())); // Paper - potentially sanitize count +- Item.STREAM_CODEC.encode(buffer, value.getItemHolder()); ++ // Leaves start - stackable shulker boxes ++ final ItemStack itemStack = org.leavesmc.leaves.util.ShulkerBoxUtils.encodeMaxStackSize(value.copy()); ++ buffer.writeVarInt(io.papermc.paper.util.sanitizer.ItemComponentSanitizer.sanitizeCount(io.papermc.paper.util.sanitizer.ItemObfuscationSession.currentSession(), itemStack, itemStack.getCount())); // Paper - potentially sanitize count ++ Item.STREAM_CODEC.encode(buffer, itemStack.getItemHolder()); + // Paper start - adventure; conditionally render translatable components + boolean prev = net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.get(); +- try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.itemStack(value))) { // pass the itemstack as context to the obfuscation session ++ try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.itemStack(itemStack))) { // pass the itemstack as context to the obfuscation session + net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true); +- codec.encode(buffer, value.components.asPatch()); ++ codec.encode(buffer, itemStack.components.asPatch()); + } finally { + net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev); + } +@@ -302,7 +305,7 @@ public final class ItemStack implements DataComponentHolder { for (ItemStack itemStack : itemContainerContents.nonEmptyItems()) { int count = itemStack.getCount(); @@ -414,10 +442,10 @@ index 76f50437396f8f856381d0fbef52953ef7c263f6..889a947cec81683cb7caa447dbf28b70 return DataResult.error(() -> "Item stack with count of " + count + " was larger than maximum: " + maxStackSize); } diff --git a/net/minecraft/world/level/block/AbstractCauldronBlock.java b/net/minecraft/world/level/block/AbstractCauldronBlock.java -index 648d22cdfcf261494038d589f5a5e32704083076..47e480515715376f568b7cb7468edf2bff3d4307 100644 +index ad3f32888afd8b5f0038445a1b0fcc8cacec9fe2..18b7b7fe68c54a400f269f5ff1d09fe9e3d519b8 100644 --- a/net/minecraft/world/level/block/AbstractCauldronBlock.java +++ b/net/minecraft/world/level/block/AbstractCauldronBlock.java -@@ -58,9 +58,27 @@ public abstract class AbstractCauldronBlock extends Block { +@@ -62,9 +62,27 @@ public abstract class AbstractCauldronBlock extends Block { ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult ) { CauldronInteraction cauldronInteraction = this.interactions.map().get(stack.getItem()); @@ -447,10 +475,10 @@ index 648d22cdfcf261494038d589f5a5e32704083076..47e480515715376f568b7cb7468edf2b protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { return SHAPE; diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java -index 5f5966278faf86ed9b28955c80ba845c0cb75595..dcc503b3dca65ec2a72f6f3dc29589c6c295b181 100644 +index 38b03c7b02bdfc579e5e126c12de3d878e26d188..33e24f2c3b63b2d3b55dfae2f2e55869abeed055 100644 --- a/net/minecraft/world/level/block/CrafterBlock.java +++ b/net/minecraft/world/level/block/CrafterBlock.java -@@ -200,7 +200,7 @@ public class CrafterBlock extends BaseEntityBlock { +@@ -192,7 +192,7 @@ public class CrafterBlock extends BaseEntityBlock { Direction direction = state.getValue(ORIENTATION).front(); Container containerAt = HopperBlockEntity.getContainerAt(level, pos.relative(direction)); ItemStack itemStack = stack.copy(); @@ -460,10 +488,10 @@ index 5f5966278faf86ed9b28955c80ba845c0cb75595..dcc503b3dca65ec2a72f6f3dc29589c6 org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack); diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 77e7188180cce9ef881de64b263c704b219b610a..2f5fa4310f475ecbb29e69c0461c7d3276f8536d 100644 +index 7729c33cad94cf2b4162324be75713650fc9d378..78b3bdb668320e9cf2fb09b59929fac43cf56aca 100644 --- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -414,7 +414,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -409,7 +409,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit ItemStack itemStack = this.items.get(index); boolean flag = !stack.isEmpty() && ItemStack.isSameItemSameComponents(itemStack, stack); this.items.set(index, stack); @@ -473,10 +501,10 @@ index 77e7188180cce9ef881de64b263c704b219b610a..2f5fa4310f475ecbb29e69c0461c7d32 this.cookingTotalTime = getTotalCookTime(serverLevel, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API this.cookingTimer = 0; diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -index 26db603ed681a6c302596627d4dd5bf8a9bafc4e..9fcb70b5bf1912a5499aa7daeaa089adbe60cc55 100644 +index c63370fd458fb4f7190b79b1a8174fcc92d88f9c..4cca3fbbb93bb76d5d501dfad6997d909211809e 100644 --- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -@@ -146,7 +146,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co +@@ -148,7 +148,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co @Override public void setItem(int slot, ItemStack stack) { this.getItems().set(slot, stack); @@ -486,10 +514,10 @@ index 26db603ed681a6c302596627d4dd5bf8a9bafc4e..9fcb70b5bf1912a5499aa7daeaa089ad } diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 42a29e700d2549de7cd905c373212e9757bcfcf1..3122753c96e98e57fa900cd15005ab4874e4b1db 100644 +index 2d979850378c05ce569782d8e04a452f986612a7..a2fe5fdf50ae731e423821a0d1c52141b478e0be 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -109,7 +109,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -113,7 +113,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen public void setItem(int index, ItemStack stack) { this.unpackLootTable(null); this.getItems().set(index, stack); @@ -498,7 +526,7 @@ index 42a29e700d2549de7cd905c373212e9757bcfcf1..3122753c96e98e57fa900cd15005ab48 } @Override -@@ -688,9 +688,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -692,9 +692,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen if (item.isEmpty()) { // Spigot start - SPIGOT-6693, SimpleContainer#setItem ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size diff --git a/leaves-server/minecraft-patches/features/0034-Return-nether-portal-fix.patch b/leaves-server/minecraft-patches/features/0035-Return-nether-portal-fix.patch similarity index 90% rename from leaves-server/minecraft-patches/features/0034-Return-nether-portal-fix.patch rename to leaves-server/minecraft-patches/features/0035-Return-nether-portal-fix.patch index 47ed7f93..a2601394 100644 --- a/leaves-server/minecraft-patches/features/0034-Return-nether-portal-fix.patch +++ b/leaves-server/minecraft-patches/features/0035-Return-nether-portal-fix.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Return nether portal fix This patch is powered by NetherPortalFix(https://github.com/TwelveIterationMods/NetherPortalFix) diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 0df1160ce4e027cc1c1bf7071a4d8730aaa7fde6..eba1717566a8ea534bbf149e0593cc7656df2db9 100644 +index 66110486725de7967e55839043b9fc9690e4c0f5..f144a8bd5eb55ce093ad92ffd1304860dc52c1b1 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -1484,6 +1484,21 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1428,6 +1428,21 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc org.bukkit.event.player.PlayerChangedWorldEvent changeEvent = new org.bukkit.event.player.PlayerChangedWorldEvent(this.getBukkitEntity(), serverLevel.getWorld()); this.level().getCraftServer().getPluginManager().callEvent(changeEvent); // CraftBukkit end @@ -32,10 +32,10 @@ index 0df1160ce4e027cc1c1bf7071a4d8730aaa7fde6..eba1717566a8ea534bbf149e0593cc76 if (this.isBlocking()) { this.stopUsingItem(); diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index a79f83991aa50d45695beeeb018f203c6d7ae6d8..46d93b9c063cb056f3051ebe0f3558f5b4f55bea 100644 +index b4a4ba86fd6023db33b2ee9cb02ec41f9733a813..3b612c02ddbf25c6dcfe5df14fca027986e6f252 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -852,6 +852,20 @@ public abstract class PlayerList { +@@ -860,6 +860,20 @@ public abstract class PlayerList { if (fromWorld != level) { org.bukkit.event.player.PlayerChangedWorldEvent event = new org.bukkit.event.player.PlayerChangedWorldEvent(player.getBukkitEntity(), fromWorld.getWorld()); this.server.server.getPluginManager().callEvent(event); @@ -57,10 +57,10 @@ index a79f83991aa50d45695beeeb018f203c6d7ae6d8..46d93b9c063cb056f3051ebe0f3558f5 // Save player file again if they were disconnected diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 35a00a30a726294d6c6e3d879cfec9fcc7d10028..d1f25cc8efe38b152bb1a0e8886c8024da3ba840 100644 +index 108430b3934a6f9757e7be50d77e760bbade669c..6893ca36cd4ae9a62fecedb1167cc6cf797a7f8f 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -274,7 +274,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -245,7 +245,7 @@ public abstract class LivingEntity extends Entity implements Attackable { protected ItemStack useItem = ItemStack.EMPTY; public int useItemRemaining; protected int fallFlyTicks; @@ -70,10 +70,10 @@ index 35a00a30a726294d6c6e3d879cfec9fcc7d10028..d1f25cc8efe38b152bb1a0e8886c8024 @Nullable private DamageSource lastDamageSource; diff --git a/net/minecraft/world/level/block/NetherPortalBlock.java b/net/minecraft/world/level/block/NetherPortalBlock.java -index e2eb693b0130513115392cb0cb5a829ede5be8c5..fd6e228e5943c7004a595b5e154b7606ed330ea5 100644 +index 2f08780430fc643991ffb4aeba1f1ae8e78944d2..171b383efabbbe849aff28832c47076f85a46307 100644 --- a/net/minecraft/world/level/block/NetherPortalBlock.java +++ b/net/minecraft/world/level/block/NetherPortalBlock.java -@@ -183,7 +183,18 @@ public class NetherPortalBlock extends Block implements Portal { +@@ -184,7 +184,18 @@ public class NetherPortalBlock extends Block implements Portal { @Nullable private TeleportTransition getExitPortal(ServerLevel level, Entity entity, BlockPos pos, BlockPos exitPos, boolean isNether, WorldBorder worldBorder, int searchRadius, boolean canCreatePortal, int createRadius) { // CraftBukkit diff --git a/leaves-server/minecraft-patches/features/0035-Leaves-Extra-Yggdrasil-Service.patch b/leaves-server/minecraft-patches/features/0036-Leaves-Extra-Yggdrasil-Service.patch similarity index 91% rename from leaves-server/minecraft-patches/features/0035-Leaves-Extra-Yggdrasil-Service.patch rename to leaves-server/minecraft-patches/features/0036-Leaves-Extra-Yggdrasil-Service.patch index 5d04a2d0..576f4353 100644 --- a/leaves-server/minecraft-patches/features/0035-Leaves-Extra-Yggdrasil-Service.patch +++ b/leaves-server/minecraft-patches/features/0036-Leaves-Extra-Yggdrasil-Service.patch @@ -18,7 +18,7 @@ index 8c3151c25c172b846f0d028b5100718ada2d09d7..d59d05f8894481fb5ebe1aeb8ee7a162 private final String baseUrl; private final URL joinUrl; diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java -index 9aa664537cc37e44db46d5a2a64ae3116938c681..1a5a8ad60240c0864875f6314e01adab4a283ddf 100644 +index 9c9b601a3f903bebb0dd1bda0e24745587229727..4cde785a679dccc3dfa42272e6094328e9ce98c1 100644 --- a/net/minecraft/server/Main.java +++ b/net/minecraft/server/Main.java @@ -177,7 +177,7 @@ public class Main { @@ -31,10 +31,10 @@ index 9aa664537cc37e44db46d5a2a64ae3116938c681..1a5a8ad60240c0864875f6314e01adab String string = Optional.ofNullable((String) optionSet.valueOf("world")).orElse(dedicatedServerSettings.getProperties().levelName); LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(file.toPath()); diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 09fc1c1923f7cc4470cca3b703810fb165c4ca15..1ce3afe6c3e3b7c0aad2706215d75a265d892070 100644 +index 105c207b8db2c505f256f4104642af5929b50aa9..50f73905e6785d87a0faf886802d956a1c7b9751 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -245,7 +245,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ca.spottedleaf.moonrise.patch + if (ret != null) { + return ret; + } ++ if (org.leavesmc.leaves.LeavesConfig.modify.updateSuppressionCrashFix) throw new org.leavesmc.leaves.util.UpdateSuppressionException(null, null); // Leaves - fix update suppression crash + throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner); + // Paper end - optimise blockstate property access + } +diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java +index bf731da711ce629c0f9250a7bd4025d363623773..845319dd3e355f739cce70b7df3172dd146601b1 100644 +--- a/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/net/minecraft/world/level/chunk/LevelChunk.java +@@ -371,7 +371,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p + if (blockState == state) { + return null; + } else { +- Block block = state.getBlock(); ++ Block block = state.getBlock(); try { // Leaves start - fix update suppression crash + this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(i, y, i2, state); + this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(i, y, i2, state); + this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(i, y, i2, state); +@@ -443,6 +443,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p + this.markUnsaved(); + return blockState; + } ++ } catch (org.leavesmc.leaves.util.UpdateSuppressionException e) {throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, block);} // Leaves end - fix update suppression crash + } + } + } diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java -index 26c15c60d358273a3b369c286771c81d6f0979dd..1c75e37bf1fa2cc5d80add2bcf00b95defd0079d 100644 +index 332b33a004ab11150cca0cc2cefc26d0286648f5..263bf2b795057c2d5218bf9cfb684e526601aa77 100644 --- a/net/minecraft/world/level/redstone/NeighborUpdater.java +++ b/net/minecraft/world/level/redstone/NeighborUpdater.java -@@ -63,9 +63,17 @@ public interface NeighborUpdater { +@@ -60,9 +60,17 @@ public interface NeighborUpdater { state.handleNeighborChanged(level, pos, neighborBlock, orientation, movedByPiston); // Spigot start } catch (StackOverflowError ex) { @@ -69,7 +102,7 @@ index 26c15c60d358273a3b369c286771c81d6f0979dd..1c75e37bf1fa2cc5d80add2bcf00b95d + if (org.leavesmc.leaves.LeavesConfig.modify.updateSuppressionCrashFix) { + throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, neighborBlock); + } - level.lastPhysicsProblem = new BlockPos(pos); + level.lastPhysicsProblem = pos.immutable(); // Spigot end } catch (Throwable var9) { + if (org.leavesmc.leaves.LeavesConfig.modify.updateSuppressionCrashFix) { diff --git a/leaves-server/minecraft-patches/features/0038-Bedrock-break-list.patch b/leaves-server/minecraft-patches/features/0039-Bedrock-break-list.patch similarity index 84% rename from leaves-server/minecraft-patches/features/0038-Bedrock-break-list.patch rename to leaves-server/minecraft-patches/features/0039-Bedrock-break-list.patch index 2a3f80b1..521fd8e8 100644 --- a/leaves-server/minecraft-patches/features/0038-Bedrock-break-list.patch +++ b/leaves-server/minecraft-patches/features/0039-Bedrock-break-list.patch @@ -5,22 +5,22 @@ Subject: [PATCH] Bedrock break list diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index de9b2b92456466376186737914706df22e1578f5..7822cecf362cd8d430d90c0daac6e97c8a8d124b 100644 +index f12b397901c0a2f779221e6694cecaced7069c9e..ca4fdcabbe6c0c57bfa13ef6d83bcd560baae8fc 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1754,6 +1754,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; } // CraftBukkit end @@ -16,16 +16,16 @@ index 46c23990e78ce77b188052672778bdef560a0d13..c6aad768cad0f0eccbe5405f41c4fa34 + /* Leaves - it is feature, not bug! // Paper start - break redstone on trapdoors early boolean open = state.getValue(TrapDoorBlock.OPEN) != hasNeighborSignal; - // note: this must run before any state for this block/its neighborus are written to the world -@@ -178,8 +180,9 @@ public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleW + // note: this must run before any state for this block/its neighbours are written to the world +@@ -157,8 +159,9 @@ public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleW } } } - if (open) { -- // Paper end - break redstone on trapdoors early +- // Paper end - break redstone on trapdoors early + */ + + if (state.getValue(TrapDoorBlock.OPEN) != hasNeighborSignal) { - state = state.setValue(OPEN, Boolean.valueOf(hasNeighborSignal)); + state = state.setValue(OPEN, hasNeighborSignal); this.playSound(null, level, pos, hasNeighborSignal); } diff --git a/leaves-server/minecraft-patches/features/0040-Disable-distance-check-for-UseItemOnPacket.patch b/leaves-server/minecraft-patches/features/0041-Disable-distance-check-for-UseItemOnPacket.patch similarity index 88% rename from leaves-server/minecraft-patches/features/0040-Disable-distance-check-for-UseItemOnPacket.patch rename to leaves-server/minecraft-patches/features/0041-Disable-distance-check-for-UseItemOnPacket.patch index 3f91428d..c6748471 100644 --- a/leaves-server/minecraft-patches/features/0040-Disable-distance-check-for-UseItemOnPacket.patch +++ b/leaves-server/minecraft-patches/features/0041-Disable-distance-check-for-UseItemOnPacket.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Disable distance check for UseItemOnPacket diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 771abbc4aeea227b99b069d9d6f58a6b8df4ee5d..19d8998ca4e2a61bcc5c33b2a6fff6ee8deb56c4 100644 +index 72e1265509a00376515e963499099c0765104ea2..878d80d0cb9fddeb7916a34d39c34119d65fbe00 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1929,7 +1929,7 @@ public class ServerGamePacketListenerImpl +@@ -1991,7 +1991,7 @@ public class ServerGamePacketListenerImpl if (this.player.canInteractWithBlock(blockPos, 1.0)) { Vec3 vec3 = location.subtract(Vec3.atCenterOf(blockPos)); double d = 1.0000001; diff --git a/leaves-server/minecraft-patches/features/0041-No-feather-falling-trample.patch b/leaves-server/minecraft-patches/features/0042-No-feather-falling-trample.patch similarity index 93% rename from leaves-server/minecraft-patches/features/0041-No-feather-falling-trample.patch rename to leaves-server/minecraft-patches/features/0042-No-feather-falling-trample.patch index 0c682f35..4ba5e30b 100644 --- a/leaves-server/minecraft-patches/features/0041-No-feather-falling-trample.patch +++ b/leaves-server/minecraft-patches/features/0042-No-feather-falling-trample.patch @@ -5,7 +5,7 @@ Subject: [PATCH] No feather falling trample diff --git a/net/minecraft/world/level/block/FarmBlock.java b/net/minecraft/world/level/block/FarmBlock.java -index 47c9b32c89e7e6f84a279c2f6098ada77dc58b6b..9aafef742de9e833cc772da679127cd02cb8c1cb 100644 +index a31ac95237515b874f59941ec24c74e2c357b3d8..d18a4a7a41bc3a685f9621f9e6f5480bd0d390bc 100644 --- a/net/minecraft/world/level/block/FarmBlock.java +++ b/net/minecraft/world/level/block/FarmBlock.java @@ -116,6 +116,13 @@ public class FarmBlock extends Block { diff --git a/leaves-server/minecraft-patches/features/0119-Disable-packet-limit.patch b/leaves-server/minecraft-patches/features/0043-Disable-packet-limit.patch similarity index 89% rename from leaves-server/minecraft-patches/features/0119-Disable-packet-limit.patch rename to leaves-server/minecraft-patches/features/0043-Disable-packet-limit.patch index 5e9fe6ed..3ebeac0e 100644 --- a/leaves-server/minecraft-patches/features/0119-Disable-packet-limit.patch +++ b/leaves-server/minecraft-patches/features/0043-Disable-packet-limit.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Disable packet limit diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java -index fd490f139e901c2ac598f1eab7aa8d50c65ef864..284cdbd6034ec8962409abba6da37eab311018cc 100644 +index 364ddf9f25ef3cb97ba788c469fee9dd495b84a7..7af8b2cf9ccfeadac1cc60541da31ba6f4dc0edb 100644 --- a/net/minecraft/network/Connection.java +++ b/net/minecraft/network/Connection.java -@@ -244,8 +244,8 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -243,8 +243,8 @@ public class Connection extends SimpleChannelInboundHandler> { if (this.stopReadingPackets) { return; } @@ -20,10 +20,10 @@ index fd490f139e901c2ac598f1eab7aa8d50c65ef864..284cdbd6034ec8962409abba6da37eab synchronized (PACKET_LIMIT_LOCK) { if (this.allPacketCounts != null) { diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index a2c35011153daa3b171119b9c0b2e71a7f9a1788..a2be014d33d9ac6189fb7a79af674f2db0fe27cf 100644 +index 878d80d0cb9fddeb7916a34d39c34119d65fbe00..2ed38800fb3e3a1f4fb04c781321c642e402a854 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -791,7 +791,7 @@ public class ServerGamePacketListenerImpl +@@ -780,7 +780,7 @@ public class ServerGamePacketListenerImpl public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async // CraftBukkit start @@ -32,7 +32,7 @@ index a2c35011153daa3b171119b9c0b2e71a7f9a1788..a2be014d33d9ac6189fb7a79af674f2d this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - Kick event cause // Paper - add proper async disconnect return; } -@@ -1897,6 +1897,7 @@ public class ServerGamePacketListenerImpl +@@ -1955,6 +1955,7 @@ public class ServerGamePacketListenerImpl private static int getSpamThreshold() { return io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.incomingPacketThreshold; } // Paper - Configurable threshold private boolean checkLimit(long timestamp) { @@ -40,7 +40,7 @@ index a2c35011153daa3b171119b9c0b2e71a7f9a1788..a2be014d33d9ac6189fb7a79af674f2d if (this.lastLimitedPacket != -1 && timestamp - this.lastLimitedPacket < getSpamThreshold() && this.limitedPackets++ >= 8) { // Paper - Configurable threshold; raise packet limit to 8 return false; } -@@ -2511,6 +2512,7 @@ public class ServerGamePacketListenerImpl +@@ -2492,6 +2493,7 @@ public class ServerGamePacketListenerImpl // Spigot start - spam exclusions private void detectRateSpam(String message) { @@ -48,7 +48,7 @@ index a2c35011153daa3b171119b9c0b2e71a7f9a1788..a2be014d33d9ac6189fb7a79af674f2d // CraftBukkit start - replaced with thread safe throttle if (org.spigotmc.SpigotConfig.enableSpamExclusions) { for (String exclude : org.spigotmc.SpigotConfig.spamExclusions) { -@@ -3298,7 +3300,7 @@ public class ServerGamePacketListenerImpl +@@ -3280,7 +3282,7 @@ public class ServerGamePacketListenerImpl @Override public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { // Paper start - auto recipe limit diff --git a/leaves-server/minecraft-patches/features/0044-Redstone-wire-dont-connect-if-on-trapdoor.patch b/leaves-server/minecraft-patches/features/0044-Redstone-wire-dont-connect-if-on-trapdoor.patch deleted file mode 100644 index d1841f13..00000000 --- a/leaves-server/minecraft-patches/features/0044-Redstone-wire-dont-connect-if-on-trapdoor.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Wed, 14 Jun 2023 12:07:07 +0800 -Subject: [PATCH] Redstone wire dont connect if on trapdoor - - -diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java -index 12c9d60314c99fb65e640d255a2d0c6b7790ad4d..ff29671f78a4e896e70daf89f440f3b9425b0760 100644 ---- a/net/minecraft/world/level/block/RedStoneWireBlock.java -+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java -@@ -204,7 +204,7 @@ public class RedStoneWireBlock extends Block { - RandomSource random - ) { - if (direction == Direction.DOWN) { -- return !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state; -+ return org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.redstoneDontCantOnTrapDoor ? state : !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state; // Leaves - behavior to 1.19 - } else if (direction == Direction.UP) { - return this.getConnectionState(level, state, pos); - } else { -@@ -263,7 +263,7 @@ public class RedStoneWireBlock extends Block { - BlockPos blockPos = pos.relative(direction); - BlockState blockState = level.getBlockState(blockPos); - if (nonNormalCubeAbove) { -- boolean flag = blockState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, blockPos, blockState); -+ boolean flag = (!org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.redstoneDontCantOnTrapDoor && blockState.getBlock() instanceof TrapDoorBlock) || this.canSurviveOn(level, blockPos, blockState); // Leaves - behavior to 1.19 - if (flag && shouldConnectTo(level.getBlockState(blockPos.above()))) { - if (blockState.isFaceSturdy(level, blockPos, direction.getOpposite())) { - return RedstoneSide.UP; diff --git a/leaves-server/minecraft-patches/features/0042-Syncmatica-Protocol.patch b/leaves-server/minecraft-patches/features/0044-Syncmatica-Protocol.patch similarity index 89% rename from leaves-server/minecraft-patches/features/0042-Syncmatica-Protocol.patch rename to leaves-server/minecraft-patches/features/0044-Syncmatica-Protocol.patch index 52d76b3d..f6dc636e 100644 --- a/leaves-server/minecraft-patches/features/0042-Syncmatica-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0044-Syncmatica-Protocol.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Syncmatica Protocol This patch is Powered by Syncmatica(https://github.com/End-Tech/syncmatica) diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 19d8998ca4e2a61bcc5c33b2a6fff6ee8deb56c4..325300e7ad68b7ad377ff1269bc5d568d663ec3a 100644 +index 2f4776fa065cb712afe9d8abc835c57777c963b7..f1372015cf5991ef80a07e7fcbd1fb9d65e9d74f 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -326,8 +326,11 @@ public class ServerGamePacketListenerImpl +@@ -319,8 +319,11 @@ public class ServerGamePacketListenerImpl this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(player.getUUID(), server::enforceSecureProfile); this.chatMessageChain = new FutureChain(server.chatExecutor); // CraftBukkit - async chat this.tickEndEvent = new io.papermc.paper.event.packet.ClientTickEndEvent(player.getBukkitEntity()); // Paper - add client tick end event diff --git a/leaves-server/minecraft-patches/features/0043-Shared-villager-discounts.patch b/leaves-server/minecraft-patches/features/0045-Shared-villager-discounts.patch similarity index 90% rename from leaves-server/minecraft-patches/features/0043-Shared-villager-discounts.patch rename to leaves-server/minecraft-patches/features/0045-Shared-villager-discounts.patch index 43483dbc..b94a4a26 100644 --- a/leaves-server/minecraft-patches/features/0043-Shared-villager-discounts.patch +++ b/leaves-server/minecraft-patches/features/0045-Shared-villager-discounts.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Shared villager discounts diff --git a/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/net/minecraft/world/entity/ai/gossip/GossipContainer.java -index b74a4ce1b629d440681a1f5c026997ccaf1d0373..4eb97c8265ed8346b208d06a37f8068004593944 100644 +index 425ca1931fb0a5c33ba7aaf4f639409c9fea836f..c17ba3f76069f23b38de2aabf29b784049059144 100644 --- a/net/minecraft/world/entity/ai/gossip/GossipContainer.java +++ b/net/minecraft/world/entity/ai/gossip/GossipContainer.java -@@ -115,6 +115,16 @@ public class GossipContainer { +@@ -121,6 +121,16 @@ public class GossipContainer { public int getReputation(UUID identifier, Predicate gossip) { GossipContainer.EntityGossips entityGossips = this.gossips.get(identifier); diff --git a/leaves-server/minecraft-patches/features/0046-Redstone-ignore-upwards-update.patch b/leaves-server/minecraft-patches/features/0046-Redstone-ignore-upwards-update.patch new file mode 100644 index 00000000..3d02f0f4 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0046-Redstone-ignore-upwards-update.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: violetc <58360096+s-yh-china@users.noreply.github.com> +Date: Wed, 14 Jun 2023 12:07:07 +0800 +Subject: [PATCH] Redstone ignore upwards update + + +diff --git a/net/minecraft/world/level/block/ComparatorBlock.java b/net/minecraft/world/level/block/ComparatorBlock.java +index afecf6bb6152b4d9dfee4cd8c5b1d798cbf723b3..0e51c10987a7b1964d1be3b2942c28aa6b0eb8d9 100644 +--- a/net/minecraft/world/level/block/ComparatorBlock.java ++++ b/net/minecraft/world/level/block/ComparatorBlock.java +@@ -58,6 +58,7 @@ public class ComparatorBlock extends DiodeBlock implements EntityBlock { + BlockState neighborState, + RandomSource random + ) { ++ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.redstoneIgnoreUpwardsUpdate && direction == Direction.DOWN) return state; // Leaves - behavior to 1.20.1 + return direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState) + ? Blocks.AIR.defaultBlockState() + : super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random); +diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java +index 1943a6aad888647953e2d9dbbeedb0bd81c6f9df..35dc47d5ba1a2659304ccc08010611438ccf04d8 100644 +--- a/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/net/minecraft/world/level/block/RedStoneWireBlock.java +@@ -179,7 +179,7 @@ public class RedStoneWireBlock extends Block { + RandomSource random + ) { + if (direction == Direction.DOWN) { +- return !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state; ++ return org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.redstoneIgnoreUpwardsUpdate ? state : !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state; // Leaves - behavior to 1.19 + } else if (direction == Direction.UP) { + return this.getConnectionState(level, state, pos); + } else { +@@ -238,7 +238,7 @@ public class RedStoneWireBlock extends Block { + BlockPos blockPos = pos.relative(direction); + BlockState blockState = level.getBlockState(blockPos); + if (nonNormalCubeAbove) { +- boolean flag = blockState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, blockPos, blockState); ++ boolean flag = (!org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.redstoneIgnoreUpwardsUpdate && blockState.getBlock() instanceof TrapDoorBlock) || this.canSurviveOn(level, blockPos, blockState); // Leaves - behavior to 1.19 + if (flag && shouldConnectTo(level.getBlockState(blockPos.above()))) { + if (blockState.isFaceSturdy(level, blockPos, direction.getOpposite())) { + return RedstoneSide.UP; +diff --git a/net/minecraft/world/level/block/RepeaterBlock.java b/net/minecraft/world/level/block/RepeaterBlock.java +index 1d45564253258eebdf10470dd7eefa644a4151ae..13c1974dd368579f5c3d11b87e1c3eff02d69ac7 100644 +--- a/net/minecraft/world/level/block/RepeaterBlock.java ++++ b/net/minecraft/world/level/block/RepeaterBlock.java +@@ -68,6 +68,7 @@ public class RepeaterBlock extends DiodeBlock { + BlockState neighborState, + RandomSource random + ) { ++ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.redstoneIgnoreUpwardsUpdate && direction == Direction.DOWN) return state; // Leaves - behavior to 1.20.1 + if (direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState)) { + return Blocks.AIR.defaultBlockState(); + } else { diff --git a/leaves-server/minecraft-patches/features/0045-Disable-check-out-of-order-command.patch b/leaves-server/minecraft-patches/features/0047-Disable-check-out-of-order-command.patch similarity index 100% rename from leaves-server/minecraft-patches/features/0045-Disable-check-out-of-order-command.patch rename to leaves-server/minecraft-patches/features/0047-Disable-check-out-of-order-command.patch diff --git a/leaves-server/minecraft-patches/features/0046-Despawn-enderman-with-block.patch b/leaves-server/minecraft-patches/features/0048-Despawn-enderman-with-block.patch similarity index 84% rename from leaves-server/minecraft-patches/features/0046-Despawn-enderman-with-block.patch rename to leaves-server/minecraft-patches/features/0048-Despawn-enderman-with-block.patch index 540183f3..52f07387 100644 --- a/leaves-server/minecraft-patches/features/0046-Despawn-enderman-with-block.patch +++ b/leaves-server/minecraft-patches/features/0048-Despawn-enderman-with-block.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Despawn enderman with block diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java -index e2f1623b977889d31407d060b8e0bf911a80049e..a2437f181602cc334dc8b590c1b63565b2e67054 100644 +index 41c8fc535e7f0bd61e23f48ac250f362807fa062..775466831746b914947cd018d8def4b8bf1d6f15 100644 --- a/net/minecraft/world/entity/monster/EnderMan.java +++ b/net/minecraft/world/entity/monster/EnderMan.java -@@ -457,7 +457,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -452,7 +452,7 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean requiresCustomPersistence() { diff --git a/leaves-server/minecraft-patches/features/0048-Optimized-dragon-respawn.patch b/leaves-server/minecraft-patches/features/0049-Optimized-dragon-respawn.patch similarity index 96% rename from leaves-server/minecraft-patches/features/0048-Optimized-dragon-respawn.patch rename to leaves-server/minecraft-patches/features/0049-Optimized-dragon-respawn.patch index 5ea3a0fb..20da66ef 100644 --- a/leaves-server/minecraft-patches/features/0048-Optimized-dragon-respawn.patch +++ b/leaves-server/minecraft-patches/features/0049-Optimized-dragon-respawn.patch @@ -18,10 +18,10 @@ index f7bb979f08634a7e1b77c59040f59fb5e11aafa5..3cad7d6bca9af77bace18bfd7cc013ac for (int i1 = 0; i1 < this.height; i1++) { for (int i2 = 0; i2 < this.depth; i2++) { diff --git a/net/minecraft/world/level/dimension/end/EndDragonFight.java b/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 6e7e87c32734b3aae354bc34459e5f207da5c78f..5a28a821bb401f8f1465b085c9ffda52ba9a0a9f 100644 +index 8ccd40c70e150bd5a8d89818c229258642f2349e..18a567b676f0bfcd725f19c5ed9e3fdbc8e65573 100644 --- a/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -274,8 +274,68 @@ public class EndDragonFight { +@@ -273,8 +273,68 @@ public class EndDragonFight { return false; } @@ -90,7 +90,7 @@ index 6e7e87c32734b3aae354bc34459e5f207da5c78f..5a28a821bb401f8f1465b085c9ffda52 ChunkPos chunkPos = new ChunkPos(this.origin); for (int i = -8 + chunkPos.x; i <= 8 + chunkPos.x; i++) { -@@ -571,6 +631,11 @@ public class EndDragonFight { +@@ -572,6 +632,11 @@ public class EndDragonFight { } public boolean respawnDragon(List crystals) { // CraftBukkit - return boolean diff --git a/leaves-server/minecraft-patches/features/0047-Creative-fly-no-clip.patch b/leaves-server/minecraft-patches/features/0050-Creative-fly-no-clip.patch similarity index 80% rename from leaves-server/minecraft-patches/features/0047-Creative-fly-no-clip.patch rename to leaves-server/minecraft-patches/features/0050-Creative-fly-no-clip.patch index 53d71b75..e5ff38d0 100644 --- a/leaves-server/minecraft-patches/features/0047-Creative-fly-no-clip.patch +++ b/leaves-server/minecraft-patches/features/0050-Creative-fly-no-clip.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Creative fly no clip diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 6fa522d6935c277f2fc35bb772aa7b18b4adf6e3..39fc3ea891947ddd102f992e7b6c62f9367849e7 100644 +index 2fe76bc1c26423ed5e39453ac1b27a2cc66b1f2e..3eb9a9f6d7f8d28d527941177a5faf2c97628594 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java -@@ -262,8 +262,8 @@ public abstract class Player extends LivingEntity { +@@ -277,8 +277,8 @@ public abstract class Player extends LivingEntity { @Override public void tick() { @@ -19,16 +19,16 @@ index 6fa522d6935c277f2fc35bb772aa7b18b4adf6e3..39fc3ea891947ddd102f992e7b6c62f9 this.setOnGround(false); } -@@ -470,7 +470,7 @@ public abstract class Player extends LivingEntity { - } - - Pose pose1; -- if (this.isSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(pose)) { -+ if (this.isCreativeFlyOrSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(pose)) { // Leaves - creative no clip - pose1 = pose; +@@ -471,7 +471,7 @@ public abstract class Player extends LivingEntity { + if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.SWIMMING)) { + Pose desiredPose = this.getDesiredPose(); + Pose pose; +- if (this.isSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(desiredPose)) { ++ if (this.isCreativeFlyOrSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(desiredPose)) { // Leaves - creative no clip + pose = desiredPose; } else if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.CROUCHING)) { - pose1 = Pose.CROUCHING; -@@ -604,7 +604,7 @@ public abstract class Player extends LivingEntity { + pose = Pose.CROUCHING; +@@ -614,7 +614,7 @@ public abstract class Player extends LivingEntity { } this.bob = this.bob + (f - this.bob) * 0.4F; @@ -37,9 +37,9 @@ index 6fa522d6935c277f2fc35bb772aa7b18b4adf6e3..39fc3ea891947ddd102f992e7b6c62f9 AABB aabb; if (this.isPassenger() && !this.getVehicle().isRemoved()) { aabb = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0, 0.0, 1.0); -@@ -2044,6 +2044,21 @@ public abstract class Player extends LivingEntity { - @Override - public abstract boolean isSpectator(); +@@ -1931,6 +1931,21 @@ public abstract class Player extends LivingEntity { + return this.gameMode() == GameType.SPECTATOR; + } + // Leaves start - creative no clip + public boolean isCreativeFlyOrSpectator() { @@ -60,18 +60,20 @@ index 6fa522d6935c277f2fc35bb772aa7b18b4adf6e3..39fc3ea891947ddd102f992e7b6c62f9 public boolean canBeHitByProjectile() { return !this.isSpectator() && super.canBeHitByProjectile(); diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java -index 1f4a3d2610abfa2ea2b1d5feba9606b806d6d416..c74e09eed6b8fe2852b3cb592e1a1e628ba9f22a 100644 +index 0c67e5481a43bf7c02bb54a8ea1abca77d53a292..5cbd5d04de525c33715bc45826bd2ed446355505 100644 --- a/net/minecraft/world/item/BlockItem.java +++ b/net/minecraft/world/item/BlockItem.java -@@ -216,7 +216,7 @@ public class BlockItem extends Item { - CollisionContext collisionContext = player == null ? CollisionContext.empty() : CollisionContext.of(player); +@@ -207,8 +207,9 @@ public class BlockItem extends Item { + protected boolean canPlace(BlockPlaceContext context, BlockState state) { + Player player = context.getPlayer(); // CraftBukkit start ++ CollisionContext collisionContext = player == null ? CollisionContext.empty() : CollisionContext.placementContext(player); Level world = context.getLevel(); // Paper - Cancel hit for vanished players -- boolean canBuild = (!this.mustSurvive() || state.canSurvive(world, context.getClickedPos())) && world.checkEntityCollision(state, player, collisionContext, context.getClickedPos(), true); // Paper - Cancel hit for vanished players +- boolean canBuild = (!this.mustSurvive() || state.canSurvive(world, context.getClickedPos())) && world.checkEntityCollision(state, player, CollisionContext.placementContext(player), context.getClickedPos(), true); // Paper - Cancel hit for vanished players + boolean canBuild = (!this.mustSurvive() || state.canSurvive(world, context.getClickedPos())) && ((org.leavesmc.leaves.LeavesConfig.modify.creativeNoClip && context.getPlayer() != null) ? context.getPlayer().canSpectatingPlace(world, state, context.getClickedPos(), collisionContext) : world.checkEntityCollision(state, player, collisionContext, context.getClickedPos(), true)); // Paper - Cancel hit for vanished players // Leaves - creative no clip org.bukkit.entity.Player bukkitPlayer = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; - BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, context.getClickedPos()), bukkitPlayer, CraftBlockData.fromData(state), canBuild, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent + org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent( diff --git a/net/minecraft/world/item/StandingAndWallBlockItem.java b/net/minecraft/world/item/StandingAndWallBlockItem.java index 1f0e7c391d02b18e2c89700025713ec3d759f2ea..300ee12ca9584e53e9d72e3ebfd039beb3fab3b2 100644 --- a/net/minecraft/world/item/StandingAndWallBlockItem.java @@ -86,10 +88,10 @@ index 1f0e7c391d02b18e2c89700025713ec3d759f2ea..300ee12ca9584e53e9d72e3ebfd039be org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent(org.bukkit.craftbukkit.block.CraftBlock.at(context.getLevel(), clickedPos), player, org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(blockState), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent diff --git a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java -index cc8781c0a357eebc2bff936b4e7be53cc316716d..f5264831b2dc1843b09599086f2bb586d041535d 100644 +index 5e58113b3401268e0432235dc10b2734dbbd8b71..1f7c2d06952febd7a5d4e216b6e22794239b9325 100644 --- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java -@@ -147,7 +147,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl +@@ -152,7 +152,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl List entities = level.getEntities(null, progressDeltaAabb); if (!entities.isEmpty()) { for (Entity entity : entities) { @@ -99,10 +101,10 @@ index cc8781c0a357eebc2bff936b4e7be53cc316716d..f5264831b2dc1843b09599086f2bb586 MoverType.SHULKER_BOX, new Vec3( diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index ee2f8e8deb35059824b5730a1442f383dc79f01c..841167f3f168ff3129b17e176df476ed7b9aaaf5 100644 +index 8449545bd5278f5558567dd6b7c1522f63045f22..3d2770828d4fe1123b158e70bfe459d7cf16332a 100644 --- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -@@ -148,7 +148,7 @@ public class PistonMovingBlockEntity extends BlockEntity { +@@ -152,7 +152,7 @@ public class PistonMovingBlockEntity extends BlockEntity { d3 = movementDirection.getStepZ(); } @@ -111,11 +113,11 @@ index ee2f8e8deb35059824b5730a1442f383dc79f01c..841167f3f168ff3129b17e176df476ed // Paper - EAR items stuck in slime pushed by a piston entity.activatedTick = Math.max(entity.activatedTick, net.minecraft.server.MinecraftServer.currentTick + 10); entity.activatedImmunityTick = Math.max(entity.activatedImmunityTick, net.minecraft.server.MinecraftServer.currentTick + 10); -@@ -184,6 +184,7 @@ public class PistonMovingBlockEntity extends BlockEntity { +@@ -188,6 +188,7 @@ public class PistonMovingBlockEntity extends BlockEntity { } private static void moveEntityByPiston(Direction noClipDirection, Entity entity, double progress, Direction direction) { + if (entity instanceof net.minecraft.world.entity.player.Player player && player.isCreativeFlyOrSpectator()) return; // Leaves - creative no clip NOCLIP.set(noClipDirection); + Vec3 vec3 = entity.position(); entity.move(MoverType.PISTON, new Vec3(progress * direction.getStepX(), progress * direction.getStepY(), progress * direction.getStepZ())); - entity.applyEffectsFromBlocks(); diff --git a/leaves-server/minecraft-patches/features/0050-Elytra-aeronautics-no-chunk-load.patch b/leaves-server/minecraft-patches/features/0050-Elytra-aeronautics-no-chunk-load.patch deleted file mode 100644 index b5bb3f26..00000000 --- a/leaves-server/minecraft-patches/features/0050-Elytra-aeronautics-no-chunk-load.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Sun, 2 Jul 2023 09:25:00 +0800 -Subject: [PATCH] Elytra aeronautics no chunk load - - -diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index 36c0a690e7e9b301c5a3d63fae2c7cbe36ba6cdf..6b625fbd538e5a4073e86e22adfcd382e1efde86 100644 ---- a/net/minecraft/server/level/ChunkMap.java -+++ b/net/minecraft/server/level/ChunkMap.java -@@ -792,7 +792,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - private boolean skipPlayer(ServerPlayer player) { -- return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); -+ return (player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS)) -+ || (org.leavesmc.leaves.LeavesConfig.modify.elytraAeronautics.noChunk && player.elytraAeronauticsNoChunk); // Leaves - Elytra aeronautics - } - - void updatePlayerStatus(ServerPlayer player, boolean track) { -@@ -826,6 +827,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - public void move(ServerPlayer player) { -+ if (player.elytraAeronauticsNoChunk) return; // Leaves - no chunk - // Paper - optimise entity tracker - - SectionPos lastSectionPos = player.getLastSectionPos(); -diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 325300e7ad68b7ad377ff1269bc5d568d663ec3a..b3abfd93b7b4ce47e3382a9f81b82dbb2beb37ae 100644 ---- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -549,7 +549,7 @@ public class ServerGamePacketListenerImpl - speed *= 2f; // TODO: Get the speed of the vehicle instead of the player - - // Paper start - Prevent moving into unloaded chunks -- if (this.player.level().paperConfig().chunks.preventMovingIntoUnloadedChunks && ( -+ if (this.player.level().paperConfig().chunks.preventMovingIntoUnloadedChunks && !player.elytraAeronauticsNoChunk && ( // Leaves - no chunk load - !serverLevel.areChunksLoadedForMove(this.player.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(this.player.position()))) || - !serverLevel.areChunksLoadedForMove(rootVehicle.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(rootVehicle.position()))) - )) { -diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 25b7fe802216d805b6426a5b0098d8e41fe48a7d..7dc1aaaf590edcd1e7c6c6734c4baeecbfec93a7 100644 ---- a/net/minecraft/world/entity/Entity.java -+++ b/net/minecraft/world/entity/Entity.java -@@ -1109,7 +1109,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - return; - } - } -- -+ // Leaves start - elytra aeronautics -+ if (org.leavesmc.leaves.LeavesConfig.modify.elytraAeronautics.noChunk && this instanceof Player player) { -+ if (type == MoverType.PLAYER && player.isFallFlying()) { -+ org.leavesmc.leaves.util.ElytraAeronauticsHelper.flightBehaviour(player, movement); -+ } -+ } -+ // Leaves end - elytra aeronautics - ProfilerFiller profilerFiller = Profiler.get(); - profilerFiller.push("move"); - if (this.stuckSpeedMultiplier.lengthSqr() > 1.0E-7) { -@@ -2059,6 +2065,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - this.yo = y; - this.zo = d1; - this.setPos(d, y, d1); -+ if (this instanceof Player player && player.elytraAeronauticsNoChunk) return; // Leaves - elytra aeronautics - if (this.valid) this.level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit - } - -diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 39fc3ea891947ddd102f992e7b6c62f9367849e7..9a2ab505fda1c59df99ef384af5fb8bc5d1bf68c 100644 ---- a/net/minecraft/world/entity/player/Player.java -+++ b/net/minecraft/world/entity/player/Player.java -@@ -200,6 +200,7 @@ public abstract class Player extends LivingEntity { - private int currentImpulseContextResetGraceTime; - public boolean affectsSpawning = true; // Paper - Affects Spawning API - public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage -+ public boolean elytraAeronauticsNoChunk = false; // Leaves - Elytra aeronautics - - // CraftBukkit start - public boolean fauxSleeping; diff --git a/leaves-server/minecraft-patches/features/0049-Shave-snow-layers.patch b/leaves-server/minecraft-patches/features/0051-Shave-snow-layers.patch similarity index 93% rename from leaves-server/minecraft-patches/features/0049-Shave-snow-layers.patch rename to leaves-server/minecraft-patches/features/0051-Shave-snow-layers.patch index cc5ad723..9164594c 100644 --- a/leaves-server/minecraft-patches/features/0049-Shave-snow-layers.patch +++ b/leaves-server/minecraft-patches/features/0051-Shave-snow-layers.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Shave snow layers diff --git a/net/minecraft/world/item/ShovelItem.java b/net/minecraft/world/item/ShovelItem.java -index 75bbe901e79d9ba3250ed2426a36c1c3363c19c1..29849cd8f53daf2da0b9973c805d44376984013c 100644 +index 887ac9f547ceaf76fd533ae47239a64c29a64b18..29b272ff2e4fe686a0e12b33f6edbe1a412b1590 100644 --- a/net/minecraft/world/item/ShovelItem.java +++ b/net/minecraft/world/item/ShovelItem.java -@@ -44,6 +44,26 @@ public class ShovelItem extends DiggerItem { +@@ -43,6 +43,26 @@ public class ShovelItem extends Item { return InteractionResult.PASS; } else { Player player = context.getPlayer(); diff --git a/leaves-server/minecraft-patches/features/0052-Elytra-aeronautics-no-chunk-load.patch b/leaves-server/minecraft-patches/features/0052-Elytra-aeronautics-no-chunk-load.patch new file mode 100644 index 00000000..10f41979 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0052-Elytra-aeronautics-no-chunk-load.patch @@ -0,0 +1,160 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: violetc <58360096+s-yh-china@users.noreply.github.com> +Date: Sun, 2 Jul 2023 09:25:00 +0800 +Subject: [PATCH] Elytra aeronautics no chunk load + + +diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java +index 4785f9d6c53e18419a3df4a1be9c8a4f9d8cadfb..711bd09283c57e5cbe3b04d6950ecf1308fcf09c 100644 +--- a/net/minecraft/server/level/ChunkMap.java ++++ b/net/minecraft/server/level/ChunkMap.java +@@ -854,7 +854,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + private boolean skipPlayer(ServerPlayer player) { +- return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); ++ return (player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS)) ++ || (org.leavesmc.leaves.LeavesConfig.modify.elytraAeronautics.enableNoChunkLoad && player.elytraAeronauticsNoChunk); // Leaves - Elytra aeronautics + } + + void updatePlayerStatus(ServerPlayer player, boolean track) { +@@ -888,6 +889,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + public void move(ServerPlayer player) { ++ if (player.elytraAeronauticsNoChunk) return; // Leaves - no chunk + // Paper - optimise entity tracker + + SectionPos lastSectionPos = player.getLastSectionPos(); +diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java +index 270ce4c452ed7efce45923e80b11a606c3f15dab..b8a9b2f5671537cf0a805dc2c98945094bd7b8b1 100644 +--- a/net/minecraft/server/level/ServerLevel.java ++++ b/net/minecraft/server/level/ServerLevel.java +@@ -830,6 +830,9 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + } + } + ); ++ if (org.leavesmc.leaves.LeavesConfig.modify.elytraAeronautics.enableNoChunkLoad) { ++ org.leavesmc.leaves.util.ElytraAeronauticsHelper.tick(this); ++ } + profilerFiller.pop(); + this.tickBlockEntities(); + } +diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 448c77f5002276eab680a96b518e8a7234806f80..655ca2ead22addbb458b89e12cb2be1d269e4f5e 100644 +--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -541,7 +541,7 @@ public class ServerGamePacketListenerImpl + speed *= 2f; // TODO: Get the speed of the vehicle instead of the player + + // Paper start - Prevent moving into unloaded chunks +- if (this.player.level().paperConfig().chunks.preventMovingIntoUnloadedChunks && ( ++ if (this.player.level().paperConfig().chunks.preventMovingIntoUnloadedChunks && !player.elytraAeronauticsNoChunk && ( // Leaves - no chunk load + !serverLevel.areChunksLoadedForMove(this.player.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(this.player.position()))) || + !serverLevel.areChunksLoadedForMove(rootVehicle.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(rootVehicle.position()))) + )) { +@@ -1549,6 +1549,7 @@ public class ServerGamePacketListenerImpl + teleportBack = this.hasNewCollision(serverLevel, this.player, boundingBox, newBox); + } // else: no collision at all detected, why do we care? + } ++ teleportBack = teleportBack && !player.elytraAeronauticsNoChunk; // Leaves - Elytra aeronautics + // Paper end - optimise out extra getCubes + if (teleportBack) { + io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK, +diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java +index 2d54997ead46e5185104af621dbe39f66246aa96..a074f50e761243af9e25d12fcddcb86dbd148590 100644 +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -1092,7 +1092,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + return; + } + } +- ++ // Leaves start - elytra aeronautics ++ if (org.leavesmc.leaves.LeavesConfig.modify.elytraAeronautics.enableNoChunkLoad && this instanceof Player player) { ++ if (type == MoverType.PLAYER && player.isFallFlying()) { ++ org.leavesmc.leaves.util.ElytraAeronauticsHelper.flightBehaviour(player, movement); ++ } ++ } ++ // Leaves end - elytra aeronautics + ProfilerFiller profilerFiller = Profiler.get(); + profilerFiller.push("move"); + if (this.stuckSpeedMultiplier.lengthSqr() > 1.0E-7) { +@@ -2053,6 +2059,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + this.yo = y; + this.zo = d1; + this.setPos(d, y, d1); ++ if (this instanceof Player player && player.elytraAeronauticsNoChunk) return; // Leaves - elytra aeronautics + if (this.valid) this.level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit + } + +diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java +index 6893ca36cd4ae9a62fecedb1167cc6cf797a7f8f..a95fec1506af042bd3d4424e93aa3f4de9627487 100644 +--- a/net/minecraft/world/entity/LivingEntity.java ++++ b/net/minecraft/world/entity/LivingEntity.java +@@ -3276,6 +3276,11 @@ public abstract class LivingEntity extends Entity implements Attackable { + this.fallFlyTicks++; + } else { + this.fallFlyTicks = 0; ++ // Leaves start - Elytra aeronautics ++ if (this instanceof ServerPlayer player) { ++ org.leavesmc.leaves.util.ElytraAeronauticsHelper.handleCruiseDeactivate(player); ++ } ++ // Leaves end - Elytra aeronautics + } + + if (this.isSleeping()) { +diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java +index 3eb9a9f6d7f8d28d527941177a5faf2c97628594..a00e1ccb915e9e33b0c56b228cb0447d8af1e195 100644 +--- a/net/minecraft/world/entity/player/Player.java ++++ b/net/minecraft/world/entity/player/Player.java +@@ -210,6 +210,7 @@ public abstract class Player extends LivingEntity { + private int currentImpulseContextResetGraceTime = 0; + public boolean affectsSpawning = true; // Paper - Affects Spawning API + public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage ++ public boolean elytraAeronauticsNoChunk = false; // Leaves - Elytra aeronautics + + // CraftBukkit start + public boolean fauxSleeping; +diff --git a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +index e0e193078e550225e163149638bf9e053c0531f8..484f1c5eba3776eff86438ba02607e60c7083b3b 100644 +--- a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -328,7 +328,7 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + this.spawningEntity = compound.read("SpawningEntity", net.minecraft.core.UUIDUtil.CODEC).orElse(null); // Paper + } + +- private List getExplosions() { ++ public List getExplosions() { // Leaves private -> public + ItemStack itemStack = this.entityData.get(DATA_ID_FIREWORKS_ITEM); + Fireworks fireworks = itemStack.get(DataComponents.FIREWORKS); + return fireworks != null ? fireworks.explosions() : List.of(); +diff --git a/net/minecraft/world/item/FireworkRocketItem.java b/net/minecraft/world/item/FireworkRocketItem.java +index 18d63d2da49451a2d5e1da7bf0c00e05e2f192bc..6c78a59b6518799c9b199c96cc4592fb48229e9a 100644 +--- a/net/minecraft/world/item/FireworkRocketItem.java ++++ b/net/minecraft/world/item/FireworkRocketItem.java +@@ -57,6 +57,24 @@ public class FireworkRocketItem extends Item implements ProjectileItem { + if (player.isFallFlying()) { + ItemStack itemInHand = player.getItemInHand(hand); + if (level instanceof ServerLevel serverLevel) { ++ // Leaves start - Elytra aeronautics ++ if (player instanceof net.minecraft.server.level.ServerPlayer sp && sp.elytraAeronauticsNoChunk) { ++ final FireworkRocketEntity firework = new FireworkRocketEntity(level, itemInHand, player); ++ firework.spawningEntity = player.getUUID(); ++ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Firework) firework.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand)); ++ if (event.callEvent() && org.leavesmc.leaves.util.ElytraAeronauticsHelper.proxySpawnAndTick(firework)) { ++ player.awardStat(Stats.ITEM_USED.get(this)); ++ if (event.shouldConsume() && !player.hasInfiniteMaterials()) { ++ itemInHand.shrink(1); ++ } else { ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ } else { ++ player.containerMenu.sendAllDataToRemote(); ++ } ++ return InteractionResult.SUCCESS; ++ } ++ // Leaves end - Elytra aeronautics + // Paper start - PlayerElytraBoostEvent + final Projectile.Delayed delayed = Projectile.spawnProjectileDelayed(new FireworkRocketEntity(level, itemInHand, player), serverLevel, itemInHand, f -> f.spawningEntity = player.getUUID()); // Paper - firework api - assign spawning entity uuid + com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Firework) delayed.projectile().getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand)); diff --git a/leaves-server/minecraft-patches/features/0051-Cache-ignite-odds.patch b/leaves-server/minecraft-patches/features/0053-Cache-ignite-odds.patch similarity index 65% rename from leaves-server/minecraft-patches/features/0051-Cache-ignite-odds.patch rename to leaves-server/minecraft-patches/features/0053-Cache-ignite-odds.patch index 550bbbac..dd419aae 100644 --- a/leaves-server/minecraft-patches/features/0051-Cache-ignite-odds.patch +++ b/leaves-server/minecraft-patches/features/0053-Cache-ignite-odds.patch @@ -5,27 +5,27 @@ Subject: [PATCH] Cache ignite odds diff --git a/net/minecraft/world/level/block/FireBlock.java b/net/minecraft/world/level/block/FireBlock.java -index 7340c664fdcf991a2549c8f07f6ab093bbe6e4e8..d9796f683de7c0c12f45f62597792f80c66c60b7 100644 +index c03ad7be16fbb9f98c28bc09de59bf33d4edf5d7..8c0b2eb643ccaaa921a90dc2963ce4abcede854d 100644 --- a/net/minecraft/world/level/block/FireBlock.java +++ b/net/minecraft/world/level/block/FireBlock.java -@@ -225,6 +225,7 @@ public class FireBlock extends BaseFireBlock { - this.checkBurnOut(level, pos.south(), 300 + i, random, ageValue, pos); - // CraftBukkit end - BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); +@@ -205,6 +205,7 @@ public class FireBlock extends BaseFireBlock { + this.checkBurnOut(level, pos.south(), 300 + i, random, ageValue, pos); + // CraftBukkit end + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + Object2IntOpenHashMap blockPositionIgniteCache = new Object2IntOpenHashMap<>(); // Leaves - cache ignite odds - for (int i1 = -1; i1 <= 1; i1++) { - for (int i2 = -1; i2 <= 1; i2++) { -@@ -236,7 +237,7 @@ public class FireBlock extends BaseFireBlock { - } + for (int i1 = -1; i1 <= 1; i1++) { + for (int i2 = -1; i2 <= 1; i2++) { +@@ -216,7 +217,7 @@ public class FireBlock extends BaseFireBlock { + } - mutableBlockPos.setWithOffset(pos, i1, i3, i2); -- int igniteOdds = this.getIgniteOdds(level, mutableBlockPos); + mutableBlockPos.setWithOffset(pos, i1, i3, i2); +- int igniteOdds = this.getIgniteOdds(level, mutableBlockPos); + int igniteOdds = this.getIgniteOdds(level, mutableBlockPos, org.leavesmc.leaves.LeavesConfig.performance.cacheIgniteOdds ? blockPositionIgniteCache : null); // Leaves - cache ignite odds - if (igniteOdds > 0) { - int i5 = (igniteOdds + 40 + level.getDifficulty().getId() * 7) / (ageValue + 30); - if (isIncreasedFireBurnout) { -@@ -340,20 +341,33 @@ public class FireBlock extends BaseFireBlock { + if (igniteOdds > 0) { + int i5 = (igniteOdds + 40 + level.getDifficulty().getId() * 7) / (ageValue + 30); + if (isIncreasedFireBurnout) { +@@ -319,20 +320,33 @@ public class FireBlock extends BaseFireBlock { return false; } diff --git a/leaves-server/minecraft-patches/features/0052-Lava-riptide.patch b/leaves-server/minecraft-patches/features/0054-Lava-riptide.patch similarity index 87% rename from leaves-server/minecraft-patches/features/0052-Lava-riptide.patch rename to leaves-server/minecraft-patches/features/0054-Lava-riptide.patch index 264495b7..283a6bc9 100644 --- a/leaves-server/minecraft-patches/features/0052-Lava-riptide.patch +++ b/leaves-server/minecraft-patches/features/0054-Lava-riptide.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Lava riptide diff --git a/net/minecraft/world/item/TridentItem.java b/net/minecraft/world/item/TridentItem.java -index 23284dbeff327d1b8dc89f3a0dc0ee549cec2daa..edf6ac62e068f46f68b76ea1e8a801cfe2611d3e 100644 +index df629e3f2defce5e65aaf874d7c5ddff71f39c28..a069729494d638e5f0828c12ad1186e748d0677e 100644 --- a/net/minecraft/world/item/TridentItem.java +++ b/net/minecraft/world/item/TridentItem.java -@@ -78,7 +78,7 @@ public class TridentItem extends Item implements ProjectileItem { +@@ -70,7 +70,7 @@ public class TridentItem extends Item implements ProjectileItem { return false; } else { float tridentSpinAttackStrength = EnchantmentHelper.getTridentSpinAttackStrength(stack, player); @@ -17,7 +17,7 @@ index 23284dbeff327d1b8dc89f3a0dc0ee549cec2daa..edf6ac62e068f46f68b76ea1e8a801cf return false; } else if (stack.nextDamageWillBreak()) { return false; -@@ -154,7 +154,7 @@ public class TridentItem extends Item implements ProjectileItem { +@@ -150,7 +150,7 @@ public class TridentItem extends Item implements ProjectileItem { ItemStack itemInHand = player.getItemInHand(hand); if (itemInHand.nextDamageWillBreak()) { return InteractionResult.FAIL; diff --git a/leaves-server/minecraft-patches/features/0053-No-block-update-command.patch b/leaves-server/minecraft-patches/features/0055-No-block-update-command.patch similarity index 78% rename from leaves-server/minecraft-patches/features/0053-No-block-update-command.patch rename to leaves-server/minecraft-patches/features/0055-No-block-update-command.patch index aa3332e2..f6081e5b 100644 --- a/leaves-server/minecraft-patches/features/0053-No-block-update-command.patch +++ b/leaves-server/minecraft-patches/features/0055-No-block-update-command.patch @@ -5,22 +5,22 @@ Subject: [PATCH] No block update command diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 30a543de1d8b454ffec0c6cd668aad3504cdf95d..0ea8b6c844f85226081408847781f5ccea461bc3 100644 +index b8a9b2f5671537cf0a805dc2c98945094bd7b8b1..a2199f7aac4f44a70087dd90fe9330fcb8970772 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -2386,6 +2386,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -1789,6 +1789,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @Override - public void blockUpdated(BlockPos pos, Block block) { + public void updateNeighborsAt(BlockPos pos, Block block, @Nullable Orientation orientation) { + if (org.leavesmc.leaves.command.NoBlockUpdateCommand.isNoBlockUpdate()) return; // Leaves - no block update - if (!this.isDebug()) { - // CraftBukkit start - if (this.populating) { + if (captureBlockStates) { return; } // Paper - Cancel all physics during placement + this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, block, null, orientation); + } diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index 889a947cec81683cb7caa447dbf28b701fb38d0b..e1351c55d1b50c0f28a4c225400ade1d626d840c 100644 +index 649d17dcd7856e3b1344192d8ea4b2e9f73fc03b..93b7c607e0f527a910fc15c88c9a0a9ede26f23d 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java -@@ -487,7 +487,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -482,7 +482,7 @@ public final class ItemStack implements DataComponentHolder { net.minecraft.world.level.block.state.BlockState block = serverLevel.getBlockState(newPos); if (!(block.getBlock() instanceof net.minecraft.world.level.block.BaseEntityBlock)) { // Containers get placed automatically @@ -28,25 +28,25 @@ index 889a947cec81683cb7caa447dbf28b701fb38d0b..e1351c55d1b50c0f28a4c225400ade1d + if (!org.leavesmc.leaves.command.NoBlockUpdateCommand.isNoBlockUpdate()) block.onPlace(serverLevel, newPos, oldBlock, true, context); // Leaves - no block update } - serverLevel.notifyAndUpdatePhysics(newPos, null, oldBlock, block, serverLevel.getBlockState(newPos), updateFlag, net.minecraft.world.level.block.Block.UPDATE_LIMIT); // send null chunk as chunk.k() returns false by this point + serverLevel.notifyAndUpdatePhysics(newPos, null, oldBlock, block, serverLevel.getBlockState(newPos), updateFlags, net.minecraft.world.level.block.Block.UPDATE_LIMIT); // send null chunk as chunk.k() returns false by this point diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index 1776b79309ffd9a8a52f27a144606ed9a441251e..1e4e1a3236fc6b9aa515f2025cdef5a901c64d58 100644 +index 845319dd3e355f739cce70b7df3172dd146601b1..7fca1659bd85b1a737355fb9a8377dff64a7fe17 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java -@@ -405,7 +405,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -413,7 +413,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p return null; } else { - if (!this.level.isClientSide && doPlace && (!this.level.captureBlockStates || block instanceof net.minecraft.world.level.block.BaseEntityBlock)) { // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. -- state.onPlace(this.level, pos, blockState, isMoving); -+ if (!org.leavesmc.leaves.command.NoBlockUpdateCommand.isNoBlockUpdate()) state.onPlace(this.level, pos, blockState, isMoving); // Leaves - no block update + if (!this.level.isClientSide && (flags & 512) == 0 && (!this.level.captureBlockStates || block instanceof net.minecraft.world.level.block.BaseEntityBlock)) { // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. +- state.onPlace(this.level, pos, blockState, flag1); ++ if (!org.leavesmc.leaves.command.NoBlockUpdateCommand.isNoBlockUpdate()) state.onPlace(this.level, pos, blockState, flag1); // Leaves - no block update } if (state.hasBlockEntity()) { diff --git a/net/minecraft/world/level/material/FlowingFluid.java b/net/minecraft/world/level/material/FlowingFluid.java -index e30499bdcd6600e5c9d4a755c1182fb6dff3735f..ce3a74860f4a6b65e6eb1cf422f71ec1f844ecd2 100644 +index ace1099a12c762b2e73b71dd3551cf351fedf067..0ccc884066b0a217c7b833c33d3fe96dd7ad0a0b 100644 --- a/net/minecraft/world/level/material/FlowingFluid.java +++ b/net/minecraft/world/level/material/FlowingFluid.java -@@ -475,6 +475,7 @@ public abstract class FlowingFluid extends Fluid { +@@ -476,6 +476,7 @@ public abstract class FlowingFluid extends Fluid { @Override public void tick(ServerLevel level, BlockPos pos, BlockState blockState, FluidState fluidState) { diff --git a/leaves-server/minecraft-patches/features/0054-Raider-die-skip-self-raid-check.patch b/leaves-server/minecraft-patches/features/0056-Raider-die-skip-self-raid-check.patch similarity index 85% rename from leaves-server/minecraft-patches/features/0054-Raider-die-skip-self-raid-check.patch rename to leaves-server/minecraft-patches/features/0056-Raider-die-skip-self-raid-check.patch index e94b7e95..5a77c777 100644 --- a/leaves-server/minecraft-patches/features/0054-Raider-die-skip-self-raid-check.patch +++ b/leaves-server/minecraft-patches/features/0056-Raider-die-skip-self-raid-check.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Raider die skip self raid check diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java -index 8270d76a753bfd26a4c8ef6610bee5c24ee59cfe..f58a20e7dd6b8dc3fc431d4aba9f91a7c25f2c33 100644 +index e81ae747fe95c22321fc69791a6509d601826fd6..39a6a4579931d7edb7ab8c072d62cfc9b02791c8 100644 --- a/net/minecraft/world/entity/raid/Raider.java +++ b/net/minecraft/world/entity/raid/Raider.java -@@ -153,7 +153,7 @@ public abstract class Raider extends PatrollingMonster { +@@ -155,7 +155,7 @@ public abstract class Raider extends PatrollingMonster { } public boolean hasRaid() { diff --git a/leaves-server/minecraft-patches/features/0055-Container-open-passthrough.patch b/leaves-server/minecraft-patches/features/0057-Container-open-passthrough.patch similarity index 94% rename from leaves-server/minecraft-patches/features/0055-Container-open-passthrough.patch rename to leaves-server/minecraft-patches/features/0057-Container-open-passthrough.patch index 6de08663..6befec05 100644 --- a/leaves-server/minecraft-patches/features/0055-Container-open-passthrough.patch +++ b/leaves-server/minecraft-patches/features/0057-Container-open-passthrough.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Container open passthrough diff --git a/net/minecraft/world/entity/decoration/ItemFrame.java b/net/minecraft/world/entity/decoration/ItemFrame.java -index 65e1d7c5ac94b1cfb921fa009be59d3e5872f0b5..34a60bc540cd08da0ebec3a37ec0a01da3dd24de 100644 +index f9a97000b75db7999b1cbe1f72d680d4d7b803b7..91164be32436c003f2456d4510466779e1b576d8 100644 --- a/net/minecraft/world/entity/decoration/ItemFrame.java +++ b/net/minecraft/world/entity/decoration/ItemFrame.java @@ -408,6 +408,20 @@ public class ItemFrame extends HangingEntity { @@ -30,10 +30,10 @@ index 65e1d7c5ac94b1cfb921fa009be59d3e5872f0b5..34a60bc540cd08da0ebec3a37ec0a01d io.papermc.paper.event.player.PlayerItemFrameChangeEvent event = new io.papermc.paper.event.player.PlayerItemFrameChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.ItemFrame) this.getBukkitEntity(), this.getItem().asBukkitCopy(), io.papermc.paper.event.player.PlayerItemFrameChangeEvent.ItemFrameChangeAction.ROTATE); if (!event.callEvent()) { diff --git a/net/minecraft/world/level/block/SignBlock.java b/net/minecraft/world/level/block/SignBlock.java -index f33a42b4888dbf46175e0be409aa6c8688d552b9..da815a9a5e447e9a1cf44f54e4fcbb9481d65d86 100644 +index a06896de4401f184e8c5cc8bad829e6412eaff22..00067809380fb3cff1dd54876c28c7a8d5b0aaee 100644 --- a/net/minecraft/world/level/block/SignBlock.java +++ b/net/minecraft/world/level/block/SignBlock.java -@@ -106,6 +106,18 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo +@@ -105,6 +105,18 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo } else { return InteractionResult.TRY_WITH_EMPTY_HAND; } @@ -52,7 +52,7 @@ index f33a42b4888dbf46175e0be409aa6c8688d552b9..da815a9a5e447e9a1cf44f54e4fcbb94 } else { return InteractionResult.TRY_WITH_EMPTY_HAND; } -@@ -131,6 +143,25 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo +@@ -130,6 +142,25 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo return InteractionResult.SUCCESS_SERVER; } else if (flag) { return InteractionResult.SUCCESS_SERVER; diff --git a/leaves-server/minecraft-patches/features/0056-Dont-respond-ping-before-start-fully.patch b/leaves-server/minecraft-patches/features/0058-Dont-respond-ping-before-start-fully.patch similarity index 100% rename from leaves-server/minecraft-patches/features/0056-Dont-respond-ping-before-start-fully.patch rename to leaves-server/minecraft-patches/features/0058-Dont-respond-ping-before-start-fully.patch diff --git a/leaves-server/minecraft-patches/features/0057-Faster-chunk-serialization.patch b/leaves-server/minecraft-patches/features/0059-Faster-chunk-serialization.patch similarity index 99% rename from leaves-server/minecraft-patches/features/0057-Faster-chunk-serialization.patch rename to leaves-server/minecraft-patches/features/0059-Faster-chunk-serialization.patch index d87f2639..1f0517be 100644 --- a/leaves-server/minecraft-patches/features/0057-Faster-chunk-serialization.patch +++ b/leaves-server/minecraft-patches/features/0059-Faster-chunk-serialization.patch @@ -92,7 +92,7 @@ index c723606fa0be811e580ba47de8c9c575583cc930..c768443c8c6a4b05018bbc70d54b6f41 int onResize(int bits, T objectAdded); } diff --git a/net/minecraft/world/level/chunk/PalettedContainer.java b/net/minecraft/world/level/chunk/PalettedContainer.java -index f5da433050fd3060e0335d4002d520ebe8cd691f..afd78a03fb29c633cc8dc811a14df43aff69ba98 100644 +index 7da7ce0fd19896593e63edc88b492c02f926bba0..0f89bdb35fced1b9e674959ca510d2da9d4d4c5c 100644 --- a/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/net/minecraft/world/level/chunk/PalettedContainer.java @@ -25,6 +25,24 @@ import net.minecraft.util.ThreadingDetector; diff --git a/leaves-server/minecraft-patches/features/0058-Skip-secondary-POI-sensor-if-absent.patch b/leaves-server/minecraft-patches/features/0060-Skip-secondary-POI-sensor-if-absent.patch similarity index 87% rename from leaves-server/minecraft-patches/features/0058-Skip-secondary-POI-sensor-if-absent.patch rename to leaves-server/minecraft-patches/features/0060-Skip-secondary-POI-sensor-if-absent.patch index c110bbce..17792752 100644 --- a/leaves-server/minecraft-patches/features/0058-Skip-secondary-POI-sensor-if-absent.patch +++ b/leaves-server/minecraft-patches/features/0060-Skip-secondary-POI-sensor-if-absent.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Skip secondary POI sensor if absent This patch is Powered by Gale(https://github.com/GaleMC/Gale) diff --git a/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java b/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java -index 6b99afb4f237b5d6def98f3e03492975b795bc95..ef4413c0661800d1d712d89b6a8e95d034e90ae3 100644 +index f0583076ef62189508a392a76c3fb6b741bbdde9..a11c2ef54b6b8193362c2a2d42cef49765adb5c5 100644 --- a/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java +++ b/net/minecraft/world/entity/ai/sensing/SecondaryPoiSensor.java @@ -22,6 +22,15 @@ public class SecondaryPoiSensor extends Sensor { @@ -15,7 +15,7 @@ index 6b99afb4f237b5d6def98f3e03492975b795bc95..ef4413c0661800d1d712d89b6a8e95d0 protected void doTick(ServerLevel level, Villager entity) { + // Leaves start - skip secondary POI sensor if absent + if (org.leavesmc.leaves.LeavesConfig.performance.skipSecondaryPOISensorIfAbsent) { -+ var secondaryPoi = entity.getVillagerData().getProfession().secondaryPoi(); ++ var secondaryPoi = entity.getVillagerData().profession().value().secondaryPoi(); + if (secondaryPoi.isEmpty()) { + entity.getBrain().eraseMemory(MemoryModuleType.SECONDARY_JOB_SITE); + return; diff --git a/leaves-server/minecraft-patches/features/0061-Reduce-array-allocations.patch b/leaves-server/minecraft-patches/features/0061-Reduce-array-allocations.patch deleted file mode 100644 index 23805a08..00000000 --- a/leaves-server/minecraft-patches/features/0061-Reduce-array-allocations.patch +++ /dev/null @@ -1,281 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Thu, 20 Jul 2023 15:03:28 +0800 -Subject: [PATCH] Reduce array allocations - -This patch is Powered by Gale(https://github.com/GaleMC/Gale) - -diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java -index d21ce54ebb5724c04eadf56a2cde701d5eeb5db2..fa4b8ea36acf031ceafc1812e657c2312eb49599 100644 ---- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java -+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java -@@ -29,6 +29,7 @@ import java.util.Arrays; - import java.util.Iterator; - import java.util.List; - import java.util.function.Predicate; -+import org.leavesmc.leaves.util.ArrayConstants; - - public final class ChunkEntitySlices { - -@@ -378,7 +379,7 @@ public final class ChunkEntitySlices { - - private static final class BasicEntityList { - -- private static final Entity[] EMPTY = new Entity[0]; -+ // protected static final Entity[] EMPTY = new Entity[0]; // Leaves - reduce array allocations - private static final int DEFAULT_CAPACITY = 4; - - private E[] storage; -@@ -389,7 +390,7 @@ public final class ChunkEntitySlices { - } - - public BasicEntityList(final int cap) { -- this.storage = (E[])(cap <= 0 ? EMPTY : new Entity[cap]); -+ this.storage = (E[])(cap <= 0 ? ArrayConstants.emptyEntityArray : new Entity[cap]); // Leaves - reduce array allocations - } - - public boolean isEmpty() { -@@ -401,7 +402,7 @@ public final class ChunkEntitySlices { - } - - private void resize() { -- if (this.storage == EMPTY) { -+ if (this.storage == ArrayConstants.emptyEntityArray) { // Leaves - reduce array allocations - this.storage = (E[])new Entity[DEFAULT_CAPACITY]; - } else { - this.storage = Arrays.copyOf(this.storage, this.storage.length * 2); -diff --git a/net/minecraft/nbt/ByteArrayTag.java b/net/minecraft/nbt/ByteArrayTag.java -index 6927124a4ea1f460158bf25679104b6f9e9ccee4..b0e8f47b9fe2b62d03c11a0b95253d7de7b8adac 100644 ---- a/net/minecraft/nbt/ByteArrayTag.java -+++ b/net/minecraft/nbt/ByteArrayTag.java -@@ -6,6 +6,7 @@ import java.io.IOException; - import java.util.Arrays; - import java.util.List; - import org.apache.commons.lang3.ArrayUtils; -+import org.leavesmc.leaves.util.ArrayConstants; - - public class ByteArrayTag extends CollectionTag { - private static final int SELF_SIZE_IN_BYTES = 24; -@@ -174,7 +175,7 @@ public class ByteArrayTag extends CollectionTag { - - @Override - public void clear() { -- this.data = new byte[0]; -+ this.data = ArrayConstants.emptyByteArray; // Leaves - reduce array allocations - } - - @Override -diff --git a/net/minecraft/nbt/CompoundTag.java b/net/minecraft/nbt/CompoundTag.java -index 361bc458e0bb590c43da60a1cd993a2785ee45e9..9d1e0ba4ecccfc8a251d440d63ed90796981808e 100644 ---- a/net/minecraft/nbt/CompoundTag.java -+++ b/net/minecraft/nbt/CompoundTag.java -@@ -18,6 +18,7 @@ import javax.annotation.Nullable; - import net.minecraft.CrashReport; - import net.minecraft.CrashReportCategory; - import net.minecraft.ReportedException; -+import org.leavesmc.leaves.util.ArrayConstants; - - public class CompoundTag implements Tag { - public static final Codec CODEC = Codec.PASSTHROUGH -@@ -409,7 +410,7 @@ public class CompoundTag implements Tag { - throw new ReportedException(this.createReport(key, ByteArrayTag.TYPE, var3)); - } - -- return new byte[0]; -+ return ArrayConstants.emptyByteArray; // Leaves - reduce array allocations - } - - public int[] getIntArray(String key) { -@@ -421,7 +422,7 @@ public class CompoundTag implements Tag { - throw new ReportedException(this.createReport(key, IntArrayTag.TYPE, var3)); - } - -- return new int[0]; -+ return ArrayConstants.emptyIntArray; // Leaves - reduce array allocations - } - - public long[] getLongArray(String key) { -@@ -433,7 +434,7 @@ public class CompoundTag implements Tag { - throw new ReportedException(this.createReport(key, LongArrayTag.TYPE, var3)); - } - -- return new long[0]; -+ return ArrayConstants.emptyLongArray; // Leaves - reduce array allocations - } - - public CompoundTag getCompound(String key) { -diff --git a/net/minecraft/nbt/IntArrayTag.java b/net/minecraft/nbt/IntArrayTag.java -index 7e27546bcb587d03b6de2ab43244e6c61fdb55f4..9e94f41e61687e2dacafec9c06646ec7f7980b62 100644 ---- a/net/minecraft/nbt/IntArrayTag.java -+++ b/net/minecraft/nbt/IntArrayTag.java -@@ -6,6 +6,7 @@ import java.io.IOException; - import java.util.Arrays; - import java.util.List; - import org.apache.commons.lang3.ArrayUtils; -+import org.leavesmc.leaves.util.ArrayConstants; - - public class IntArrayTag extends CollectionTag { - private static final int SELF_SIZE_IN_BYTES = 24; -@@ -181,7 +182,7 @@ public class IntArrayTag extends CollectionTag { - - @Override - public void clear() { -- this.data = new int[0]; -+ this.data = ArrayConstants.emptyIntArray; // Leaves - reduce array allocations - } - - @Override -diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java -index 364ddf9f25ef3cb97ba788c469fee9dd495b84a7..fd490f139e901c2ac598f1eab7aa8d50c65ef864 100644 ---- a/net/minecraft/network/Connection.java -+++ b/net/minecraft/network/Connection.java -@@ -65,6 +65,7 @@ import org.apache.commons.lang3.Validate; - import org.slf4j.Logger; - import org.slf4j.Marker; - import org.slf4j.MarkerFactory; -+import org.leavesmc.leaves.util.ArrayConstants; - - public class Connection extends SimpleChannelInboundHandler> { - private static final float AVERAGE_PACKETS_SMOOTHING = 0.75F; -diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index ff80394fcae884f2a6a700de90c7b495862e532b..a9b9928f371581e6b324622aa9c75aac6d285d7c 100644 ---- a/net/minecraft/server/level/ServerLevel.java -+++ b/net/minecraft/server/level/ServerLevel.java -@@ -169,6 +169,7 @@ import net.minecraft.world.phys.shapes.Shapes; - import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.ticks.LevelTicks; - import org.slf4j.Logger; -+import org.leavesmc.leaves.util.ArrayConstants; - - public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLevel, ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel, ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevelReader, ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel { // Paper - rewrite chunk system // Paper - chunk tick iteration - public static final BlockPos END_SPAWN_POINT = new BlockPos(100, 50, 0); -diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b3abfd93b7b4ce47e3382a9f81b82dbb2beb37ae..f0feadb8d4312d6569783c299968a50fe5c2edee 100644 ---- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -245,6 +245,7 @@ import org.bukkit.inventory.CraftingInventory; - import org.bukkit.inventory.InventoryView; - import org.bukkit.inventory.SmithingInventory; - // CraftBukkit end -+import org.leavesmc.leaves.util.ArrayConstants; - - public class ServerGamePacketListenerImpl - extends ServerCommonPacketListenerImpl -@@ -803,7 +804,7 @@ public class ServerGamePacketListenerImpl - // Paper start - final int index; - if (packet.getCommand().length() > 64 && ((index = packet.getCommand().indexOf(' ')) == -1 || index >= 64)) { -- this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - add proper async disconnect -+ this.disconnectAsync(Component.translatable("disconnect.spam", ArrayConstants.emptyObjectArray), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - add proper async disconnect // Leaves - reduce array allocations - return; - } - // Paper end -diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 6689aeacf50d1498e8d23cce696fb4fecbd1cf39..66d74f720f60c85d3b0e0c04e45bbceedc4e314a 100644 ---- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -50,6 +50,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - import org.bukkit.event.player.PlayerPreLoginEvent; -+import org.leavesmc.leaves.util.ArrayConstants; - - public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, TickablePacketListener, CraftPlayer.TransferCookieConnection { - // CraftBukkit end -diff --git a/net/minecraft/server/players/StoredUserList.java b/net/minecraft/server/players/StoredUserList.java -index d445e8f126f077d8419c52fa5436ea963a1a42a4..0c0f70b5c624e05811aef398a2e6c29c14a9e323 100644 ---- a/net/minecraft/server/players/StoredUserList.java -+++ b/net/minecraft/server/players/StoredUserList.java -@@ -21,6 +21,7 @@ import javax.annotation.Nullable; - import net.minecraft.Util; - import net.minecraft.util.GsonHelper; - import org.slf4j.Logger; -+import org.leavesmc.leaves.util.ArrayConstants; - - public abstract class StoredUserList> { - private static final Logger LOGGER = LogUtils.getLogger(); -@@ -70,7 +71,7 @@ public abstract class StoredUserList> { - } - - public String[] getUserList() { -- return this.map.keySet().toArray(new String[0]); -+ return (String[]) this.map.keySet().toArray(ArrayConstants.emptyStringArray); // Leaves - reduce array allocations - } - - public boolean isEmpty() { -diff --git a/net/minecraft/util/ZeroBitStorage.java b/net/minecraft/util/ZeroBitStorage.java -index 50993ce7519a77c6a9d36cb925125adccda7037f..e5124b566e791c1c011b301f910a892689cf3c65 100644 ---- a/net/minecraft/util/ZeroBitStorage.java -+++ b/net/minecraft/util/ZeroBitStorage.java -@@ -5,7 +5,7 @@ import java.util.function.IntConsumer; - import org.apache.commons.lang3.Validate; - - public class ZeroBitStorage implements BitStorage { -- public static final long[] RAW = new long[0]; -+ public static final long[] RAW = org.leavesmc.leaves.util.ArrayConstants.emptyLongArray; // Leaves - reduce array allocations - private final int size; - - public ZeroBitStorage(int size) { -diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index e9ec19be9393ccd1e257247de86ba05e51471790..e10f4190393a934d617cd2c7afd05f3a4a6e89f9 100644 ---- a/net/minecraft/world/level/Level.java -+++ b/net/minecraft/world/level/Level.java -@@ -102,6 +102,7 @@ import org.bukkit.craftbukkit.util.CraftSpawnCategory; - import org.bukkit.entity.SpawnCategory; - import org.bukkit.event.block.BlockPhysicsEvent; - // CraftBukkit end -+import org.leavesmc.leaves.util.ArrayConstants; - - public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel, ca.spottedleaf.moonrise.patches.chunk_system.world.ChunkSystemEntityGetter { // Paper - rewrite chunk system // Paper - optimise collisions - public static final Codec> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION); -diff --git a/net/minecraft/world/level/block/ComposterBlock.java b/net/minecraft/world/level/block/ComposterBlock.java -index 86f9c284f434a16888beb60b89f460de2c0450a8..e3177018adab3d87eb4af8ac158def96908b041a 100644 ---- a/net/minecraft/world/level/block/ComposterBlock.java -+++ b/net/minecraft/world/level/block/ComposterBlock.java -@@ -410,7 +410,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { - - @Override - public int[] getSlotsForFace(Direction side) { -- return new int[0]; -+ return org.leavesmc.leaves.util.ArrayConstants.emptyIntArray; // Leaves - reduce array allocations - } - - @Override -@@ -445,7 +445,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { - - @Override - public int[] getSlotsForFace(Direction side) { -- return side == Direction.UP ? new int[]{0} : new int[0]; -+ return side == Direction.UP ? org.leavesmc.leaves.util.ArrayConstants.zeroSingletonIntArray : org.leavesmc.leaves.util.ArrayConstants.emptyIntArray; // Leaves - reduce array allocations - } - - @Override -@@ -496,7 +496,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { - - @Override - public int[] getSlotsForFace(Direction side) { -- return side == Direction.DOWN ? new int[]{0} : new int[0]; -+ return side == Direction.DOWN ? org.leavesmc.leaves.util.ArrayConstants.zeroSingletonIntArray : org.leavesmc.leaves.util.ArrayConstants.emptyIntArray; // Leaves - reduce array allocations - } - - @Override -diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 2f5fa4310f475ecbb29e69c0461c7d3276f8536d..304940047eee6fab5b763ce13fdd5d7e6f8e70f1 100644 ---- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -38,13 +38,14 @@ import net.minecraft.world.level.block.AbstractFurnaceBlock; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.BlockState; - import net.minecraft.world.phys.Vec3; -+import org.leavesmc.leaves.util.ArrayConstants; - - public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, RecipeCraftingHolder, StackedContentsCompatible { - protected static final int SLOT_INPUT = 0; - protected static final int SLOT_FUEL = 1; - protected static final int SLOT_RESULT = 2; - public static final int DATA_LIT_TIME = 0; -- private static final int[] SLOTS_FOR_UP = new int[]{0}; -+ private static final int[] SLOTS_FOR_UP = ArrayConstants.zeroSingletonIntArray; // Leaves - reduce array allocations - private static final int[] SLOTS_FOR_DOWN = new int[]{2, 1}; - private static final int[] SLOTS_FOR_SIDES = new int[]{1}; - public static final int DATA_LIT_DURATION = 1; diff --git a/leaves-server/minecraft-patches/features/0059-Store-mob-counts-in-an-array.patch b/leaves-server/minecraft-patches/features/0061-Store-mob-counts-in-an-array.patch similarity index 100% rename from leaves-server/minecraft-patches/features/0059-Store-mob-counts-in-an-array.patch rename to leaves-server/minecraft-patches/features/0061-Store-mob-counts-in-an-array.patch diff --git a/leaves-server/minecraft-patches/features/0060-Optimize-noise-generation.patch b/leaves-server/minecraft-patches/features/0062-Optimize-noise-generation.patch similarity index 100% rename from leaves-server/minecraft-patches/features/0060-Optimize-noise-generation.patch rename to leaves-server/minecraft-patches/features/0062-Optimize-noise-generation.patch diff --git a/leaves-server/minecraft-patches/features/0062-Optimize-sun-burn-tick.patch b/leaves-server/minecraft-patches/features/0063-Optimize-sun-burn-tick.patch similarity index 63% rename from leaves-server/minecraft-patches/features/0062-Optimize-sun-burn-tick.patch rename to leaves-server/minecraft-patches/features/0063-Optimize-sun-burn-tick.patch index cd4c0f19..78cb022c 100644 --- a/leaves-server/minecraft-patches/features/0062-Optimize-sun-burn-tick.patch +++ b/leaves-server/minecraft-patches/features/0063-Optimize-sun-burn-tick.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Optimize sun burn tick This patch is Powered by Gale(https://github.com/GaleMC/Gale) diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 7dc1aaaf590edcd1e7c6c6734c4baeecbfec93a7..3a2bf5f3db1130cae4c7d8dd43b5553d109982be 100644 +index a074f50e761243af9e25d12fcddcb86dbd148590..6b7e547f473e626147bf3ba137e282fa1fb23c9d 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -2040,10 +2040,22 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2034,9 +2034,20 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @Deprecated public float getLightLevelDependentMagicValue() { @@ -31,28 +31,34 @@ index 7dc1aaaf590edcd1e7c6c6734c4baeecbfec93a7..3a2bf5f3db1130cae4c7d8dd43b5553d + public float getLightLevelDependentMagicValue(BlockPos pos) { + return this.level().hasChunkAt(this.getBlockX(), this.getBlockZ()) ? this.level.getLightLevelDependentMagicValue(pos) : 0.0F; } + + public void absSnapTo(double x, double y, double z, float yRot, float xRot) { +@@ -2051,6 +2062,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + this.xRotO = this.getXRot(); + this.setYHeadRot(yRot); // Paper - Update head rotation + } + // Leaves end - optimize sun burn tick - public void absMoveTo(double x, double y, double z, float yRot, float xRot) { - this.absMoveTo(x, y, z); + public void absSnapTo(double x, double y, double z) { + double d = Mth.clamp(x, -3.0E7, 3.0E7); diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java -index 6a9a4ac52602d68f679672e16391304b8e6d8252..f4012def2ec11fe511d8a383e324a58f775cc1f2 100644 +index c83ad2553145b66aad000be3b82fec57f56359ce..c7df4f3a9fb1c3e34a737af1c80e62220abf7edb 100644 --- a/net/minecraft/world/entity/Mob.java +++ b/net/minecraft/world/entity/Mob.java -@@ -1629,20 +1629,40 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1507,17 +1507,39 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab protected void playAttackSound() { } + // Leaves start - optimize sun burn tick -+ private BlockPos cached_eye_blockpos; -+ private int cached_position_hashcode; ++ @Nullable private BlockPos cached_eye_blockpos; ++ @Nullable private net.minecraft.world.phys.Vec3 cached_position; + // Leaves end - optimize sun burn tick + public boolean isSunBurnTick() { - if (this.level().isDay() && !this.level().isClientSide) { + if (this.level().isBrightOutside() && !this.level().isClientSide) { - float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue(); - BlockPos blockPos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); -- boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow; +- boolean flag = this.isInWaterOrRain() || this.isInPowderSnow || this.wasInPowderSnow; - if (lightLevelDependentMagicValue > 0.5F - && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F - && !flag @@ -60,18 +66,19 @@ index 6a9a4ac52602d68f679672e16391304b8e6d8252..f4012def2ec11fe511d8a383e324a58f - return true; + // Leaves start - optimize sun burn tick + if (!org.leavesmc.leaves.LeavesConfig.performance.optimizeSunBurnTick) { -+ float f = this.getLightLevelDependentMagicValue(); -+ BlockPos blockposition = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); -+ boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow; -+ -+ if (f > 0.5F && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && !flag && this.level().canSeeSky(blockposition)) { ++ float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue(); ++ BlockPos blockPos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); ++ boolean flag = this.isInWaterOrRain() || this.isInPowderSnow || this.wasInPowderSnow; ++ if (lightLevelDependentMagicValue > 0.5F ++ && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F ++ && !flag ++ && this.level().canSeeSky(blockPos)) { + return true; + } + } else { -+ int positionHashCode = this.position().hashCode(); -+ if (this.cached_eye_blockpos == null || this.cached_position_hashcode != positionHashCode) { ++ if (cached_eye_blockpos == null || !this.position().equals(cached_position)) { + this.cached_eye_blockpos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); -+ this.cached_position_hashcode = positionHashCode; ++ this.cached_position = this.position(); + } + + float f = this.getLightLevelDependentMagicValue(cached_eye_blockpos); // Pass BlockPos to getBrightness @@ -79,13 +86,10 @@ index 6a9a4ac52602d68f679672e16391304b8e6d8252..f4012def2ec11fe511d8a383e324a58f + // Check brightness first + if (f <= 0.5F) return false; + if (this.random.nextFloat() * 30.0F >= (f - 0.4F) * 2.0F) return false; -+ boolean flag = this.isInWaterRainOrBubble() || this.isInPowderSnow || this.wasInPowderSnow; ++ boolean flag = this.isInWaterOrRain() || this.isInPowderSnow || this.wasInPowderSnow; + return !flag && this.level().canSeeSky(this.cached_eye_blockpos); } ++ // Leaves end - optimize sun burn tick } -- - return false; -+ // Leaves end - optimize sun burn tick - } - @Override + return false; diff --git a/leaves-server/minecraft-patches/features/0063-Reduce-lambda-and-Optional-allocation-in-EntityBased.patch b/leaves-server/minecraft-patches/features/0064-Reduce-lambda-and-Optional-allocation-in-EntityBased.patch similarity index 100% rename from leaves-server/minecraft-patches/features/0063-Reduce-lambda-and-Optional-allocation-in-EntityBased.patch rename to leaves-server/minecraft-patches/features/0064-Reduce-lambda-and-Optional-allocation-in-EntityBased.patch diff --git a/leaves-server/minecraft-patches/features/0064-Avoid-Class-isAssignableFrom-call-in-ClassInstanceMu.patch b/leaves-server/minecraft-patches/features/0065-Avoid-Class-isAssignableFrom-call-in-ClassInstanceMu.patch similarity index 100% rename from leaves-server/minecraft-patches/features/0064-Avoid-Class-isAssignableFrom-call-in-ClassInstanceMu.patch rename to leaves-server/minecraft-patches/features/0065-Avoid-Class-isAssignableFrom-call-in-ClassInstanceMu.patch diff --git a/leaves-server/minecraft-patches/features/0065-Optimized-CubePointRange.patch b/leaves-server/minecraft-patches/features/0066-Optimized-CubePointRange.patch similarity index 100% rename from leaves-server/minecraft-patches/features/0065-Optimized-CubePointRange.patch rename to leaves-server/minecraft-patches/features/0066-Optimized-CubePointRange.patch diff --git a/leaves-server/minecraft-patches/features/0066-Check-frozen-ticks-before-landing-block.patch b/leaves-server/minecraft-patches/features/0067-Check-frozen-ticks-before-landing-block.patch similarity index 89% rename from leaves-server/minecraft-patches/features/0066-Check-frozen-ticks-before-landing-block.patch rename to leaves-server/minecraft-patches/features/0067-Check-frozen-ticks-before-landing-block.patch index ec5e7b9a..7ebf4d9d 100644 --- a/leaves-server/minecraft-patches/features/0066-Check-frozen-ticks-before-landing-block.patch +++ b/leaves-server/minecraft-patches/features/0067-Check-frozen-ticks-before-landing-block.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Check frozen ticks before landing block This patch is Powered by Gale(https://github.com/GaleMC/Gale) diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 5e7068bf9b5364c382fccfb110ed2a26a5ac1731..9b90d9f9a9317cdec1e2684e68d5ec03a143addc 100644 +index a95fec1506af042bd3d4424e93aa3f4de9627487..ce624ed17bc5c9b5e13d280f8dda736581b21821 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -572,10 +572,10 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -523,10 +523,10 @@ public abstract class LivingEntity extends Entity implements Attackable { } protected void tryAddFrost() { diff --git a/leaves-server/minecraft-patches/features/0067-Skip-entity-move-if-movement-is-zero.patch b/leaves-server/minecraft-patches/features/0068-Skip-entity-move-if-movement-is-zero.patch similarity index 86% rename from leaves-server/minecraft-patches/features/0067-Skip-entity-move-if-movement-is-zero.patch rename to leaves-server/minecraft-patches/features/0068-Skip-entity-move-if-movement-is-zero.patch index e86bcd5e..5b171364 100644 --- a/leaves-server/minecraft-patches/features/0067-Skip-entity-move-if-movement-is-zero.patch +++ b/leaves-server/minecraft-patches/features/0068-Skip-entity-move-if-movement-is-zero.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Skip entity move if movement is zero This patch is Powered by Gale(https://github.com/GaleMC/Gale) diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 8d96e314911d9985fad3d395f557aec3e04f7cff..3409bdd246acf5105836d2eef7bfed54f2927e6d 100644 +index 6b7e547f473e626147bf3ba137e282fa1fb23c9d..556c7a1358af9733585d5a8ddf4c9fe5fabc127e 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -235,6 +235,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -242,6 +242,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public float yRotO; public float xRotO; private AABB bb = INITIAL_AABB; @@ -17,7 +17,7 @@ index 8d96e314911d9985fad3d395f557aec3e04f7cff..3409bdd246acf5105836d2eef7bfed54 public boolean onGround; public boolean horizontalCollision; public boolean verticalCollision; -@@ -1086,6 +1087,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1068,6 +1069,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // Paper end - detailed watchdog information public void move(MoverType type, Vec3 movement) { @@ -31,7 +31,7 @@ index 8d96e314911d9985fad3d395f557aec3e04f7cff..3409bdd246acf5105836d2eef7bfed54 final Vec3 originalMovement = movement; // Paper - Expose pre-collision velocity // Paper start - detailed watchdog information ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread("Cannot move an entity off-main"); -@@ -4209,6 +4217,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4191,6 +4199,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public final void setBoundingBox(AABB bb) { diff --git a/leaves-server/minecraft-patches/features/0068-Skip-cloning-advancement-criteria.patch b/leaves-server/minecraft-patches/features/0069-Skip-cloning-advancement-criteria.patch similarity index 88% rename from leaves-server/minecraft-patches/features/0068-Skip-cloning-advancement-criteria.patch rename to leaves-server/minecraft-patches/features/0069-Skip-cloning-advancement-criteria.patch index dd901885..786eff64 100644 --- a/leaves-server/minecraft-patches/features/0068-Skip-cloning-advancement-criteria.patch +++ b/leaves-server/minecraft-patches/features/0069-Skip-cloning-advancement-criteria.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Skip cloning advancement criteria This patch is Powered by Gale(https://github.com/GaleMC/Gale) diff --git a/net/minecraft/advancements/Advancement.java b/net/minecraft/advancements/Advancement.java -index d5c824eabf321a2c7600c7081b8d4f3057cfae2e..32a671ffc4c1970c0af918281b031344b07a4029 100644 +index a1abe9a798e459798ac18d8a9b4756c66eba9721..4bd3babe69b516a1f4938cc3b75ef6e4c6fffe55 100644 --- a/net/minecraft/advancements/Advancement.java +++ b/net/minecraft/advancements/Advancement.java -@@ -60,7 +60,7 @@ public record Advancement( +@@ -61,7 +61,7 @@ public record Advancement( AdvancementRequirements requirements, boolean sendsTelemetryEvent ) { diff --git a/leaves-server/minecraft-patches/features/0069-Fix-villagers-dont-release-memory.patch b/leaves-server/minecraft-patches/features/0070-Fix-villagers-dont-release-memory.patch similarity index 80% rename from leaves-server/minecraft-patches/features/0069-Fix-villagers-dont-release-memory.patch rename to leaves-server/minecraft-patches/features/0070-Fix-villagers-dont-release-memory.patch index 0d9206f2..93aaca59 100644 --- a/leaves-server/minecraft-patches/features/0069-Fix-villagers-dont-release-memory.patch +++ b/leaves-server/minecraft-patches/features/0070-Fix-villagers-dont-release-memory.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix villagers dont release memory diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 3409bdd246acf5105836d2eef7bfed54f2927e6d..65e916089fba9e2a3908dafa24634f6cc259e595 100644 +index 556c7a1358af9733585d5a8ddf4c9fe5fabc127e..4133f8da3ca93b9519cecad68cc50f9bdf86cc94 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -3838,7 +3838,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3822,7 +3822,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return this; } @@ -18,12 +18,12 @@ index 3409bdd246acf5105836d2eef7bfed54f2927e6d..65e916089fba9e2a3908dafa24634f6c List list = new ArrayList<>(passengers.size()); this.ejectPassengers(); diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java -index 2b83262e4a13eae86df82913ce4f3121e3631a43..6b565fcf91e1d94b649dac90bf3c923930d252f8 100644 +index e0e0d2ea7fc60e3142c675404d152eca60263240..956b949b42a7041290838dde816d3b79e1f9e0d4 100644 --- a/net/minecraft/world/entity/npc/Villager.java +++ b/net/minecraft/world/entity/npc/Villager.java -@@ -1017,4 +1017,19 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - Optional memory = this.brain.getMemory(MemoryModuleType.LAST_SLEPT); - return memory.filter(_long -> gameTime - _long < 24000L).isPresent(); +@@ -1033,4 +1033,19 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + return super.applyImplicitComponent(component, value); + } } + + // Leaves start - fixes a memory leak when villagers get moved to another world diff --git a/leaves-server/minecraft-patches/features/0070-Avoid-anvil-too-expensive.patch b/leaves-server/minecraft-patches/features/0071-Avoid-anvil-too-expensive.patch similarity index 67% rename from leaves-server/minecraft-patches/features/0070-Avoid-anvil-too-expensive.patch rename to leaves-server/minecraft-patches/features/0071-Avoid-anvil-too-expensive.patch index f8ef1e18..6e9ab8ec 100644 --- a/leaves-server/minecraft-patches/features/0070-Avoid-anvil-too-expensive.patch +++ b/leaves-server/minecraft-patches/features/0071-Avoid-anvil-too-expensive.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Avoid anvil too expensive diff --git a/net/minecraft/world/inventory/AnvilMenu.java b/net/minecraft/world/inventory/AnvilMenu.java -index aaa022ac3656d68bad8dbd4c80a90b62fb6f9a16..e9ac7966fc49de16a444d0e991a4b736cfdb0a0d 100644 +index 65c400444314049d5529f1f76d65fbd6b1ea7af2..eed4ba79dd5328a59121bd9fe81ef1efd563094e 100644 --- a/net/minecraft/world/inventory/AnvilMenu.java +++ b/net/minecraft/world/inventory/AnvilMenu.java -@@ -260,7 +260,7 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -259,7 +259,7 @@ public class AnvilMenu extends ItemCombinerMenu { this.onlyRenaming = true; } -- if (this.cost.get() >= this.maximumRepairCost && !this.player.getAbilities().instabuild) { // CraftBukkit -+ if (this.cost.get() >= this.maximumRepairCost && (!org.leavesmc.leaves.LeavesConfig.modify.avoidAnvilTooExpensive || this.cost.get() == DEFAULT_DENIED_COST) && !this.player.getAbilities().instabuild) { // CraftBukkit // Leaves - avoid anvil too expensive +- if (this.cost.get() >= this.maximumRepairCost && !this.player.hasInfiniteMaterials()) { // CraftBukkit ++ if (this.cost.get() >= this.maximumRepairCost && (!org.leavesmc.leaves.LeavesConfig.modify.avoidAnvilTooExpensive || this.cost.get() == DEFAULT_DENIED_COST) && !this.player.hasInfiniteMaterials()) { // CraftBukkit // Leaves - avoid anvil too expensive itemStack = ItemStack.EMPTY; } diff --git a/leaves-server/minecraft-patches/features/0071-Bow-infinity-fix.patch b/leaves-server/minecraft-patches/features/0072-Bow-infinity-fix.patch similarity index 54% rename from leaves-server/minecraft-patches/features/0071-Bow-infinity-fix.patch rename to leaves-server/minecraft-patches/features/0072-Bow-infinity-fix.patch index 37182852..f03e48a0 100644 --- a/leaves-server/minecraft-patches/features/0071-Bow-infinity-fix.patch +++ b/leaves-server/minecraft-patches/features/0072-Bow-infinity-fix.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Bow infinity fix diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 9a2ab505fda1c59df99ef384af5fb8bc5d1bf68c..29bc08bdb42e60553723f30d92706047f910b284 100644 +index a00e1ccb915e9e33b0c56b228cb0447d8af1e195..7d606ed45d88bc269943c013b4793583bacb1c83 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java -@@ -2277,7 +2277,7 @@ public abstract class Player extends LivingEntity { +@@ -2165,7 +2165,7 @@ public abstract class Player extends LivingEntity { } if (anyEventCancelled.booleanValue() && !this.abilities.instabuild && this instanceof final ServerPlayer player) this.resyncUsingItem(player); // Paper - resync if no item matched the Predicate -- return this.abilities.instabuild ? new ItemStack(Items.ARROW) : ItemStack.EMPTY; -+ return this.abilities.instabuild || (org.leavesmc.leaves.LeavesConfig.modify.bowInfinityFix && net.minecraft.world.item.enchantment.EnchantmentHelper.processAmmoUse((ServerLevel) this.level(), shootable, new ItemStack(Items.ARROW), 1) <= 0) ? new ItemStack(Items.ARROW) : ItemStack.EMPTY; // Leaves - infinity fix +- return this.hasInfiniteMaterials() ? new ItemStack(Items.ARROW) : ItemStack.EMPTY; ++ return this.hasInfiniteMaterials() || (org.leavesmc.leaves.LeavesConfig.modify.bowInfinityFix && net.minecraft.world.item.enchantment.EnchantmentHelper.processAmmoUse((ServerLevel) this.level(), shootable, new ItemStack(Items.ARROW), 1) <= 0) ? new ItemStack(Items.ARROW) : ItemStack.EMPTY; } } } diff --git a/leaves-server/minecraft-patches/features/0072-Zero-tick-plants.patch b/leaves-server/minecraft-patches/features/0073-Zero-tick-plants.patch similarity index 83% rename from leaves-server/minecraft-patches/features/0072-Zero-tick-plants.patch rename to leaves-server/minecraft-patches/features/0073-Zero-tick-plants.patch index 1b95bd55..a8b2b7f8 100644 --- a/leaves-server/minecraft-patches/features/0072-Zero-tick-plants.patch +++ b/leaves-server/minecraft-patches/features/0073-Zero-tick-plants.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Zero tick plants diff --git a/net/minecraft/world/level/block/BambooStalkBlock.java b/net/minecraft/world/level/block/BambooStalkBlock.java -index d824bb7d86fd9063ec8185f6bc74dc7450c2b73a..7598b403ed10559d271d302a7759f99e41d96dd5 100644 +index a6249f5852c4ac2432bb60cb4f7a2e0a03abd7dd..29f9866e693dbbf9487cdc15ca8d2f5576cde00c 100644 --- a/net/minecraft/world/level/block/BambooStalkBlock.java +++ b/net/minecraft/world/level/block/BambooStalkBlock.java -@@ -119,6 +119,10 @@ public class BambooStalkBlock extends Block implements BonemealableBlock { +@@ -109,6 +109,10 @@ public class BambooStalkBlock extends Block implements BonemealableBlock { protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { if (!state.canSurvive(level, pos)) { level.destroyBlock(pos, true); @@ -20,10 +20,10 @@ index d824bb7d86fd9063ec8185f6bc74dc7450c2b73a..7598b403ed10559d271d302a7759f99e } diff --git a/net/minecraft/world/level/block/CactusBlock.java b/net/minecraft/world/level/block/CactusBlock.java -index 913779c68b178dbbfac3b1dcee0c6342028e5570..590525a5de0119b8a9652a00ec99b10d6cae2c46 100644 +index 8f6878cc8e72513446895bfc79886075bfcd5565..efbd3aff528cd81a79c522aa44b6348827b8c88d 100644 --- a/net/minecraft/world/level/block/CactusBlock.java +++ b/net/minecraft/world/level/block/CactusBlock.java -@@ -43,6 +43,10 @@ public class CactusBlock extends Block { +@@ -47,6 +47,10 @@ public class CactusBlock extends Block { protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { if (!state.canSurvive(level, pos)) { level.destroyBlock(pos, true); @@ -35,7 +35,7 @@ index 913779c68b178dbbfac3b1dcee0c6342028e5570..590525a5de0119b8a9652a00ec99b10d } diff --git a/net/minecraft/world/level/block/ChorusFlowerBlock.java b/net/minecraft/world/level/block/ChorusFlowerBlock.java -index 3af8f150474a8a461c5829850172196b7b9e7bfd..04e392cabf3b5c171d86cb47b29b34d05222d4a4 100644 +index 32ba79c568ef9e75639f03cd7cc34be569638742..46af89f48716a661c4ca31334299d874d29a0b36 100644 --- a/net/minecraft/world/level/block/ChorusFlowerBlock.java +++ b/net/minecraft/world/level/block/ChorusFlowerBlock.java @@ -49,6 +49,9 @@ public class ChorusFlowerBlock extends Block { @@ -49,10 +49,10 @@ index 3af8f150474a8a461c5829850172196b7b9e7bfd..04e392cabf3b5c171d86cb47b29b34d0 } diff --git a/net/minecraft/world/level/block/GrowingPlantHeadBlock.java b/net/minecraft/world/level/block/GrowingPlantHeadBlock.java -index 0994f7265322d1f33365a1df0faaffd9df05fcc0..90577291e4a2846a89c59bd5297a99e910378276 100644 +index fe11f3ec82ebdbdf3d024d7273fb16b6823b1ece..577ba4b329e6d1e224d6ea57b224ad92e1993d65 100644 --- a/net/minecraft/world/level/block/GrowingPlantHeadBlock.java +++ b/net/minecraft/world/level/block/GrowingPlantHeadBlock.java -@@ -148,4 +148,15 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements +@@ -155,4 +155,15 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements protected GrowingPlantHeadBlock getHeadBlock() { return this; } @@ -69,10 +69,10 @@ index 0994f7265322d1f33365a1df0faaffd9df05fcc0..90577291e4a2846a89c59bd5297a99e9 + // Leaves end - zero tick plants } diff --git a/net/minecraft/world/level/block/SugarCaneBlock.java b/net/minecraft/world/level/block/SugarCaneBlock.java -index 63d53f9090caca304c7f8c3f9910c57a6bdbb4d5..1d1e699926c2e244937b34d9f54c627bbd2ce5b4 100644 +index a8de37e173e244d7a16c19ac8805e0e4327c837a..c6803d4869459b778d6a331950889ae1814422ce 100644 --- a/net/minecraft/world/level/block/SugarCaneBlock.java +++ b/net/minecraft/world/level/block/SugarCaneBlock.java -@@ -44,6 +44,10 @@ public class SugarCaneBlock extends Block { +@@ -43,6 +43,10 @@ public class SugarCaneBlock extends Block { protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { if (!state.canSurvive(level, pos)) { level.destroyBlock(pos, true); diff --git a/leaves-server/minecraft-patches/features/0073-Force-peaceful-mode-switch.patch b/leaves-server/minecraft-patches/features/0074-Force-peaceful-mode-switch.patch similarity index 88% rename from leaves-server/minecraft-patches/features/0073-Force-peaceful-mode-switch.patch rename to leaves-server/minecraft-patches/features/0074-Force-peaceful-mode-switch.patch index 44987584..a8b5ab02 100644 --- a/leaves-server/minecraft-patches/features/0073-Force-peaceful-mode-switch.patch +++ b/leaves-server/minecraft-patches/features/0074-Force-peaceful-mode-switch.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Force peaceful mode switch diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java -index 6540b2d6a1062d883811ce240c49d30d1925b291..67f7a71c70095dccd5a9f1a17a422c2d1854f8da 100644 +index 59e8a5e1b35c81883c9b1ca00c6e55d77584d8cc..1e6f7c0997efdeb06dbf1450b3d7f5f4ecc4072c 100644 --- a/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java -@@ -181,6 +181,12 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -184,6 +184,12 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } // Paper end - chunk tick iteration optimisations @@ -21,7 +21,7 @@ index 6540b2d6a1062d883811ce240c49d30d1925b291..67f7a71c70095dccd5a9f1a17a422c2d public ServerChunkCache( ServerLevel level, -@@ -507,6 +513,20 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -512,6 +518,20 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon this.lastInhabitedUpdate = gameTime; if (!this.level.isDebug()) { ProfilerFiller profilerFiller = Profiler.get(); @@ -41,8 +41,8 @@ index 6540b2d6a1062d883811ce240c49d30d1925b291..67f7a71c70095dccd5a9f1a17a422c2d + // Leaves end - peaceful mode switch profilerFiller.push("pollingChunks"); if (this.level.tickRateManager().runsNormally()) { - List list = this.tickingChunks; -@@ -598,6 +618,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + profilerFiller.push("tickingChunks"); +@@ -568,6 +588,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit int _int = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); List filteredSpawningCategories; @@ -57,7 +57,7 @@ index 6540b2d6a1062d883811ce240c49d30d1925b291..67f7a71c70095dccd5a9f1a17a422c2d if (_boolean && (this.spawnEnemies || this.spawnFriendlies)) { // Paper start - PlayerNaturallySpawnCreaturesEvent for (ServerPlayer entityPlayer : this.level.players()) { -@@ -608,7 +636,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -578,7 +606,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } // Paper end - PlayerNaturallySpawnCreaturesEvent boolean flag = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit @@ -67,10 +67,10 @@ index 6540b2d6a1062d883811ce240c49d30d1925b291..67f7a71c70095dccd5a9f1a17a422c2d filteredSpawningCategories = List.of(); } diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java -index 8fd9c191e5b14fc7dd90e8f7229acd6de97e0f9e..268a4489cc5f7d5358c6cd96e0acbaf65852f7d3 100644 +index 5427f5e1f0416a8dfa3e9c38c3ce69d6e2bd37a6..acfecf37c6e3efc21d7f2194d9efed79146b1f1d 100644 --- a/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java -@@ -122,16 +122,26 @@ public final class NaturalSpawner { +@@ -116,16 +116,26 @@ public final class NaturalSpawner { static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) { return chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value(); } @@ -85,7 +85,7 @@ index 8fd9c191e5b14fc7dd90e8f7229acd6de97e0f9e..268a4489cc5f7d5358c6cd96e0acbaf6 + + public static List getFilteredSpawningCategories(NaturalSpawner.SpawnState spawnState, boolean spawnFriendlies, boolean spawnEnemies, boolean spawnPassives, ServerLevel level, boolean peacefulModeSwitch) { + // Leaves end - peaceful mode switch - LevelData worlddata = level.getLevelData(); // CraftBukkit - Other mob type spawn tick rate + net.minecraft.world.level.storage.LevelData worlddata = level.getLevelData(); // CraftBukkit - Other mob type spawn tick rate // CraftBukkit end List list = new ArrayList<>(SPAWNING_CATEGORIES.length); diff --git a/leaves-server/minecraft-patches/features/0074-Replay-Mod-API.patch b/leaves-server/minecraft-patches/features/0075-Replay-Mod-API.patch similarity index 94% rename from leaves-server/minecraft-patches/features/0074-Replay-Mod-API.patch rename to leaves-server/minecraft-patches/features/0075-Replay-Mod-API.patch index a41f44f1..f03ea5b5 100644 --- a/leaves-server/minecraft-patches/features/0074-Replay-Mod-API.patch +++ b/leaves-server/minecraft-patches/features/0075-Replay-Mod-API.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Replay Mod API This patch is Powered by ReplayMod(https://github.com/ReplayMod) diff --git a/net/minecraft/commands/CommandSourceStack.java b/net/minecraft/commands/CommandSourceStack.java -index c2b7164a1395842ab95428540782eeda4c7960b0..a00a59989c28429289fc4b65fb0605cc626de56c 100644 +index cb63e4c264a31788cd1405428af70f7a018910e9..a1e8f25b70b49590fd42b618fcd467cf306650af 100644 --- a/net/minecraft/commands/CommandSourceStack.java +++ b/net/minecraft/commands/CommandSourceStack.java -@@ -589,7 +589,7 @@ public class CommandSourceStack implements ExecutionCommandSource getOnlinePlayerNames() { @@ -81,10 +81,10 @@ index 514f8fbdeb776087608665c35de95294aadf5cf0..2f78ca86f46ea08fdcf4b8047d3d0b04 if (players.size() >= resultLimit) { return players; diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 7822cecf362cd8d430d90c0daac6e97c8a8d124b..438bbf36d4f80b38482b89e3ef59e9e48d0f62c2 100644 +index ca4fdcabbe6c0c57bfa13ef6d83bcd560baae8fc..2005719308a281128a5edc24a563df929418c6e3 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1639,7 +1639,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop !playerList.isOp(player.getGameProfile())) .map(player -> player.getGameProfile().getName()), diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 9a4bb86ebb893def457ad3fd896eb2a5e699f140..439bc4a93deb6fe134a9b1de4ca73a8c785d46db 100644 +index a2199f7aac4f44a70087dd90fe9330fcb8970772..9b1a65036392a965dc0ce93247dfc0cf53630034 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -2649,7 +2649,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2646,7 +2646,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe if (entity instanceof ServerPlayer serverPlayer) { ServerLevel.this.players.add(serverPlayer); // Leaves start - skip @@ -132,7 +132,7 @@ index 9a4bb86ebb893def457ad3fd896eb2a5e699f140..439bc4a93deb6fe134a9b1de4ca73a8c ServerLevel.this.realPlayers.add(serverPlayer); } // Leaves end - skip -@@ -2720,7 +2720,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2717,7 +2717,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe if (entity instanceof ServerPlayer serverPlayer) { ServerLevel.this.players.remove(serverPlayer); // Leaves start - skip @@ -142,7 +142,7 @@ index 9a4bb86ebb893def457ad3fd896eb2a5e699f140..439bc4a93deb6fe134a9b1de4ca73a8c } // Leaves end - skip diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 46d93b9c063cb056f3051ebe0f3558f5b4f55bea..5cbc1a5296aa2b6b267a8fa1f3edb9cf7857b8cf 100644 +index f2442fbf0cee7a2d1c3a155ec38d6a7eca36d6e8..e33776c039e36f55f0579b51b147d7be087839cf 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java @@ -131,6 +131,7 @@ public abstract class PlayerList { @@ -181,7 +181,7 @@ index 46d93b9c063cb056f3051ebe0f3558f5b4f55bea..5cbc1a5296aa2b6b267a8fa1f3edb9cf + player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit + playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + playerconnection.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities())); -+ playerconnection.send(new ClientboundSetHeldSlotPacket(player.getInventory().selected)); ++ playerconnection.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot())); + RecipeManager craftingmanager = this.server.getRecipeManager(); + playerconnection.send(new ClientboundUpdateRecipesPacket(craftingmanager.getSynchronizedItemProperties(), craftingmanager.getSynchronizedStonecutterRecipes())); + @@ -273,7 +273,7 @@ index 46d93b9c063cb056f3051ebe0f3558f5b4f55bea..5cbc1a5296aa2b6b267a8fa1f3edb9cf public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) { player.isRealPlayer = true; // Paper player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed -@@ -307,6 +421,7 @@ public abstract class PlayerList { +@@ -309,6 +423,7 @@ public abstract class PlayerList { // player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below this.players.add(player); @@ -281,7 +281,7 @@ index 46d93b9c063cb056f3051ebe0f3558f5b4f55bea..5cbc1a5296aa2b6b267a8fa1f3edb9cf this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot this.playersByUUID.put(player.getUUID(), player); // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below -@@ -376,6 +491,12 @@ public abstract class PlayerList { +@@ -380,6 +495,12 @@ public abstract class PlayerList { continue; } @@ -294,7 +294,7 @@ index 46d93b9c063cb056f3051ebe0f3558f5b4f55bea..5cbc1a5296aa2b6b267a8fa1f3edb9cf onlinePlayers.add(entityplayer1); // Paper - Use single player info update packet on join } // Paper start - Use single player info update packet on join -@@ -510,6 +631,43 @@ public abstract class PlayerList { +@@ -514,6 +635,43 @@ public abstract class PlayerList { } } @@ -335,10 +335,10 @@ index 46d93b9c063cb056f3051ebe0f3558f5b4f55bea..5cbc1a5296aa2b6b267a8fa1f3edb9cf + } + // Leaves stop - replay mod api + - public net.kyori.adventure.text.Component remove(ServerPlayer player) { // CraftBukkit - return string // Paper - return Component + public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player) { // CraftBukkit - return string // Paper - return Component // Paper start - Fix kick event leave message not being sent return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName()))); -@@ -585,6 +743,7 @@ public abstract class PlayerList { +@@ -589,6 +747,7 @@ public abstract class PlayerList { player.retireScheduler(); // Paper - Folia schedulers player.getAdvancements().stopListening(); this.players.remove(player); @@ -346,7 +346,7 @@ index 46d93b9c063cb056f3051ebe0f3558f5b4f55bea..5cbc1a5296aa2b6b267a8fa1f3edb9cf this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot this.server.getCustomBossEvents().onPlayerDisconnect(player); UUID uuid = player.getUUID(); -@@ -681,7 +840,7 @@ public abstract class PlayerList { +@@ -680,7 +839,7 @@ public abstract class PlayerList { // return this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile) // ? Component.translatable("multiplayer.disconnect.server_full") // : null; diff --git a/leaves-server/minecraft-patches/features/0075-Leaves-I18n.patch b/leaves-server/minecraft-patches/features/0076-Leaves-I18n.patch similarity index 94% rename from leaves-server/minecraft-patches/features/0075-Leaves-I18n.patch rename to leaves-server/minecraft-patches/features/0076-Leaves-I18n.patch index e097e17d..c49c36b0 100644 --- a/leaves-server/minecraft-patches/features/0075-Leaves-I18n.patch +++ b/leaves-server/minecraft-patches/features/0076-Leaves-I18n.patch @@ -52,10 +52,10 @@ index 7b9e2a1a208b46a69c16e6afd8b502259893574f..aa0db0cbbcfa079c43dbed6679abf999 DeprecatedTranslationsInfo deprecatedTranslationsInfo = DeprecatedTranslationsInfo.loadFromDefaultResource(); Map map = new HashMap<>(); diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 765521cae8bc1c65e3a390d018190646e39c4eb0..92f45558661007e761b48f59ff7f04d67f77f5ed 100644 +index e4946438d0c1fb9d2be616cb95768f890b32f286..8ed391f61b0eb50d26ce8250c652433e896d5ae4 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -227,6 +227,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -186,6 +186,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now org.leavesmc.leaves.LeavesConfig.init((java.io.File) options.valueOf("leaves-settings")); // Leaves - Server Config diff --git a/leaves-server/minecraft-patches/features/0076-Fix-minecraft-hopper-not-work-without-player.patch b/leaves-server/minecraft-patches/features/0077-Fix-minecraft-hopper-not-work-without-player.patch similarity index 80% rename from leaves-server/minecraft-patches/features/0076-Fix-minecraft-hopper-not-work-without-player.patch rename to leaves-server/minecraft-patches/features/0077-Fix-minecraft-hopper-not-work-without-player.patch index c9eac88e..00cd4117 100644 --- a/leaves-server/minecraft-patches/features/0076-Fix-minecraft-hopper-not-work-without-player.patch +++ b/leaves-server/minecraft-patches/features/0077-Fix-minecraft-hopper-not-work-without-player.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix minecraft hopper not work without player diff --git a/net/minecraft/world/entity/vehicle/MinecartHopper.java b/net/minecraft/world/entity/vehicle/MinecartHopper.java -index 8341e7f01606fca90e69384c16fc19bb9e20d1b7..deea1c6bcfbca04b0e9b45869eab5b8c5bbb17ca 100644 +index a56d9cdeb6589a053ffaaf2cd599a98ae0a0989a..eb94eb2fe717f6432e458deefb39f37600d890fc 100644 --- a/net/minecraft/world/entity/vehicle/MinecartHopper.java +++ b/net/minecraft/world/entity/vehicle/MinecartHopper.java -@@ -99,6 +99,13 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper +@@ -100,6 +100,13 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper } } diff --git a/leaves-server/minecraft-patches/features/0077-RNG-Fishing.patch b/leaves-server/minecraft-patches/features/0078-RNG-Fishing.patch similarity index 88% rename from leaves-server/minecraft-patches/features/0077-RNG-Fishing.patch rename to leaves-server/minecraft-patches/features/0078-RNG-Fishing.patch index a6536b8c..ec1da438 100644 --- a/leaves-server/minecraft-patches/features/0077-RNG-Fishing.patch +++ b/leaves-server/minecraft-patches/features/0078-RNG-Fishing.patch @@ -5,10 +5,10 @@ Subject: [PATCH] RNG Fishing diff --git a/net/minecraft/world/entity/projectile/FishingHook.java b/net/minecraft/world/entity/projectile/FishingHook.java -index f2bf0cdbd29438ca51b74ae2fcdf49dba0d52804..1d3c2be401d9239b8e6cabfe016518ffcffcb83b 100644 +index f82f37d498f99ce38f72a63d051721c6dab9f2ca..0014ede48956facc87940f4b1d5f8ac72af052bb 100644 --- a/net/minecraft/world/entity/projectile/FishingHook.java +++ b/net/minecraft/world/entity/projectile/FishingHook.java -@@ -525,7 +525,7 @@ public class FishingHook extends Projectile { +@@ -518,7 +518,7 @@ public class FishingHook extends Projectile { .withLuck(this.luck + playerOwner.getLuck()) .create(LootContextParamSets.FISHING); LootTable lootTable = this.level().getServer().reloadableRegistries().getLootTable(BuiltInLootTables.FISHING); diff --git a/leaves-server/minecraft-patches/features/0079-Spider-jockeys-drop-gapples.patch b/leaves-server/minecraft-patches/features/0079-Spider-jockeys-drop-gapples.patch deleted file mode 100644 index f0a29487..00000000 --- a/leaves-server/minecraft-patches/features/0079-Spider-jockeys-drop-gapples.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Tue, 5 Sep 2023 08:49:01 +0800 -Subject: [PATCH] Spider jockeys drop gapples - - -diff --git a/net/minecraft/world/entity/monster/Spider.java b/net/minecraft/world/entity/monster/Spider.java -index af0305079a367899708ee2bbac82aefaa9129d2f..e9a4734cddc33785ca6811f8f566904ace78fd78 100644 ---- a/net/minecraft/world/entity/monster/Spider.java -+++ b/net/minecraft/world/entity/monster/Spider.java -@@ -139,6 +139,18 @@ public class Spider extends Monster { - this.entityData.set(DATA_FLAGS_ID, b); - } - -+ // Leaves start - spider jockeys drop gapples -+ @Override -+ protected void dropFromLootTable(net.minecraft.server.level.ServerLevel wolrd, DamageSource damageSource, boolean causedByPlayer) { -+ super.dropFromLootTable(wolrd, damageSource, causedByPlayer); -+ if (org.leavesmc.leaves.LeavesConfig.modify.spiderJockeysDropGapples > 0.0D) { -+ if (this.hasPassenger(entity -> entity.getType() == EntityType.SKELETON) && this.random.nextDouble() < org.leavesmc.leaves.LeavesConfig.modify.spiderJockeysDropGapples) { -+ this.spawnAtLocation(wolrd, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.ENCHANTED_GOLDEN_APPLE)); -+ } -+ } -+ } -+ // Leaves end - spider jockeys drop gapples -+ - @Nullable - @Override - public SpawnGroupData finalizeSpawn( diff --git a/leaves-server/minecraft-patches/features/0078-Wool-Hopper-Counter.patch b/leaves-server/minecraft-patches/features/0079-Wool-Hopper-Counter.patch similarity index 91% rename from leaves-server/minecraft-patches/features/0078-Wool-Hopper-Counter.patch rename to leaves-server/minecraft-patches/features/0079-Wool-Hopper-Counter.patch index a4123690..6dc4546f 100644 --- a/leaves-server/minecraft-patches/features/0078-Wool-Hopper-Counter.patch +++ b/leaves-server/minecraft-patches/features/0079-Wool-Hopper-Counter.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Wool Hopper Counter This patch is Powered by fabric-carpet(https://github.com/gnembon/fabric-carpet) diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 50bc72f736e9e7a9839a853254a81f9add03bacf..bd8d949ff0f3d0b6a893d3b3ae608da380e715f0 100644 +index a2fe5fdf50ae731e423821a0d1c52141b478e0be..7140571ef324f823942bc2c528cb66dac9e91d94 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -428,6 +428,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -432,6 +432,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen // Paper end - Perf: Optimize Hoppers private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) { @@ -23,7 +23,7 @@ index 50bc72f736e9e7a9839a853254a81f9add03bacf..bd8d949ff0f3d0b6a893d3b3ae608da3 Container attachedContainer = getAttachedContainer(level, pos, blockEntity); if (attachedContainer == null) { return false; -@@ -494,6 +501,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -498,6 +505,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } } diff --git a/leaves-server/minecraft-patches/features/0080-Spider-jockeys-drop-gapples.patch b/leaves-server/minecraft-patches/features/0080-Spider-jockeys-drop-gapples.patch new file mode 100644 index 00000000..afcde1f9 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0080-Spider-jockeys-drop-gapples.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: violetc <58360096+s-yh-china@users.noreply.github.com> +Date: Tue, 5 Sep 2023 08:49:01 +0800 +Subject: [PATCH] Spider jockeys drop gapples + + +diff --git a/net/minecraft/world/entity/monster/Skeleton.java b/net/minecraft/world/entity/monster/Skeleton.java +index 48f26ed693b43e3f65f1559ba69b3d7249664f71..7ee1aa2d41cadefb0ee0a5f17a04ed52da60de86 100644 +--- a/net/minecraft/world/entity/monster/Skeleton.java ++++ b/net/minecraft/world/entity/monster/Skeleton.java +@@ -139,4 +139,16 @@ public class Skeleton extends AbstractSkeleton { + this.spawnAtLocation(level, Items.SKELETON_SKULL); + } + } ++ ++ // Leaves start - spider jockeys drop gapples ++ @Override ++ protected void dropFromLootTable(ServerLevel level, DamageSource damageSource, boolean causedByPlayer) { ++ super.dropFromLootTable(level, damageSource, causedByPlayer); ++ if (org.leavesmc.leaves.LeavesConfig.modify.spiderJockeysDropGapples > 0.0D) { ++ if (this.getRootVehicle().getType() == EntityType.SPIDER && this.random.nextDouble() < org.leavesmc.leaves.LeavesConfig.modify.spiderJockeysDropGapples) { ++ this.spawnAtLocation(level, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.ENCHANTED_GOLDEN_APPLE)); ++ } ++ } ++ } ++ // Leaves end - spider jockeys drop gapples + } +diff --git a/net/minecraft/world/entity/monster/Spider.java b/net/minecraft/world/entity/monster/Spider.java +index 60c4ac37bb491af13f9f9bf730b85bbe544cf81d..aaba82e591ac380314a1b7c59e4e04cca9864d31 100644 +--- a/net/minecraft/world/entity/monster/Spider.java ++++ b/net/minecraft/world/entity/monster/Spider.java +@@ -139,6 +139,18 @@ public class Spider extends Monster { + this.entityData.set(DATA_FLAGS_ID, b); + } + ++ // Leaves start - spider jockeys drop gapples ++ @Override ++ protected void dropFromLootTable(net.minecraft.server.level.ServerLevel level, DamageSource damageSource, boolean causedByPlayer) { ++ super.dropFromLootTable(level, damageSource, causedByPlayer); ++ if (org.leavesmc.leaves.LeavesConfig.modify.spiderJockeysDropGapples > 0.0D) { ++ if (this.hasPassenger(entity -> entity.getType() == EntityType.SKELETON) && this.random.nextDouble() < org.leavesmc.leaves.LeavesConfig.modify.spiderJockeysDropGapples) { ++ this.spawnAtLocation(level, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.ENCHANTED_GOLDEN_APPLE)); ++ } ++ } ++ } ++ // Leaves end - spider jockeys drop gapples ++ + @Nullable + @Override + public SpawnGroupData finalizeSpawn( diff --git a/leaves-server/minecraft-patches/features/0080-Force-Void-Trade.patch b/leaves-server/minecraft-patches/features/0081-Force-Void-Trade.patch similarity index 87% rename from leaves-server/minecraft-patches/features/0080-Force-Void-Trade.patch rename to leaves-server/minecraft-patches/features/0081-Force-Void-Trade.patch index 7b391dc9..28a30ddb 100644 --- a/leaves-server/minecraft-patches/features/0080-Force-Void-Trade.patch +++ b/leaves-server/minecraft-patches/features/0081-Force-Void-Trade.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Force Void Trade diff --git a/net/minecraft/world/entity/npc/AbstractVillager.java b/net/minecraft/world/entity/npc/AbstractVillager.java -index 18a087a52070b9bdee4d02ff3fc6a3c063e444d4..dba596ac7a26401a6f4d8726bcea0caf067af10e 100644 +index a375fad192cc09ba83775d5e37c1bb351730e6c4..203e6819aa39de7e932125acb8a0de224918bb6f 100644 --- a/net/minecraft/world/entity/npc/AbstractVillager.java +++ b/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -60,6 +60,7 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa +@@ -43,6 +43,7 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa @Nullable protected MerchantOffers offers; private final SimpleContainer inventory = new SimpleContainer(8, (org.bukkit.craftbukkit.entity.CraftAbstractVillager) this.getBukkitEntity()); // CraftBukkit - add argument @@ -16,7 +16,7 @@ index 18a087a52070b9bdee4d02ff3fc6a3c063e444d4..dba596ac7a26401a6f4d8726bcea0caf public AbstractVillager(EntityType entityType, Level level) { super(entityType, level); -@@ -154,7 +155,13 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa +@@ -144,7 +145,13 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa @Override public void processTrade(MerchantOffer offer, @Nullable io.papermc.paper.event.player.PlayerPurchaseEvent event) { // The MerchantRecipe passed in here is the one set by the PlayerPurchaseEvent if (event == null || event.willIncreaseTradeUses()) { @@ -31,7 +31,7 @@ index 18a087a52070b9bdee4d02ff3fc6a3c063e444d4..dba596ac7a26401a6f4d8726bcea0caf } if (event == null || event.isRewardingExp()) { this.rewardTradeXp(offer); -@@ -166,7 +173,7 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa +@@ -156,7 +163,7 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa @Override public void notifyTrade(MerchantOffer offer) { // offer.increaseUses(); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent @@ -40,7 +40,7 @@ index 18a087a52070b9bdee4d02ff3fc6a3c063e444d4..dba596ac7a26401a6f4d8726bcea0caf // this.rewardTradeXp(offer); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent if (this.tradingPlayer instanceof ServerPlayer) { CriteriaTriggers.TRADE.trigger((ServerPlayer)this.tradingPlayer, this, offer.getResult()); -@@ -183,7 +190,7 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa +@@ -173,7 +180,7 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa @Override public void notifyTradeUpdated(ItemStack stack) { if (!this.level().isClientSide && this.ambientSoundTime > -this.getAmbientSoundInterval() + 20) { @@ -49,7 +49,7 @@ index 18a087a52070b9bdee4d02ff3fc6a3c063e444d4..dba596ac7a26401a6f4d8726bcea0caf this.makeSound(this.getTradeUpdatedSound(!stack.isEmpty())); } } -@@ -235,6 +242,12 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa +@@ -219,6 +226,12 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa } protected void stopTrading() { @@ -62,7 +62,7 @@ index 18a087a52070b9bdee4d02ff3fc6a3c063e444d4..dba596ac7a26401a6f4d8726bcea0caf this.setTradingPlayer(null); } -@@ -313,4 +326,10 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa +@@ -297,4 +310,10 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa public boolean stillValid(Player player) { return this.getTradingPlayer() == player && this.isAlive() && player.canInteractWithEntity(this, 4.0); } @@ -74,18 +74,18 @@ index 18a087a52070b9bdee4d02ff3fc6a3c063e444d4..dba596ac7a26401a6f4d8726bcea0caf + // Leaves end - force void trade } diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java -index 6b565fcf91e1d94b649dac90bf3c923930d252f8..31c2fb7780b822bf63543c4526739b9d3faad7d8 100644 +index 956b949b42a7041290838dde816d3b79e1f9e0d4..1b906f04852637046f03d71f54f950f04c086c46 100644 --- a/net/minecraft/world/entity/npc/Villager.java +++ b/net/minecraft/world/entity/npc/Villager.java -@@ -380,6 +380,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -383,6 +383,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } private void startTrading(Player player) { + this.voidTrade = false; // Leaves - force void trade this.updateSpecialPrices(player); this.setTradingPlayer(player); - this.openTradingScreen(player, this.getDisplayName(), this.getVillagerData().getLevel()); -@@ -632,8 +633,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.openTradingScreen(player, this.getDisplayName(), this.getVillagerData().level()); +@@ -622,8 +623,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @Override protected void rewardTradeXp(MerchantOffer offer) { int i = 3 + this.random.nextInt(4); @@ -101,10 +101,10 @@ index 6b565fcf91e1d94b649dac90bf3c923930d252f8..31c2fb7780b822bf63543c4526739b9d this.updateMerchantTimer = 40; this.increaseProfessionLevelOnUpdate = true; diff --git a/net/minecraft/world/entity/npc/WanderingTrader.java b/net/minecraft/world/entity/npc/WanderingTrader.java -index 6655d06e2011e20e7346dfe57527795269094d8a..8ebf885ceb13a8b5e5b3db74fc7ee859d10f3845 100644 +index 70cc20483905d3877e2ffb51afb4902bd59f0cd0..066d18609f7f8aa5c14e95e09b454cb7d15f2ed7 100644 --- a/net/minecraft/world/entity/npc/WanderingTrader.java +++ b/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -133,9 +133,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -123,9 +123,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill return InteractionResult.CONSUME; } @@ -119,7 +119,7 @@ index 6655d06e2011e20e7346dfe57527795269094d8a..8ebf885ceb13a8b5e5b3db74fc7ee859 return InteractionResult.SUCCESS; } else { diff --git a/net/minecraft/world/inventory/MerchantMenu.java b/net/minecraft/world/inventory/MerchantMenu.java -index 3019790d5eccef23c710e77615243551fcc676b0..9a87c729dd7289dc3cccfcf50087db7dc354f895 100644 +index d59f67ffe34201c63e3d9706a4434f33b6732edb..bee1d5c30a6ee9b14a23fbcf1c479417f1776ddb 100644 --- a/net/minecraft/world/inventory/MerchantMenu.java +++ b/net/minecraft/world/inventory/MerchantMenu.java @@ -25,7 +25,7 @@ public class MerchantMenu extends AbstractContainerMenu { @@ -132,7 +132,7 @@ index 3019790d5eccef23c710e77615243551fcc676b0..9a87c729dd7289dc3cccfcf50087db7d private int merchantLevel; private boolean showProgressBar; diff --git a/net/minecraft/world/item/trading/MerchantOffer.java b/net/minecraft/world/item/trading/MerchantOffer.java -index 6c06350751db7543d5bde7723121d9d9dbb79071..262cfdd05f013b2bbc2066ad4f0625ae291213b9 100644 +index 9333c63f217e1207eced37c5be150e192f2fcc3e..0b1a086d3f101b42d95304c69f9e69f4c6c7d906 100644 --- a/net/minecraft/world/item/trading/MerchantOffer.java +++ b/net/minecraft/world/item/trading/MerchantOffer.java @@ -39,6 +39,7 @@ public class MerchantOffer { @@ -178,10 +178,10 @@ index 6c06350751db7543d5bde7723121d9d9dbb79071..262cfdd05f013b2bbc2066ad4f0625ae public void setToOutOfStock() { diff --git a/net/minecraft/world/level/block/EndGatewayBlock.java b/net/minecraft/world/level/block/EndGatewayBlock.java -index 84a1bd5e40e635962d795506861447851e443eee..5c6bc04c241f13a8c09527a39f89fa52feb0eb76 100644 +index 68914268ca9350a6c1d794e011e1f9a8aecd609c..f22d502df5f444703a248fff50c864d2924c4549 100644 --- a/net/minecraft/world/level/block/EndGatewayBlock.java +++ b/net/minecraft/world/level/block/EndGatewayBlock.java -@@ -108,6 +108,17 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal { +@@ -109,6 +109,17 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal { public TeleportTransition getPortalDestination(ServerLevel level, Entity entity, BlockPos pos) { if (level.getBlockEntity(pos) instanceof TheEndGatewayBlockEntity theEndGatewayBlockEntity) { Vec3 portalPosition = theEndGatewayBlockEntity.getPortalPosition(level, pos); diff --git a/leaves-server/minecraft-patches/features/0081-Villager-infinite-discounts.patch b/leaves-server/minecraft-patches/features/0082-Villager-infinite-discounts.patch similarity index 100% rename from leaves-server/minecraft-patches/features/0081-Villager-infinite-discounts.patch rename to leaves-server/minecraft-patches/features/0082-Villager-infinite-discounts.patch diff --git a/leaves-server/minecraft-patches/features/0082-CCE-update-suppression.patch b/leaves-server/minecraft-patches/features/0083-CCE-update-suppression.patch similarity index 87% rename from leaves-server/minecraft-patches/features/0082-CCE-update-suppression.patch rename to leaves-server/minecraft-patches/features/0083-CCE-update-suppression.patch index 1c5c1122..9390ac45 100644 --- a/leaves-server/minecraft-patches/features/0082-CCE-update-suppression.patch +++ b/leaves-server/minecraft-patches/features/0083-CCE-update-suppression.patch @@ -5,10 +5,10 @@ Subject: [PATCH] CCE update suppression diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java -index 7794e66211af34ecca8524d3ca7e0d928f0ab0eb..fca50f68625050daabcae3a3b615cf88cce41111 100644 +index fef902077b69830b570d1adf86603f45b4f6a839..c34318fdc454ea31655c3c3aa5dbedd3d922ee24 100644 --- a/net/minecraft/world/level/block/ShulkerBoxBlock.java +++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java -@@ -236,7 +236,9 @@ public class ShulkerBoxBlock extends BaseEntityBlock { +@@ -185,7 +185,9 @@ public class ShulkerBoxBlock extends BaseEntityBlock { protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { // Leaves start - fix update suppression crash try { @@ -19,7 +19,7 @@ index 7794e66211af34ecca8524d3ca7e0d928f0ab0eb..fca50f68625050daabcae3a3b615cf88 } catch (ClassCastException ex) { if (org.leavesmc.leaves.LeavesConfig.modify.updateSuppressionCrashFix) { throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, this); -@@ -244,7 +246,6 @@ public class ShulkerBoxBlock extends BaseEntityBlock { +@@ -193,7 +195,6 @@ public class ShulkerBoxBlock extends BaseEntityBlock { throw ex; } } diff --git a/leaves-server/minecraft-patches/features/0083-Disable-offline-warn-if-use-proxy.patch b/leaves-server/minecraft-patches/features/0084-Disable-offline-warn-if-use-proxy.patch similarity index 88% rename from leaves-server/minecraft-patches/features/0083-Disable-offline-warn-if-use-proxy.patch rename to leaves-server/minecraft-patches/features/0084-Disable-offline-warn-if-use-proxy.patch index fa58f1c8..3cade859 100644 --- a/leaves-server/minecraft-patches/features/0083-Disable-offline-warn-if-use-proxy.patch +++ b/leaves-server/minecraft-patches/features/0084-Disable-offline-warn-if-use-proxy.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Disable offline warn if use proxy diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 92f45558661007e761b48f59ff7f04d67f77f5ed..c301cc8b76295750b8dd0c6d7f8e5b11a275bb15 100644 +index 8ed391f61b0eb50d26ce8250c652433e896d5ae4..46eabb498758052cc1ce1b4f46d9c033df14b8ef 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -288,7 +288,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -246,7 +246,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface String proxyFlavor = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "Velocity" : "BungeeCord"; String proxyLink = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "https://docs.papermc.io/velocity/security" : "http://www.spigotmc.org/wiki/firewall-guide/"; // Paper end - Add Velocity IP Forwarding Support diff --git a/leaves-server/minecraft-patches/features/0084-Armor-stand-cant-kill-by-mob-projectile.patch b/leaves-server/minecraft-patches/features/0085-Armor-stand-cant-kill-by-mob-projectile.patch similarity index 89% rename from leaves-server/minecraft-patches/features/0084-Armor-stand-cant-kill-by-mob-projectile.patch rename to leaves-server/minecraft-patches/features/0085-Armor-stand-cant-kill-by-mob-projectile.patch index 88b63fcf..8a2efc45 100644 --- a/leaves-server/minecraft-patches/features/0084-Armor-stand-cant-kill-by-mob-projectile.patch +++ b/leaves-server/minecraft-patches/features/0085-Armor-stand-cant-kill-by-mob-projectile.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Armor stand cant kill by mob projectile diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java -index dfae614a67476d649be2a8c2cd8258abe12842e3..cb42b92dd66305be342b7bd7457fda504e6165e9 100644 +index f09bf1f8b23aae530b14129b7a56c96285ef2cf1..a09bd2121d457cace3e38f321985cff8817b2a2f 100644 --- a/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -484,6 +484,15 @@ public class ArmorStand extends LivingEntity { +@@ -414,6 +414,15 @@ public class ArmorStand extends LivingEntity { // CraftBukkit end boolean isCanBreakArmorStand = damageSource.is(DamageTypeTags.CAN_BREAK_ARMOR_STAND); boolean isAlwaysKillsArmorStands = damageSource.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS); diff --git a/leaves-server/minecraft-patches/features/0085-Make-Item-tick-vanilla.patch b/leaves-server/minecraft-patches/features/0086-Make-Item-tick-vanilla.patch similarity index 81% rename from leaves-server/minecraft-patches/features/0085-Make-Item-tick-vanilla.patch rename to leaves-server/minecraft-patches/features/0086-Make-Item-tick-vanilla.patch index e4e910de..22d6f7dd 100644 --- a/leaves-server/minecraft-patches/features/0085-Make-Item-tick-vanilla.patch +++ b/leaves-server/minecraft-patches/features/0086-Make-Item-tick-vanilla.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make Item tick vanilla diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java -index 4f5db8203189a413f410fe7648e4995bae171918..e3cdb823b6d76e62725b6428651dacfe20fc4154 100644 +index 0cb2d5cd37171cd6e01748ed3d2ce99da1a15e3f..71c5dd7e58ecc3f4dce0c942a8ce88cb8898cf99 100644 --- a/net/minecraft/world/entity/item/ItemEntity.java +++ b/net/minecraft/world/entity/item/ItemEntity.java -@@ -133,6 +133,9 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -140,6 +140,9 @@ public class ItemEntity extends Entity implements TraceableEntity { // Paper start - EAR 2 @Override public void inactiveTick() { @@ -18,7 +18,7 @@ index 4f5db8203189a413f410fe7648e4995bae171918..e3cdb823b6d76e62725b6428651dacfe super.inactiveTick(); if (this.pickupDelay > 0 && this.pickupDelay != 32767) { this.pickupDelay--; -@@ -150,6 +153,8 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -157,6 +160,8 @@ public class ItemEntity extends Entity implements TraceableEntity { // CraftBukkit end this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause } diff --git a/leaves-server/minecraft-patches/features/0086-Copper-Bulb-1-gt-delay.patch b/leaves-server/minecraft-patches/features/0087-Copper-Bulb-1-gt-delay.patch similarity index 96% rename from leaves-server/minecraft-patches/features/0086-Copper-Bulb-1-gt-delay.patch rename to leaves-server/minecraft-patches/features/0087-Copper-Bulb-1-gt-delay.patch index 7b91a05d..517340ee 100644 --- a/leaves-server/minecraft-patches/features/0086-Copper-Bulb-1-gt-delay.patch +++ b/leaves-server/minecraft-patches/features/0087-Copper-Bulb-1-gt-delay.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Copper Bulb 1 gt delay diff --git a/net/minecraft/world/level/block/CopperBulbBlock.java b/net/minecraft/world/level/block/CopperBulbBlock.java -index d3d3ad8bb33313e735eec559f854fb76bdf84cc2..4e346b1e77042a17bb28fb510196ff3bbde5bc92 100644 +index 25caeb117d9a49fa00f46ec895a35dee8242aacd..ce1d34f28f9318b741df074fccddfe91f16b57cf 100644 --- a/net/minecraft/world/level/block/CopperBulbBlock.java +++ b/net/minecraft/world/level/block/CopperBulbBlock.java @@ -32,14 +32,26 @@ public class CopperBulbBlock extends Block { diff --git a/leaves-server/minecraft-patches/features/0087-Crafter-1-gt-delay.patch b/leaves-server/minecraft-patches/features/0088-Crafter-1-gt-delay.patch similarity index 80% rename from leaves-server/minecraft-patches/features/0087-Crafter-1-gt-delay.patch rename to leaves-server/minecraft-patches/features/0088-Crafter-1-gt-delay.patch index f5b7ab2c..92a5bf4a 100644 --- a/leaves-server/minecraft-patches/features/0087-Crafter-1-gt-delay.patch +++ b/leaves-server/minecraft-patches/features/0088-Crafter-1-gt-delay.patch @@ -5,19 +5,19 @@ Subject: [PATCH] Crafter 1 gt delay diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java -index 5f5966278faf86ed9b28955c80ba845c0cb75595..f5e3c1e4e13d14eac45622742391495ec6b3d925 100644 +index 33e24f2c3b63b2d3b55dfae2f2e55869abeed055..3ce56a24e131c3ea4c6d568e3f7bd2de8076ac60 100644 --- a/net/minecraft/world/level/block/CrafterBlock.java +++ b/net/minecraft/world/level/block/CrafterBlock.java -@@ -82,7 +82,7 @@ public class CrafterBlock extends BaseEntityBlock { +@@ -75,7 +75,7 @@ public class CrafterBlock extends BaseEntityBlock { boolean triggeredValue = state.getValue(TRIGGERED); BlockEntity blockEntity = level.getBlockEntity(pos); if (hasNeighborSignal && !triggeredValue) { - level.scheduleTick(pos, this, 4); + level.scheduleTick(pos, this, !org.leavesmc.leaves.LeavesConfig.modify.oldMC.crafter1gt ? 4 : 1); // Leaves - crafter 1 gt delay - level.setBlock(pos, state.setValue(TRIGGERED, Boolean.valueOf(true)), 2); + level.setBlock(pos, state.setValue(TRIGGERED, true), 2); this.setBlockEntityTriggered(blockEntity, true); } else if (!hasNeighborSignal && triggeredValue) { -@@ -132,7 +132,7 @@ public class CrafterBlock extends BaseEntityBlock { +@@ -125,7 +125,7 @@ public class CrafterBlock extends BaseEntityBlock { @Override public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { if (state.getValue(TRIGGERED)) { diff --git a/leaves-server/minecraft-patches/features/0088-More-Region-Format-Support.patch b/leaves-server/minecraft-patches/features/0089-More-Region-Format-Support.patch similarity index 90% rename from leaves-server/minecraft-patches/features/0088-More-Region-Format-Support.patch rename to leaves-server/minecraft-patches/features/0089-More-Region-Format-Support.patch index 615292dd..37db07b3 100644 --- a/leaves-server/minecraft-patches/features/0088-More-Region-Format-Support.patch +++ b/leaves-server/minecraft-patches/features/0089-More-Region-Format-Support.patch @@ -21,7 +21,7 @@ index a814512fcfb85312474ae2c2c21443843bf57831..2b0349568f38321c893a8ffa16607350 public MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite( final int chunkX, final int chunkZ, final CompoundTag compound diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java -index 98fbc5c8044bd945d64569f13412a6e7e49a4e7f..01e9a0076632f3be8bd15fa6793ed6296fe4c2bb 100644 +index 709df35246fb328cda21679b53d44d9f96206cb3..8fa38dcff5987e109423a2ed0a86abc9c5c195cd 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java @@ -1260,7 +1260,7 @@ public final class MoonriseRegionFileIO { @@ -54,10 +54,10 @@ index 51c126735ace8fdde89ad97b5cab62f244212db0..a6573e327ace16b7ea320eb1440ffcbc + public void moonrise$write(final org.leavesmc.leaves.region.IRegionFile regionFile) throws IOException; // Leaves - more region format } diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 438bbf36d4f80b38482b89e3ef59e9e48d0f62c2..164b8dc3f247aedd37bce24a7acb6ab1858e7d20 100644 +index 2005719308a281128a5edc24a563df929418c6e3..f1681577f27a618338cae1634094e728c98fc3ff 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -951,10 +951,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> progressMap = Reference2FloatMaps.synchronize(new Reference2FloatOpenHashMap<>()); volatile Component status = Component.translatable("optimizeWorld.stage.counting"); @@ -83,7 +83,7 @@ index e0bcda2ddea0d6633445a7440fbf0d18e50a7653..cb2cd0b4f4e5f2c85cdd9e73b1d2a34d final DimensionDataStorage overworldDataStorage; public WorldUpgrader( -@@ -261,7 +261,7 @@ public class WorldUpgrader implements AutoCloseable { +@@ -272,7 +272,7 @@ public class WorldUpgrader implements AutoCloseable { } private static List getAllChunkPositions(RegionStorageInfo regionStorageInfo, Path path) { @@ -92,7 +92,7 @@ index e0bcda2ddea0d6633445a7440fbf0d18e50a7653..cb2cd0b4f4e5f2c85cdd9e73b1d2a34d if (files == null) { return List.of(); } else { -@@ -274,7 +274,7 @@ public class WorldUpgrader implements AutoCloseable { +@@ -285,7 +285,7 @@ public class WorldUpgrader implements AutoCloseable { int i1 = Integer.parseInt(matcher.group(2)) << 5; List list1 = Lists.newArrayList(); @@ -101,7 +101,7 @@ index e0bcda2ddea0d6633445a7440fbf0d18e50a7653..cb2cd0b4f4e5f2c85cdd9e73b1d2a34d for (int i2 = 0; i2 < 32; i2++) { for (int i3 = 0; i3 < 32; i3++) { ChunkPos chunkPos = new ChunkPos(i2 + i, i3 + i1); -@@ -322,7 +322,7 @@ public class WorldUpgrader implements AutoCloseable { +@@ -333,7 +333,7 @@ public class WorldUpgrader implements AutoCloseable { protected abstract boolean tryProcessOnePosition(T chunkStorage, ChunkPos chunkPos, ResourceKey dimension); @@ -110,7 +110,7 @@ index e0bcda2ddea0d6633445a7440fbf0d18e50a7653..cb2cd0b4f4e5f2c85cdd9e73b1d2a34d if (WorldUpgrader.this.recreateRegionFiles) { if (this.previousWriteFuture != null) { this.previousWriteFuture.join(); -@@ -424,7 +424,7 @@ public class WorldUpgrader implements AutoCloseable { +@@ -438,7 +438,7 @@ public class WorldUpgrader implements AutoCloseable { } } @@ -120,7 +120,7 @@ index e0bcda2ddea0d6633445a7440fbf0d18e50a7653..cb2cd0b4f4e5f2c85cdd9e73b1d2a34d class PoiUpgrader extends WorldUpgrader.SimpleRegionStorageUpgrader { diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java -index 0c41177462cca5c4bbab6490e323b9535fd6300f..bb6b482271da00586acb438fd7648f8f4cd5586b 100644 +index 22f3aa1674664906e8ec45372d758d79017e3987..1d9b2a315d3c18df3c0dfc0e8daac18c4d7462b7 100644 --- a/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/net/minecraft/world/level/chunk/storage/RegionFile.java @@ -22,7 +22,7 @@ import net.minecraft.util.profiling.jfr.JvmProfiler; @@ -132,16 +132,16 @@ index 0c41177462cca5c4bbab6490e323b9535fd6300f..bb6b482271da00586acb438fd7648f8f private static final Logger LOGGER = LogUtils.getLogger(); public static final int MAX_CHUNK_SIZE = 500 * 1024 * 1024; // Paper - don't write garbage data to disk if writing serialization fails private static final int SECTOR_BYTES = 4096; -@@ -124,7 +124,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche +@@ -130,7 +130,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche + return this.recalculateCount.get(); } - // note: only call for CHUNK regionfiles - boolean recalculateHeader() throws IOException { + public boolean recalculateHeader() throws IOException { // Leaves - more region format if (!this.canRecalcHeader) { return false; } -@@ -786,7 +786,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche +@@ -794,7 +794,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche } } @@ -150,7 +150,7 @@ index 0c41177462cca5c4bbab6490e323b9535fd6300f..bb6b482271da00586acb438fd7648f8f int offsetIndex = getOffsetIndex(chunkPos); int i = this.offsets.get(offsetIndex); int sectorNumber = getSectorNumber(i); -@@ -904,7 +904,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche +@@ -912,7 +912,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche } @Override @@ -159,7 +159,7 @@ index 0c41177462cca5c4bbab6490e323b9535fd6300f..bb6b482271da00586acb438fd7648f8f regionFile.write(this.pos, ByteBuffer.wrap(this.buf, 0, this.count)); } // Paper end - rewrite chunk system -@@ -970,11 +970,11 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche +@@ -978,11 +978,11 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche return (x & 31) + (z & 31) * 32; } @@ -173,7 +173,7 @@ index 0c41177462cca5c4bbab6490e323b9535fd6300f..bb6b482271da00586acb438fd7648f8f final int offset = getChunkIndex(x, z); boolean previous = this.oversized[offset] == 1; this.oversized[offset] = (byte) (oversized ? 1 : 0); -@@ -1013,7 +1013,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche +@@ -1021,7 +1021,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche return this.path.getParent().resolve(this.path.getFileName().toString().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); } @@ -183,7 +183,7 @@ index 0c41177462cca5c4bbab6490e323b9535fd6300f..bb6b482271da00586acb438fd7648f8f try (DataInputStream out = new DataInputStream(new java.io.BufferedInputStream(new java.util.zip.InflaterInputStream(Files.newInputStream(file))))) { return net.minecraft.nbt.NbtIo.read((java.io.DataInput) out); diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d17610260bb3 100644 +index 384f2cd090d6d23bd1308d6e82c24338f2bf55d1..7b86212082f49bef0c087c8e080874fe1d4f268d 100644 --- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java @@ -18,7 +18,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise @@ -291,7 +291,16 @@ index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d176 final DataInputStream input = regionFile == null ? null : regionFile.getChunkDataInputStream(new ChunkPos(chunkX, chunkZ)); -@@ -237,7 +247,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -238,7 +248,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise + + final ChunkPos pos = new ChunkPos(chunkX, chunkZ); + final ChunkPos headerChunkPos = SerializableChunkData.getChunkCoordinate(ret); +- final RegionFile regionFile = this.getRegionFile(pos); ++ final org.leavesmc.leaves.region.IRegionFile regionFile = this.getRegionFile(pos); + + if (regionFile.getRecalculateCount() != readData.recalculateCount()) { + return null; +@@ -262,7 +272,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise } // Paper end - rewrite chunk system // Paper start - rewrite chunk system @@ -300,7 +309,7 @@ index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d176 return this.getRegionFile(chunkcoordintpair, false); } // Paper end - rewrite chunk system -@@ -249,7 +259,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -274,7 +284,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise this.isChunkData = isChunkDataFolder(this.folder); // Paper - recalculate region file headers } @@ -309,7 +318,7 @@ index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d176 // Paper start - rewrite chunk system if (existingOnly) { return this.moonrise$getRegionFileIfExists(chunkPos.x, chunkPos.z); -@@ -257,7 +267,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -282,7 +292,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise synchronized (this) { final long key = ChunkPos.asLong(chunkPos.x >> REGION_SHIFT, chunkPos.z >> REGION_SHIFT); @@ -318,7 +327,7 @@ index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d176 if (ret != null) { return ret; } -@@ -266,13 +276,22 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -291,13 +301,22 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise this.regionCache.removeLast().close(); } @@ -343,7 +352,7 @@ index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d176 this.regionCache.putAndMoveToFirst(key, ret); -@@ -286,7 +305,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -311,7 +330,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); } @@ -352,7 +361,7 @@ index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d176 synchronized (regionfile) { try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) { CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); -@@ -321,7 +340,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -346,7 +365,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise @Nullable public CompoundTag read(ChunkPos chunkPos) throws IOException { // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing @@ -361,7 +370,7 @@ index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d176 if (regionFile == null) { return null; } -@@ -360,7 +379,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -385,7 +404,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise public void scanChunk(ChunkPos chunkPos, StreamTagVisitor visitor) throws IOException { // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing @@ -370,7 +379,7 @@ index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d176 if (regionFile == null) { return; } -@@ -374,7 +393,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -399,7 +418,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise } public void write(ChunkPos chunkPos, @Nullable CompoundTag chunkData) throws IOException { // Paper - rewrite chunk system - public @@ -379,7 +388,7 @@ index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d176 // Paper start - rewrite chunk system if (regionFile == null) { // if the RegionFile doesn't exist, no point in deleting from it -@@ -404,7 +423,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -429,7 +448,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise // Paper start - rewrite chunk system synchronized (this) { final ExceptionCollector exceptionCollector = new ExceptionCollector<>(); @@ -388,7 +397,7 @@ index dad7f94b611cf0fc68b1a3878c458233f6bb6d61..2689ba38ba9d2703078cd4f9f2c6d176 try { regionFile.close(); } catch (final IOException ex) { -@@ -420,7 +439,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -445,7 +464,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise // Paper start - rewrite chunk system synchronized (this) { final ExceptionCollector exceptionCollector = new ExceptionCollector<>(); diff --git a/leaves-server/minecraft-patches/features/0089-No-TNT-place-update.patch b/leaves-server/minecraft-patches/features/0089-No-TNT-place-update.patch deleted file mode 100644 index 0b8e96f7..00000000 --- a/leaves-server/minecraft-patches/features/0089-No-TNT-place-update.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Thu, 18 Jan 2024 12:31:31 +0800 -Subject: [PATCH] No TNT place update - - -diff --git a/net/minecraft/world/level/block/TntBlock.java b/net/minecraft/world/level/block/TntBlock.java -index 9dca05fb66ce3ff9e0c3e31978bf4d5d9e139b8e..bc960220f4d9854a73990ce06c598a86e56fa558 100644 ---- a/net/minecraft/world/level/block/TntBlock.java -+++ b/net/minecraft/world/level/block/TntBlock.java -@@ -45,7 +45,7 @@ public class TntBlock extends Block { - @Override - protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { - if (!oldState.is(state.getBlock())) { -- if (level.hasNeighborSignal(pos) && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent -+ if (!org.leavesmc.leaves.LeavesConfig.modify.noTNTPlaceUpdate & level.hasNeighborSignal(pos) && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent - // Paper start - TNTPrimeEvent - org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos); - if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) { diff --git a/leaves-server/minecraft-patches/features/0090-No-TNT-place-update.patch b/leaves-server/minecraft-patches/features/0090-No-TNT-place-update.patch new file mode 100644 index 00000000..af66fae0 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0090-No-TNT-place-update.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: violetc <58360096+s-yh-china@users.noreply.github.com> +Date: Thu, 18 Jan 2024 12:31:31 +0800 +Subject: [PATCH] No TNT place update + + +diff --git a/net/minecraft/world/level/block/TntBlock.java b/net/minecraft/world/level/block/TntBlock.java +index 93d6e05578622b057d8e973c71f880a17036a6b5..807b2d9bde6d9a365feff13adc4a8b546bec6d0c 100644 +--- a/net/minecraft/world/level/block/TntBlock.java ++++ b/net/minecraft/world/level/block/TntBlock.java +@@ -47,7 +47,7 @@ public class TntBlock extends Block { + @Override + protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { + if (!oldState.is(state.getBlock())) { +- if (level.hasNeighborSignal(pos) && prime(level, pos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null))) { // CraftBukkit - TNTPrimeEvent ++ if (level.hasNeighborSignal(pos) && !org.leavesmc.leaves.LeavesConfig.modify.noTNTPlaceUpdate && prime(level, pos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null))) { // CraftBukkit - TNTPrimeEvent // Leaves - prevent update + level.removeBlock(pos, false); + } + } diff --git a/leaves-server/minecraft-patches/features/0091-Placing-locked-hopper-no-longer-send-NC-updates.patch b/leaves-server/minecraft-patches/features/0091-Placing-locked-hopper-no-longer-send-NC-updates.patch deleted file mode 100644 index 972ca1f2..00000000 --- a/leaves-server/minecraft-patches/features/0091-Placing-locked-hopper-no-longer-send-NC-updates.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Fortern -Date: Sat, 20 Jan 2024 02:50:56 +0800 -Subject: [PATCH] Placing locked hopper no longer send NC updates - - -diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 2d0b54c56f89f05a3babf257ca17e6ca32f54d96..9b5e0c569cc17475f6cb4a5c7bed3e39b9ae5b5e 100644 ---- a/net/minecraft/world/level/Level.java -+++ b/net/minecraft/world/level/Level.java -@@ -1213,7 +1213,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - } - - if ((i & 1) != 0) { -- this.blockUpdated(blockposition, iblockdata1.getBlock()); -+ // Leaves start - Placing locked hopper doesn't send NC updates. -+ if (!(iblockdata.getBlock() instanceof net.minecraft.world.level.block.HopperBlock) || iblockdata.getValue(net.minecraft.world.level.block.HopperBlock.ENABLED)) { -+ this.blockUpdated(blockposition, iblockdata1.getBlock()); -+ } -+ // Leaves end - Placing locked hopper doesn't send NC updates. - if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) { - this.updateNeighbourForOutputSignal(blockposition, newBlock.getBlock()); - } diff --git a/leaves-server/minecraft-patches/features/0090-Servux-Protocol.patch b/leaves-server/minecraft-patches/features/0091-Servux-Protocol.patch similarity index 75% rename from leaves-server/minecraft-patches/features/0090-Servux-Protocol.patch rename to leaves-server/minecraft-patches/features/0091-Servux-Protocol.patch index b418ac7e..dcf7ba15 100644 --- a/leaves-server/minecraft-patches/features/0090-Servux-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0091-Servux-Protocol.patch @@ -5,14 +5,14 @@ Subject: [PATCH] Servux Protocol diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 439bc4a93deb6fe134a9b1de4ca73a8c785d46db..dd7df1616d215020a65ce5d048f1b6f01469c86f 100644 +index 9b1a65036392a965dc0ce93247dfc0cf53630034..c4113e01a8624397e78a18834bdcd857bf953bbe 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -2192,6 +2192,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2207,6 +2207,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } this.lastSpawnChunkRadius = i; + org.leavesmc.leaves.protocol.servux.ServuxHudDataProtocol.refreshSpawnMetadata = true; // Leaves - servux } - public LongSet getForcedChunks() { + public LongSet getForceLoadedChunks() { diff --git a/leaves-server/minecraft-patches/features/0092-Placing-locked-hopper-no-longer-send-NC-updates.patch b/leaves-server/minecraft-patches/features/0092-Placing-locked-hopper-no-longer-send-NC-updates.patch new file mode 100644 index 00000000..45d19e67 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0092-Placing-locked-hopper-no-longer-send-NC-updates.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fortern +Date: Sat, 20 Jan 2024 02:50:56 +0800 +Subject: [PATCH] Placing locked hopper no longer send NC updates + + +diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java +index 7c13e7b7a547150642c4a4bddf5e8dee1d580984..148d92e12c238b81087f68756da7d17da435d3ea 100644 +--- a/net/minecraft/world/level/Level.java ++++ b/net/minecraft/world/level/Level.java +@@ -1200,7 +1200,11 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl + } + + if ((flags & 1) != 0) { +- this.updateNeighborsAt(pos, blockState.getBlock()); ++ // Leaves start - Placing locked hopper doesn't send NC updates. ++ if (!(blockState.getBlock() instanceof net.minecraft.world.level.block.HopperBlock) || blockState.getValue(net.minecraft.world.level.block.HopperBlock.ENABLED)) { ++ this.updateNeighborsAt(pos, blockState.getBlock()); ++ } ++ // Leaves end - Placing locked hopper doesn't send NC updates. + if (!this.isClientSide && state.hasAnalogOutputSignal()) { + this.updateNeighbourForOutputSignal(pos, newState.getBlock()); + } diff --git a/leaves-server/minecraft-patches/features/0092-Renewable-deepslate.patch b/leaves-server/minecraft-patches/features/0093-Renewable-deepslate.patch similarity index 90% rename from leaves-server/minecraft-patches/features/0092-Renewable-deepslate.patch rename to leaves-server/minecraft-patches/features/0093-Renewable-deepslate.patch index ecc4cf38..4e5e29c0 100644 --- a/leaves-server/minecraft-patches/features/0092-Renewable-deepslate.patch +++ b/leaves-server/minecraft-patches/features/0093-Renewable-deepslate.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Renewable deepslate diff --git a/net/minecraft/world/level/block/LiquidBlock.java b/net/minecraft/world/level/block/LiquidBlock.java -index 19d1906e9d4e92ff49a833bca03a7308ee8059e3..928b4196d4fe359dffa11be3b32a52761378a347 100644 +index 7320b416e8d660419018b0699f49ab6f45a3373b..553c6b298ec5929dba6acd859bd38bfbe293838b 100644 --- a/net/minecraft/world/level/block/LiquidBlock.java +++ b/net/minecraft/world/level/block/LiquidBlock.java @@ -190,7 +190,7 @@ public class LiquidBlock extends Block implements BucketPickup { @@ -15,13 +15,13 @@ index 19d1906e9d4e92ff49a833bca03a7308ee8059e3..928b4196d4fe359dffa11be3b32a5276 - Block block = level.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE; + Block block = level.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : (org.leavesmc.leaves.LeavesConfig.modify.renewableDeepslate && level.dimension() == Level.OVERWORLD && pos.getY() < 0 ? Blocks.COBBLED_DEEPSLATE : Blocks.COBBLESTONE); // Leaves - renewable deepslate // CraftBukkit start - if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState())) { + if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState(), 3)) { this.fizz(level, pos); diff --git a/net/minecraft/world/level/material/LavaFluid.java b/net/minecraft/world/level/material/LavaFluid.java -index 6f135caffb7638c6156f00341aeac12b50cea99d..b4116b109e251e878b42e16edbaea07ac8256294 100644 +index 033f252248b671e35135269dd2df6e7ca4585604..5bea04f4d70566e6791bef49e32c775cc5546d6c 100644 --- a/net/minecraft/world/level/material/LavaFluid.java +++ b/net/minecraft/world/level/material/LavaFluid.java -@@ -211,7 +211,7 @@ public abstract class LavaFluid extends FlowingFluid { +@@ -223,7 +223,7 @@ public abstract class LavaFluid extends FlowingFluid { if (this.is(FluidTags.LAVA) && fluidState1.is(FluidTags.WATER)) { if (blockState.getBlock() instanceof LiquidBlock) { // CraftBukkit start diff --git a/leaves-server/minecraft-patches/features/0093-Renewable-sponges.patch b/leaves-server/minecraft-patches/features/0094-Renewable-sponges.patch similarity index 91% rename from leaves-server/minecraft-patches/features/0093-Renewable-sponges.patch rename to leaves-server/minecraft-patches/features/0094-Renewable-sponges.patch index e2f6f9c4..7bec76d3 100644 --- a/leaves-server/minecraft-patches/features/0093-Renewable-sponges.patch +++ b/leaves-server/minecraft-patches/features/0094-Renewable-sponges.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Renewable sponges diff --git a/net/minecraft/world/entity/monster/Guardian.java b/net/minecraft/world/entity/monster/Guardian.java -index c8e249b8f7ee8e9c075169ec988f5a0d459a3767..a4b9511114ff7422691962b7a01d3084dae1ecc1 100644 +index a36f0181e1aa24538d6c868a8675da89427bdeae..b9c08ae9579ab5867adff4e0c5e7824b56203b3c 100644 --- a/net/minecraft/world/entity/monster/Guardian.java +++ b/net/minecraft/world/entity/monster/Guardian.java @@ -452,6 +452,28 @@ public class Guardian extends Monster { @@ -17,7 +17,7 @@ index c8e249b8f7ee8e9c075169ec988f5a0d459a3767..a4b9511114ff7422691962b7a01d3084 + public void thunderHit(net.minecraft.server.level.ServerLevel level, net.minecraft.world.entity.LightningBolt lightning) { + if (org.leavesmc.leaves.LeavesConfig.modify.renewableSponges && !this.isRemoved() && !(this instanceof ElderGuardian)) { + ElderGuardian elderGuardian = new ElderGuardian(EntityType.ELDER_GUARDIAN ,this.level()); -+ elderGuardian.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ elderGuardian.snapTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + elderGuardian.finalizeSpawn(level ,this.level().getCurrentDifficultyAt(elderGuardian.blockPosition()), EntitySpawnReason.CONVERSION, null); + elderGuardian.setNoAi(this.isNoAi()); + diff --git a/leaves-server/minecraft-patches/features/0094-Renewable-coral.patch b/leaves-server/minecraft-patches/features/0095-Renewable-coral.patch similarity index 77% rename from leaves-server/minecraft-patches/features/0094-Renewable-coral.patch rename to leaves-server/minecraft-patches/features/0095-Renewable-coral.patch index fb0b1c8b..7ea5639c 100644 --- a/leaves-server/minecraft-patches/features/0094-Renewable-coral.patch +++ b/leaves-server/minecraft-patches/features/0095-Renewable-coral.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Renewable coral diff --git a/net/minecraft/world/level/block/CoralFanBlock.java b/net/minecraft/world/level/block/CoralFanBlock.java -index 9530fa0793ed0904b17f8972d09f98a97b2cecb0..0bc0c1f7f86f0893b571218c313c49ea90790a34 100644 +index a10af527340d26b9cfd59f73a2518ce31ea5c464..5beaa24e96f3057cfd38df691306c78fcedf669c 100644 --- a/net/minecraft/world/level/block/CoralFanBlock.java +++ b/net/minecraft/world/level/block/CoralFanBlock.java @@ -13,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockBehaviour; @@ -30,7 +30,7 @@ index 9530fa0793ed0904b17f8972d09f98a97b2cecb0..0bc0c1f7f86f0893b571218c313c49ea + // Leaves end - renewable coral } diff --git a/net/minecraft/world/level/block/CoralPlantBlock.java b/net/minecraft/world/level/block/CoralPlantBlock.java -index d1a4dd8ef1ad9d7fb8ae434fc096a9d5b9c5b69d..27df4f7ab514600aaa8dd65a3fee8c280a915a46 100644 +index 20396db7afb93bc8ea5b7ae28a76ca82bd1a4535..9fc66adcb3ffdbfee5ad6b76a01e396634a6f4e5 100644 --- a/net/minecraft/world/level/block/CoralPlantBlock.java +++ b/net/minecraft/world/level/block/CoralPlantBlock.java @@ -16,7 +16,7 @@ import net.minecraft.world.level.material.Fluids; @@ -42,7 +42,7 @@ index d1a4dd8ef1ad9d7fb8ae434fc096a9d5b9c5b69d..27df4f7ab514600aaa8dd65a3fee8c28 public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter(coralPlantBlock -> coralPlantBlock.deadBlock), propertiesCodec()) .apply(instance, CoralPlantBlock::new) -@@ -79,4 +79,12 @@ public class CoralPlantBlock extends BaseCoralPlantTypeBlock { +@@ -78,4 +78,12 @@ public class CoralPlantBlock extends BaseCoralPlantTypeBlock { protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { return SHAPE; } @@ -53,6 +53,31 @@ index d1a4dd8ef1ad9d7fb8ae434fc096a9d5b9c5b69d..27df4f7ab514600aaa8dd65a3fee8c28 + return org.leavesmc.leaves.LeavesConfig.modify.renewableCoral == org.leavesmc.leaves.LeavesConfig.ModifyConfig.RenewableCoralType.EXPANDED + || org.leavesmc.leaves.LeavesConfig.modify.renewableCoral == org.leavesmc.leaves.LeavesConfig.ModifyConfig.RenewableCoralType.TRUE; + } ++ // Leaves end - renewable coral + } +diff --git a/net/minecraft/world/level/block/CoralWallFanBlock.java b/net/minecraft/world/level/block/CoralWallFanBlock.java +index af0cc07404032032211ca4e377e8af681af2d7ab..7a0033ebce5f5058f331b32bb57e5f586a3d9d21 100644 +--- a/net/minecraft/world/level/block/CoralWallFanBlock.java ++++ b/net/minecraft/world/level/block/CoralWallFanBlock.java +@@ -13,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.Fluids; + +-public class CoralWallFanBlock extends BaseCoralWallFanBlock { ++public class CoralWallFanBlock extends BaseCoralWallFanBlock implements org.leavesmc.leaves.util.FertilizableCoral { // Leaves - renewable coral + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( + instance -> instance.group(CoralBlock.DEAD_CORAL_FIELD.forGetter(coralWallFanBlock -> coralWallFanBlock.deadBlock), propertiesCodec()) + .apply(instance, CoralWallFanBlock::new) +@@ -69,4 +69,11 @@ public class CoralWallFanBlock extends BaseCoralWallFanBlock { + return super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random); + } + } ++ ++ // Leaves start - renewable coral ++ @Override ++ public boolean isEnabled() { ++ return org.leavesmc.leaves.LeavesConfig.modify.renewableCoral == org.leavesmc.leaves.LeavesConfig.ModifyConfig.RenewableCoralType.EXPANDED; ++ } + // Leaves end - renewable coral } diff --git a/net/minecraft/world/level/levelgen/feature/CoralClawFeature.java b/net/minecraft/world/level/levelgen/feature/CoralClawFeature.java @@ -69,7 +94,7 @@ index abb8519ede1c2271c98497a8e3336f0ad89c340d..f5009d112b32ce91296ed84310bb9bf4 return false; } else { diff --git a/net/minecraft/world/level/levelgen/feature/CoralFeature.java b/net/minecraft/world/level/levelgen/feature/CoralFeature.java -index d62e64a7663141a5e7223fb6c1358f3799ec1c3e..f0a9a461bfa9b128cc71537e58e0f1ade02a6698 100644 +index 2569754d96694edbc1fe64e6048d6ec26cbe243e..88d38433ffb78fbdd04d9adf53d584c492dc8ec7 100644 --- a/net/minecraft/world/level/levelgen/feature/CoralFeature.java +++ b/net/minecraft/world/level/levelgen/feature/CoralFeature.java @@ -31,7 +31,7 @@ public abstract class CoralFeature extends Feature { diff --git a/leaves-server/minecraft-patches/features/0095-Fast-resume.patch b/leaves-server/minecraft-patches/features/0096-Fast-resume.patch similarity index 74% rename from leaves-server/minecraft-patches/features/0095-Fast-resume.patch rename to leaves-server/minecraft-patches/features/0096-Fast-resume.patch index fa2b30a9..5ffc5340 100644 --- a/leaves-server/minecraft-patches/features/0095-Fast-resume.patch +++ b/leaves-server/minecraft-patches/features/0096-Fast-resume.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Fast resume diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -index b5817aa8f537593f6d9fc6b612c82ccccb250ac7..920d925159ad8088de3e751591d464d22ffd2c06 100644 +index f473999938840562b1007a789600342e5796a123..7e20b6469ef06c0338b5298d36b3a1ba1c52e897 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -@@ -603,6 +603,49 @@ public final class ChunkHolderManager { +@@ -656,6 +656,49 @@ public final class ChunkHolderManager { } } + // Leaves start - add custom ticket -+ public void addTicketAtLevelCustom(final Ticket ticket, final long chunk, final boolean lock) { ++ public void addTicketAtLevelCustom(final Ticket ticket, final long chunk, final boolean lock) { + final long removeDelay = ticket.moonrise$getRemoveDelay(); + + final int chunkX = CoordinateUtils.getChunkX(chunk); @@ -21,14 +21,14 @@ index b5817aa8f537593f6d9fc6b612c82ccccb250ac7..920d925159ad8088de3e751591d464d2 + + final ReentrantAreaLock.Node ticketLock = lock ? this.ticketLockArea.lock(chunkX, chunkZ) : null; + try { -+ final SortedArraySet> ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (final long keyInMap) -> SortedArraySet.create(4)); ++ final SortedArraySet ticketsAtChunk = this.tickets.computeIfAbsent(chunk, (final long keyInMap) -> SortedArraySet.create(4)); + + final int levelBefore = getTicketLevelAt(ticketsAtChunk); -+ final Ticket current = (Ticket)((ChunkSystemSortedArraySet>)ticketsAtChunk).moonrise$replace(ticket); ++ final Ticket current = ((ChunkSystemSortedArraySet)ticketsAtChunk).moonrise$replace(ticket); + final int levelAfter = getTicketLevelAt(ticketsAtChunk); + + if (current != ticket) { -+ final long oldRemoveDelay = ((ChunkSystemTicket) current).moonrise$getRemoveDelay(); ++ final long oldRemoveDelay = ((ChunkSystemTicket) current).moonrise$getRemoveDelay(); + if (removeDelay != oldRemoveDelay) { + if (oldRemoveDelay != NO_TIMEOUT_MARKER && removeDelay == NO_TIMEOUT_MARKER) { + this.removeExpireCount(chunkX, chunkZ); @@ -55,14 +55,14 @@ index b5817aa8f537593f6d9fc6b612c82ccccb250ac7..920d925159ad8088de3e751591d464d2 + } + // Leaves end - add custom ticket + - public boolean removeTicketAtLevel(final TicketType type, final ChunkPos chunkPos, final int level, final T identifier) { - return this.removeTicketAtLevel(type, CoordinateUtils.getChunkKey(chunkPos), level, identifier); - } + private void removeTicketCounter(final TicketType type, final long pos) { + final long[] counterTypes = ((ChunkSystemTicketType)(Object)type).moonrise$getCounterTypes(); + if (counterTypes.length == 0) { diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 164b8dc3f247aedd37bce24a7acb6ab1858e7d20..26e6fc29125fb129cbeb4c736dff222d4fe648b9 100644 +index f1681577f27a618338cae1634094e728c98fc3ff..6bc08a61a51b19e8f5670b0c54a3faeeab16bbc4 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -744,6 +744,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Mon, 29 Jul 2024 08:20:31 +0800 -Subject: [PATCH] Fix fortress mob spawn - - -diff --git a/net/minecraft/world/level/biome/MobSpawnSettings.java b/net/minecraft/world/level/biome/MobSpawnSettings.java -index 2d256b201df3afa1cf5879fdc931a1aa684110e4..6b8903bc4ec86302d6b5444742db22518fe91a8e 100644 ---- a/net/minecraft/world/level/biome/MobSpawnSettings.java -+++ b/net/minecraft/world/level/biome/MobSpawnSettings.java -@@ -175,6 +175,14 @@ public class MobSpawnSettings { - this.maxCount = maxCount; - } - -+ // Leaves start - fix fortress mob spawn -+ @Override -+ public boolean equals(Object obj) { -+ if(!org.leavesmc.leaves.LeavesConfig.modify.oldMC.fixFortressMobSpawn || !(obj instanceof SpawnerData other)) return super.equals(obj); -+ return this.type == other.type && this.minCount == other.minCount && this.maxCount == other.maxCount; -+ } -+ // Leaves end - fix fortress mob spawn -+ - @Override - public String toString() { - return EntityType.getKey(this.type) + "*(" + this.minCount + "-" + this.maxCount + "):" + this.getWeight(); diff --git a/leaves-server/minecraft-patches/features/0106-Fix-FallingBlockEntity-Duplicate.patch b/leaves-server/minecraft-patches/features/0106-Fix-FallingBlockEntity-Duplicate.patch index 302be77b..b30eac46 100644 --- a/leaves-server/minecraft-patches/features/0106-Fix-FallingBlockEntity-Duplicate.patch +++ b/leaves-server/minecraft-patches/features/0106-Fix-FallingBlockEntity-Duplicate.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix FallingBlockEntity Duplicate diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java -index 5746587666c7cb788764aab2f6ccf0f3ac5c282f..35d5dd7ca192ae384ecfd858e7c898c9f4b841b4 100644 +index 31edd0d45ac6c38887e4cebffe5a7cf377b47466..b6e188cf9f224a9c4b75339acd0306758bf0cb71 100644 --- a/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -401,7 +401,7 @@ public class FallingBlockEntity extends Entity { +@@ -382,7 +382,7 @@ public class FallingBlockEntity extends Entity { ResourceKey resourceKey1 = this.level().dimension(); boolean flag = (resourceKey1 == Level.END || resourceKey == Level.END) && resourceKey1 != resourceKey; Entity entity = super.teleport(teleportTransition); diff --git a/leaves-server/minecraft-patches/features/0107-Old-Block-remove-behaviour.patch b/leaves-server/minecraft-patches/features/0107-Old-Block-remove-behaviour.patch new file mode 100644 index 00000000..f8562b25 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0107-Old-Block-remove-behaviour.patch @@ -0,0 +1,804 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: violetc <58360096+s-yh-china@users.noreply.github.com> +Date: Wed, 14 Aug 2024 01:48:14 +0800 +Subject: [PATCH] Old Block remove behaviour + + +diff --git a/net/minecraft/world/Containers.java b/net/minecraft/world/Containers.java +index da10ca5ef12be1a834adda9243c082dadde24ec0..f682930f765d04f0a278b0648c2773ab5d4d740e 100644 +--- a/net/minecraft/world/Containers.java ++++ b/net/minecraft/world/Containers.java +@@ -51,4 +51,15 @@ public class Containers { + public static void updateNeighboursAfterDestroy(BlockState state, Level level, BlockPos pos) { + level.updateNeighbourForOutputSignal(pos, state.getBlock()); + } ++ ++ // Leaves start - behaviour 1.21.1- ++ public static void dropContentsOnDestroy(BlockState state, BlockState newState, Level level, BlockPos pos) { ++ if (!state.is(newState.getBlock())) { ++ if (level.getBlockEntity(pos) instanceof Container container) { ++ dropContents(level, pos, container); ++ level.updateNeighbourForOutputSignal(pos, state.getBlock()); ++ } ++ } ++ } ++ // Leaves end - behaviour 1.21.1- + } +diff --git a/net/minecraft/world/level/block/AbstractFurnaceBlock.java b/net/minecraft/world/level/block/AbstractFurnaceBlock.java +index d52eeff0d564a24bddb873750c81e3fe999f16f0..aa2597d825f93b0b0623ab7fae29e45de3f3ebcc 100644 +--- a/net/minecraft/world/level/block/AbstractFurnaceBlock.java ++++ b/net/minecraft/world/level/block/AbstractFurnaceBlock.java +@@ -51,6 +51,26 @@ public abstract class AbstractFurnaceBlock extends BaseEntityBlock { + return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ BlockEntity blockEntity = level.getBlockEntity(pos); ++ if (blockEntity instanceof AbstractFurnaceBlockEntity) { ++ if (level instanceof ServerLevel) { ++ Containers.dropContents(level, pos, (AbstractFurnaceBlockEntity)blockEntity); ++ ((AbstractFurnaceBlockEntity)blockEntity).getRecipesToAwardAndPopExperience((ServerLevel)level, net.minecraft.world.phys.Vec3.atCenterOf(pos)); ++ } ++ ++ super.onRemove(state, level, pos, newState, isMoving); ++ level.updateNeighbourForOutputSignal(pos, this); ++ } else { ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/BarrelBlock.java b/net/minecraft/world/level/block/BarrelBlock.java +index f7820265f10b78674acd13e6204b9212fd27b038..700bd0f6a4f4fd6cd85b3e666fff1b3fd0a96b8e 100644 +--- a/net/minecraft/world/level/block/BarrelBlock.java ++++ b/net/minecraft/world/level/block/BarrelBlock.java +@@ -49,6 +49,14 @@ public class BarrelBlock extends BaseEntityBlock { + return InteractionResult.SUCCESS; + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ Containers.dropContentsOnDestroy(state, newState, level, pos); ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/BasePressurePlateBlock.java b/net/minecraft/world/level/block/BasePressurePlateBlock.java +index 42ee3f32fe44c1f0680c994a69201f7bd7792673..19214c236bca4e454e3bbe7dc50e00b66398c119 100644 +--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java ++++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java +@@ -125,6 +125,19 @@ public abstract class BasePressurePlateBlock extends Block { + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ if (this.getSignalForState(state) > 0) { ++ this.updateNeighbours(level, pos); ++ } ++ ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (!movedByPiston && this.getSignalForState(state) > 0) { +diff --git a/net/minecraft/world/level/block/BaseRailBlock.java b/net/minecraft/world/level/block/BaseRailBlock.java +index 4e13f5b233018d648f8ff83447624353fd62683b..8ecc438a518703aedd5aeed00727023ff26555c5 100644 +--- a/net/minecraft/world/level/block/BaseRailBlock.java ++++ b/net/minecraft/world/level/block/BaseRailBlock.java +@@ -121,6 +121,23 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!isMoving) { ++ super.onRemove(state, level, pos, newState, isMoving); ++ if (state.getValue(this.getShapeProperty()).isSlope()) { ++ level.updateNeighborsAt(pos.above(), this); ++ } ++ ++ if (this.isStraight) { ++ level.updateNeighborsAt(pos, this); ++ level.updateNeighborsAt(pos.below(), this); ++ } ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (!movedByPiston) { +diff --git a/net/minecraft/world/level/block/BrewingStandBlock.java b/net/minecraft/world/level/block/BrewingStandBlock.java +index f563f8ea63e67f808802baa4c6a700e803c045a0..0cc4479d9d3f6aea280c9f88997d141dc24917a9 100644 +--- a/net/minecraft/world/level/block/BrewingStandBlock.java ++++ b/net/minecraft/world/level/block/BrewingStandBlock.java +@@ -78,6 +78,14 @@ public class BrewingStandBlock extends BaseEntityBlock { + level.addParticle(ParticleTypes.SMOKE, d, d1, d2, 0.0, 0.0, 0.0); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ Containers.dropContentsOnDestroy(state, newState, level, pos); ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/ButtonBlock.java b/net/minecraft/world/level/block/ButtonBlock.java +index 66c589bc633d32ebf36b1ab55ba6250ca2ddd6f6..f96d3c7b7ec15973aca3aabe056608fd5efb856b 100644 +--- a/net/minecraft/world/level/block/ButtonBlock.java ++++ b/net/minecraft/world/level/block/ButtonBlock.java +@@ -132,6 +132,19 @@ public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock { + return isOn ? this.type.buttonClickOn() : this.type.buttonClickOff(); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ if (state.getValue(POWERED)) { ++ this.updateNeighbours(state, level, pos); ++ } ++ ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (!movedByPiston && state.getValue(POWERED)) { +diff --git a/net/minecraft/world/level/block/CampfireBlock.java b/net/minecraft/world/level/block/CampfireBlock.java +index 028e2ad8bcb23b3f9f80a5ec551204bb2d7db1ae..c9e2becc0644de707e0bd251318813c50fc82be2 100644 +--- a/net/minecraft/world/level/block/CampfireBlock.java ++++ b/net/minecraft/world/level/block/CampfireBlock.java +@@ -105,6 +105,20 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB + return InteractionResult.TRY_WITH_EMPTY_HAND; + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ BlockEntity blockEntity = level.getBlockEntity(pos); ++ if (blockEntity instanceof CampfireBlockEntity) { ++ net.minecraft.world.Containers.dropContents(level, pos, ((CampfireBlockEntity)blockEntity).getItems()); ++ } ++ ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) { + if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent +diff --git a/net/minecraft/world/level/block/ChestBlock.java b/net/minecraft/world/level/block/ChestBlock.java +index c4937d1b482e2ec60961bda62ad6cc155f0ce8f7..818b1a5df0e9a0566210e4b3512ad856515e385f 100644 +--- a/net/minecraft/world/level/block/ChestBlock.java ++++ b/net/minecraft/world/level/block/ChestBlock.java +@@ -244,6 +244,14 @@ public class ChestBlock extends AbstractChestBlock implements + return blockState.is(this) && blockState.getValue(TYPE) == ChestType.SINGLE ? blockState.getValue(FACING) : null; + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ Containers.dropContentsOnDestroy(state, newState, level, pos); ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java +index eb315a50a83dc7230d7ad66f4daeb0d632679941..7bccf15310f6851875bfd77d4c66f4ce863b65e1 100644 +--- a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java ++++ b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java +@@ -180,6 +180,27 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock { + SLOT_OCCUPIED_PROPERTIES.forEach(property -> builder.add(property)); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ if (!state.is(newState.getBlock())) { ++ if (level.getBlockEntity(pos) instanceof ChiseledBookShelfBlockEntity chiseledBookShelfBlockEntity && !chiseledBookShelfBlockEntity.isEmpty()) { ++ for (int i = 0; i < 6; i++) { ++ ItemStack item = chiseledBookShelfBlockEntity.getItem(i); ++ if (!item.isEmpty()) { ++ Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), item); ++ } ++ } ++ ++ chiseledBookShelfBlockEntity.clearContent(); ++ level.updateNeighbourForOutputSignal(pos, this); ++ } ++ ++ super.onRemove(state, level, pos, newState, movedByPiston); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java +index 3ce56a24e131c3ea4c6d568e3f7bd2de8076ac60..d9688878de652cd47f5ffa427fad13615683648e 100644 +--- a/net/minecraft/world/level/block/CrafterBlock.java ++++ b/net/minecraft/world/level/block/CrafterBlock.java +@@ -129,6 +129,14 @@ public class CrafterBlock extends BaseEntityBlock { + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ Containers.dropContentsOnDestroy(state, newState, level, pos); ++ super.onRemove(state, level, pos, newState, movedByPiston); ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/CreakingHeartBlock.java b/net/minecraft/world/level/block/CreakingHeartBlock.java +index 73885449a3316face50292756de2a3f298d3d111..333e18e4ead0bb6ef9681ce27ec156f79821af7c 100644 +--- a/net/minecraft/world/level/block/CreakingHeartBlock.java ++++ b/net/minecraft/world/level/block/CreakingHeartBlock.java +@@ -152,6 +152,16 @@ public class CreakingHeartBlock extends BaseEntityBlock { + builder.add(AXIS, STATE, NATURAL); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ if (level.getBlockEntity(pos) instanceof CreakingHeartBlockEntity creakingHeartBlockEntity) { ++ creakingHeartBlockEntity.removeProtector(null); ++ } ++ super.onRemove(state, level, pos, newState, movedByPiston); ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/DecoratedPotBlock.java b/net/minecraft/world/level/block/DecoratedPotBlock.java +index f1570f1f4f7e43aacbcffef8bcf8ef27d46899da..6afd1c618112234ce4940105582a4399e20ab34c 100644 +--- a/net/minecraft/world/level/block/DecoratedPotBlock.java ++++ b/net/minecraft/world/level/block/DecoratedPotBlock.java +@@ -165,6 +165,14 @@ public class DecoratedPotBlock extends BaseEntityBlock implements SimpleWaterlog + return new DecoratedPotBlockEntity(pos, state); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ Containers.dropContentsOnDestroy(state, newState, level, pos); ++ super.onRemove(state, level, pos, newState, movedByPiston); ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java +index 558751ade918a92a1173096ccfeacf238f4260d0..94d35e4812705771756a0ee1a9b0255be75e3770 100644 +--- a/net/minecraft/world/level/block/DiodeBlock.java ++++ b/net/minecraft/world/level/block/DiodeBlock.java +@@ -175,6 +175,16 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock { + this.updateNeighborsInFront(level, pos, state); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ super.onRemove(state, level, pos, newState, isMoving); ++ this.updateNeighborsInFront(level, pos, state); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (!movedByPiston) { +diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java +index 7ff6255fcd50344cd6ac7f8a67d61fd59c85e413..7a23d27ce76ae6b90d01c4dc7af416bb6b6516ea 100644 +--- a/net/minecraft/world/level/block/DispenserBlock.java ++++ b/net/minecraft/world/level/block/DispenserBlock.java +@@ -147,6 +147,14 @@ public class DispenserBlock extends BaseEntityBlock { + return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite()); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ Containers.dropContentsOnDestroy(state, newState, level, pos); ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/HopperBlock.java b/net/minecraft/world/level/block/HopperBlock.java +index 46a27f60ba407dacdac190b5e292ab3f1db5a078..d3535a9dc462d92a306aea981d7799d8d975f59d 100644 +--- a/net/minecraft/world/level/block/HopperBlock.java ++++ b/net/minecraft/world/level/block/HopperBlock.java +@@ -125,6 +125,14 @@ public class HopperBlock extends BaseEntityBlock { + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ Containers.dropContentsOnDestroy(state, newState, level, pos); ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/JukeboxBlock.java b/net/minecraft/world/level/block/JukeboxBlock.java +index 56cf6528f0cd9b8528490d7cee9a1f0e54108ef9..955854e5b3a18b8f1441145554a97c5454a65d12 100644 +--- a/net/minecraft/world/level/block/JukeboxBlock.java ++++ b/net/minecraft/world/level/block/JukeboxBlock.java +@@ -73,6 +73,19 @@ public class JukeboxBlock extends BaseEntityBlock { + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ if (level.getBlockEntity(pos) instanceof JukeboxBlockEntity jukeboxBlockEntity) { ++ jukeboxBlockEntity.popOutTheItem(); ++ } ++ ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/LecternBlock.java b/net/minecraft/world/level/block/LecternBlock.java +index 5a9b601b7bf7e80b04ebd8f5c8b7d121031132c7..ee666995db38374193414d24fa38260c855be622 100644 +--- a/net/minecraft/world/level/block/LecternBlock.java ++++ b/net/minecraft/world/level/block/LecternBlock.java +@@ -197,6 +197,36 @@ public class LecternBlock extends BaseEntityBlock { + changePowered(level, pos, state, false); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ if (state.getValue(HAS_BOOK)) { ++ this.popBook(state, level, pos); ++ } ++ ++ if (state.getValue(POWERED)) { ++ updateBelow(level, pos, state); ++ } ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ } ++ ++ private void popBook(BlockState state, Level level, BlockPos pos) { ++ if (level.getBlockEntity(pos, false) instanceof LecternBlockEntity lecternBlockEntity) { // CraftBukkit - don't validate, type may be changed already ++ Direction direction = state.getValue(FACING); ++ ItemStack itemStack = lecternBlockEntity.getBook().copy(); ++ if (itemStack.isEmpty()) return; // CraftBukkit - SPIGOT-5500 ++ float f = 0.25F * direction.getStepX(); ++ float f1 = 0.25F * direction.getStepZ(); ++ net.minecraft.world.entity.item.ItemEntity itemEntity = new net.minecraft.world.entity.item.ItemEntity(level, pos.getX() + 0.5 + f, pos.getY() + 1, pos.getZ() + 0.5 + f1, itemStack); ++ itemEntity.setDefaultPickUpDelay(); ++ level.addFreshEntity(itemEntity); ++ lecternBlockEntity.clearContent(); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (state.getValue(POWERED)) { +diff --git a/net/minecraft/world/level/block/LeverBlock.java b/net/minecraft/world/level/block/LeverBlock.java +index 76f2a29f37187344324d68941307d58e6343b6ae..3645ca9589aa1a74134180c9918a6f67bc64ce7a 100644 +--- a/net/minecraft/world/level/block/LeverBlock.java ++++ b/net/minecraft/world/level/block/LeverBlock.java +@@ -125,6 +125,19 @@ public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock { + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ if (state.getValue(POWERED)) { ++ this.updateNeighbours(state, level, pos); ++ } ++ ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (!movedByPiston && state.getValue(POWERED)) { +diff --git a/net/minecraft/world/level/block/LightningRodBlock.java b/net/minecraft/world/level/block/LightningRodBlock.java +index 13b92472d50a41446b86c62ec31919fe0a953374..d567a7c303bf1baa92fc24ff47870d56c70907af 100644 +--- a/net/minecraft/world/level/block/LightningRodBlock.java ++++ b/net/minecraft/world/level/block/LightningRodBlock.java +@@ -120,6 +120,18 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ if (!state.is(newState.getBlock())) { ++ if (state.getValue(POWERED)) { ++ this.updateNeighbours(state, level, pos); ++ } ++ super.onRemove(state, level, pos, newState, movedByPiston); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (state.getValue(POWERED)) { +diff --git a/net/minecraft/world/level/block/ObserverBlock.java b/net/minecraft/world/level/block/ObserverBlock.java +index bd2aa00ce8b78c16f6107064dd00bfbb072df0df..6db3a21bcc37ae79f82b19ee0a851f539d4a654d 100644 +--- a/net/minecraft/world/level/block/ObserverBlock.java ++++ b/net/minecraft/world/level/block/ObserverBlock.java +@@ -127,6 +127,17 @@ public class ObserverBlock extends DirectionalBlock { + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) { ++ this.updateNeighborsInFront(level, pos, state.setValue(POWERED, Boolean.FALSE)); ++ } ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) { +diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java +index 35dc47d5ba1a2659304ccc08010611438ccf04d8..04cc3c5a6ae0bea5f3a47ff7f9a7fe1f486294eb 100644 +--- a/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/net/minecraft/world/level/block/RedStoneWireBlock.java +@@ -363,6 +363,27 @@ public class RedStoneWireBlock extends Block { + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ super.onRemove(state, level, pos, newState, isMoving); ++ for (Direction direction : Direction.values()) { ++ level.updateNeighborsAt(pos.relative(direction), this); ++ } ++ ++ // Paper start - optimize redstone - replace call to updatePowerStrength ++ if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) { ++ level.getWireHandler().onWireRemoved(pos, state); // Alternate Current ++ } else { ++ this.updateSurroundingRedstone(level, pos, state, null, false); // Vanilla/Eigencraft ++ } ++ // Paper end - optimize redstone ++ this.updateNeighborsOfNeighboringWires(level, pos); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (!movedByPiston) { +diff --git a/net/minecraft/world/level/block/RedstoneTorchBlock.java b/net/minecraft/world/level/block/RedstoneTorchBlock.java +index 33e2f2de19208b7af6551132887e310744b4b702..d36c3bdb59bf9b9467d1a9807ab789b4c180010d 100644 +--- a/net/minecraft/world/level/block/RedstoneTorchBlock.java ++++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java +@@ -53,6 +53,15 @@ public class RedstoneTorchBlock extends BaseTorchBlock { + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!isMoving) { ++ this.notifyNeighbors(level, pos, state); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (!movedByPiston) { +diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java +index f0101e88140f480c1a94f899744991f78c9e3756..fa9cb4c40a41eea7fd63a4513d0b0f39067de9ba 100644 +--- a/net/minecraft/world/level/block/SculkSensorBlock.java ++++ b/net/minecraft/world/level/block/SculkSensorBlock.java +@@ -129,6 +129,18 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ if (!state.is(newState.getBlock())) { ++ if (getPhase(state) == SculkSensorPhase.ACTIVE) { ++ updateNeighbours(level, pos, state); ++ } ++ super.onRemove(state, level, pos, newState, movedByPiston); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (getPhase(state) == SculkSensorPhase.ACTIVE) { +diff --git a/net/minecraft/world/level/block/SculkShriekerBlock.java b/net/minecraft/world/level/block/SculkShriekerBlock.java +index 757f8453e147875ab9f14d9726bb734ef27447c9..d0558d0e33f3d6e25af2dd71650d723e8997dae6 100644 +--- a/net/minecraft/world/level/block/SculkShriekerBlock.java ++++ b/net/minecraft/world/level/block/SculkShriekerBlock.java +@@ -68,6 +68,16 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo + super.stepOn(level, pos, state, entity); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ if (level instanceof ServerLevel serverLevel && state.getValue(SHRIEKING) && !state.is(newState.getBlock())) { ++ serverLevel.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryRespond(serverLevel)); ++ } ++ super.onRemove(state, level, pos, newState, movedByPiston); ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { + if (state.getValue(SHRIEKING)) { +diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java +index c34318fdc454ea31655c3c3aa5dbedd3d922ee24..8a5f70778b550cd470b7225e74c6c87a6ec6e7e5 100644 +--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java ++++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java +@@ -152,6 +152,19 @@ public class ShulkerBoxBlock extends BaseEntityBlock { + // Paper end - re-set loot table if it was cleared + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ BlockEntity blockEntity = level.getBlockEntity(pos); ++ if (blockEntity instanceof ShulkerBoxBlockEntity) { ++ level.updateNeighbourForOutputSignal(pos, state.getBlock()); ++ } ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + Containers.updateNeighboursAfterDestroy(state, level, pos); +diff --git a/net/minecraft/world/level/block/TripWireBlock.java b/net/minecraft/world/level/block/TripWireBlock.java +index c8f793d1cdeef7e3e0d5fceb45a4507d542e4b33..27f382f6c663b2954a6fb966ece05ba021fcd6b1 100644 +--- a/net/minecraft/world/level/block/TripWireBlock.java ++++ b/net/minecraft/world/level/block/TripWireBlock.java +@@ -108,6 +108,16 @@ public class TripWireBlock extends Block { + } + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating ++ if (!isMoving && !state.is(newState.getBlock())) { ++ this.updateSource(level, pos, state.setValue(POWERED, Boolean.TRUE)); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating +diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java +index a92462c76a648e6c175b8c2ef3e925aba81ba774..b32760f1096581059418f479b060019f7dccbd67 100644 +--- a/net/minecraft/world/level/block/TripWireHookBlock.java ++++ b/net/minecraft/world/level/block/TripWireHookBlock.java +@@ -245,6 +245,25 @@ public class TripWireHookBlock extends Block { + level.updateNeighborsAt(pos.relative(opposite), block, orientation); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!isMoving && !state.is(newState.getBlock())) { ++ boolean attachedValue = state.getValue(ATTACHED); ++ boolean poweredValue = state.getValue(POWERED); ++ if (attachedValue || poweredValue) { ++ calculateState(level, pos, state, true, false, -1, null); ++ } ++ ++ if (poweredValue) { ++ notifyNeighbors(this, level, pos, state.getValue(FACING)); ++ } ++ ++ super.onRemove(state, level, pos, newState, isMoving); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + if (!movedByPiston) { +diff --git a/net/minecraft/world/level/block/entity/BlockEntityType.java b/net/minecraft/world/level/block/entity/BlockEntityType.java +index 386e6a48701b4c9256e33174123381a93d61e292..abade114c5b5051ce96b6489f08feb7e1cc774ee 100644 +--- a/net/minecraft/world/level/block/entity/BlockEntityType.java ++++ b/net/minecraft/world/level/block/entity/BlockEntityType.java +@@ -263,7 +263,7 @@ public class BlockEntityType { + } + + public boolean isValid(BlockState state) { +- return this.validBlocks.contains(state.getBlock()); ++ return org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockRemoveBehaviour || this.validBlocks.contains(state.getBlock()); // Leaves - behaviour 1.21.1- + } + + @Deprecated +diff --git a/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/net/minecraft/world/level/block/piston/MovingPistonBlock.java +index 05bbc2e59384702439548a988e128a85f1adbe82..af516d5b6bd31de2c6a388ec8001126e2a351cf3 100644 +--- a/net/minecraft/world/level/block/piston/MovingPistonBlock.java ++++ b/net/minecraft/world/level/block/piston/MovingPistonBlock.java +@@ -67,6 +67,18 @@ public class MovingPistonBlock extends BaseEntityBlock { + return createTickerHelper(blockEntityType, BlockEntityType.PISTON, PistonMovingBlockEntity::tick); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ BlockEntity blockEntity = level.getBlockEntity(pos); ++ if (blockEntity instanceof PistonMovingBlockEntity) { ++ ((PistonMovingBlockEntity)blockEntity).finalTick(); ++ } ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + public void destroy(LevelAccessor level, BlockPos pos, BlockState state) { + BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite()); +diff --git a/net/minecraft/world/level/block/piston/PistonHeadBlock.java b/net/minecraft/world/level/block/piston/PistonHeadBlock.java +index 6c789e56f21f01252c21786cfeb48d88485b5636..e24a61a4e2dac0159d52f07c93ddf860f4bfb8f7 100644 +--- a/net/minecraft/world/level/block/piston/PistonHeadBlock.java ++++ b/net/minecraft/world/level/block/piston/PistonHeadBlock.java +@@ -78,6 +78,19 @@ public class PistonHeadBlock extends DirectionalBlock { + return super.playerWillDestroy(level, pos, state, player); + } + ++ // Leaves start - behaviour 1.21.1- ++ @Override ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { ++ if (!state.is(newState.getBlock())) { ++ super.onRemove(state, level, pos, newState, isMoving); ++ BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite()); ++ if (this.isFittingBase(state, level.getBlockState(blockPos))) { ++ level.destroyBlock(blockPos, true); ++ } ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + @Override + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite()); +diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java +index bbb1abfbfe7afd7b631cf269c1e338697cd016d2..768e5c6f1c0ce7d4bec41c37668249e708ebb4bc 100644 +--- a/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -171,6 +171,15 @@ public abstract class BlockBehaviour implements FeatureElement { + org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot + } + ++ // Leaves start - behaviour 1.21.1- ++ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ org.spigotmc.AsyncCatcher.catchOp("block remove"); // Spigot ++ if (state.hasBlockEntity() && !state.is(newState.getBlock())) { ++ level.removeBlockEntity(pos); ++ } ++ } ++ // Leaves end - behaviour 1.21.1- ++ + protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { + } + +@@ -867,6 +876,12 @@ public abstract class BlockBehaviour implements FeatureElement { + // CraftBukkit end + } + ++ // Leaves start - behaviour 1.21.1- ++ public void onRemove(Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { ++ this.getBlock().onRemove(this.asState(), level, pos, newState, movedByPiston); ++ } ++ // Leaves end - behaviour 1.21.1- ++ + public void affectNeighborsAfterRemoval(ServerLevel level, BlockPos pos, boolean movedByPiston) { + this.getBlock().affectNeighborsAfterRemoval(this.asState(), level, pos, movedByPiston); + } +diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java +index 7fca1659bd85b1a737355fb9a8377dff64a7fe17..d1b25a1e698253e1dfaf203536e4f10d8705be0f 100644 +--- a/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/net/minecraft/world/level/chunk/LevelChunk.java +@@ -394,20 +394,26 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p + boolean flag = !blockState.is(block); + boolean flag1 = (flags & 64) != 0; + boolean flag2 = (flags & 256) == 0; +- if (flag && blockState.hasBlockEntity()) { +- if (!this.level.isClientSide && flag2) { +- BlockEntity blockEntity = this.level.getBlockEntity(pos); +- if (blockEntity != null) { +- blockEntity.preRemoveSideEffects(pos, blockState); ++ // Leaves start - behaviour 1.21.1- ++ if (!org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockRemoveBehaviour) { ++ if (flag && blockState.hasBlockEntity()) { ++ if (!this.level.isClientSide && flag2) { ++ BlockEntity blockEntity = this.level.getBlockEntity(pos); ++ if (blockEntity != null) { ++ blockEntity.preRemoveSideEffects(pos, blockState); ++ } + } +- } + +- this.removeBlockEntity(pos); +- } ++ this.removeBlockEntity(pos); ++ } + +- if ((flag || block instanceof BaseRailBlock) && this.level instanceof ServerLevel serverLevel && ((flags & 1) != 0 || flag1)) { +- blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1); ++ if ((flag || block instanceof BaseRailBlock) && this.level instanceof ServerLevel serverLevel && ((flags & 1) != 0 || flag1)) { ++ blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1); ++ } ++ } else { ++ blockState.onRemove(this.level, pos, state, flag1); + } ++ // Leaves end - behaviour 1.21.1- + + if (!section.getBlockState(i, i1, i2).is(block)) { + return null; diff --git a/leaves-server/minecraft-patches/features/0107-Old-BlockEntity-behaviour.patch b/leaves-server/minecraft-patches/features/0107-Old-BlockEntity-behaviour.patch deleted file mode 100644 index cc93e8e8..00000000 --- a/leaves-server/minecraft-patches/features/0107-Old-BlockEntity-behaviour.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Wed, 14 Aug 2024 01:48:14 +0800 -Subject: [PATCH] Old BlockEntity behaviour - - -diff --git a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java -index 1411c6b0471281827b9d21958c0c7d962809898f..2aa08b7da25f159640e0640482d40c69b060bb9f 100644 ---- a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java -+++ b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java -@@ -192,7 +192,14 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock { - } - - chiseledBookShelfBlockEntity.clearContent(); -- flag = true; -+ // Leaves start - behaviour 1.21.1- -+ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockEntityBehaviour) { -+ flag = false; -+ level.updateNeighbourForOutputSignal(pos, this); -+ } else { -+ flag = true; -+ } -+ // Leaves end - behaviour 1.21.1- - } else { - flag = false; - } -diff --git a/net/minecraft/world/level/block/LecternBlock.java b/net/minecraft/world/level/block/LecternBlock.java -index 82fcae1f8b4149f13adf5118287718812518f8bf..d6e4e2f9d762d512d22a4da3736f997d2cd9624d 100644 ---- a/net/minecraft/world/level/block/LecternBlock.java -+++ b/net/minecraft/world/level/block/LecternBlock.java -@@ -237,10 +237,11 @@ public class LecternBlock extends BaseEntityBlock { - this.popBook(state, level, pos); - } - -- super.onRemove(state, level, pos, newState, isMoving); -+ if (!org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockEntityBehaviour) super.onRemove(state, level, pos, newState, isMoving); // Leaves - behaviour 1.21.1- - if (state.getValue(POWERED)) { - updateBelow(level, pos, state); - } -+ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockEntityBehaviour) super.onRemove(state, level, pos, newState, isMoving); // Leaves - behaviour 1.21.1- - } - } - -diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java -index 2fd1bae800b7dca0a58b572095e2c58012412481..237e5a48dc345cae90aa9921251fe48d1c2470e1 100644 ---- a/net/minecraft/world/level/block/SculkSensorBlock.java -+++ b/net/minecraft/world/level/block/SculkSensorBlock.java -@@ -138,10 +138,11 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg - @Override - protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) { - if (!state.is(newState.getBlock())) { -- super.onRemove(state, level, pos, newState, movedByPiston); -+ if (!org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockEntityBehaviour) super.onRemove(state, level, pos, newState, movedByPiston); // Leaves - behaviour 1.21.1- - if (getPhase(state) == SculkSensorPhase.ACTIVE) { - updateNeighbours(level, pos, state); - } -+ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockEntityBehaviour) super.onRemove(state, level, pos, newState, movedByPiston); // Leaves - behaviour 1.21.1- - } - } - -diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java -index fca50f68625050daabcae3a3b615cf88cce41111..a5786b13f21781c2e85a6a7910ce42005f8951c8 100644 ---- a/net/minecraft/world/level/block/ShulkerBoxBlock.java -+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java -@@ -178,10 +178,11 @@ public class ShulkerBoxBlock extends BaseEntityBlock { - protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { - if (!state.is(newState.getBlock())) { - BlockEntity blockEntity = level.getBlockEntity(pos); -- super.onRemove(state, level, pos, newState, isMoving); -+ if (!org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockEntityBehaviour) super.onRemove(state, level, pos, newState, isMoving); // Leaves - behaviour 1.21.1- - if (blockEntity instanceof ShulkerBoxBlockEntity) { - level.updateNeighbourForOutputSignal(pos, state.getBlock()); - } -+ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockEntityBehaviour) super.onRemove(state, level, pos, newState, isMoving); // Leaves - behaviour 1.21.1- - } - } - -diff --git a/net/minecraft/world/level/block/entity/BlockEntity.java b/net/minecraft/world/level/block/entity/BlockEntity.java -index 77618757c0e678532dbab814aceed83f7f1cd892..fa78fc79b6000832d8623e632d845cf942496428 100644 ---- a/net/minecraft/world/level/block/entity/BlockEntity.java -+++ b/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -55,7 +55,7 @@ public abstract class BlockEntity { - } - - public boolean isValidBlockState(BlockState state) { -- return this.type.isValid(state); -+ return org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockEntityBehaviour || this.type.isValid(state); // Leaves - behaviour 1.21.1- - } - - public static BlockPos getPosFromTag(CompoundTag tag) { diff --git a/leaves-server/minecraft-patches/features/0108-Revert-raid-changes.patch b/leaves-server/minecraft-patches/features/0108-Revert-raid-changes.patch index 37350661..b3698ec1 100644 --- a/leaves-server/minecraft-patches/features/0108-Revert-raid-changes.patch +++ b/leaves-server/minecraft-patches/features/0108-Revert-raid-changes.patch @@ -21,17 +21,17 @@ index 80f17f33f670018240c854df589cf90cdeab6e70..4c6ce6a4a730033802651b0c0052fc46 if (raidAt == null || raidAt.getRaidOmenLevel() < raidAt.getMaxRaidOmenLevel()) { serverPlayer.addEffect(new MobEffectInstance(MobEffects.RAID_OMEN, 600, amplifier)); diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java -index 41b0db439b425b052bd1469daa6620a435ca852b..4e2b73ad91b4fc12da123b22910a7e3a78b23d1d 100644 +index 62a3a8d46e10e6f02e3f515bbce5d9ba1f6566b8..6a45e00490f0067d25010371f7c5fa40bbe7671c 100644 --- a/net/minecraft/world/entity/raid/Raid.java +++ b/net/minecraft/world/entity/raid/Raid.java -@@ -318,7 +318,20 @@ public class Raid { +@@ -333,7 +333,20 @@ public class Raid { } if (flag1) { -- this.waveSpawnPos = this.getValidSpawnPos(); +- this.waveSpawnPos = this.getValidSpawnPos(level); + // Leaves Start - old FindSpawnPosition + if (!org.leavesmc.leaves.LeavesConfig.modify.oldMC.raid.useOldFindSpawnPosition) { -+ this.waveSpawnPos = this.getValidSpawnPos(); ++ this.waveSpawnPos = this.getValidSpawnPos(level); + } else { + int n4 = 0; + if (this.raidCooldownTicks < 100) { @@ -40,63 +40,63 @@ index 41b0db439b425b052bd1469daa6620a435ca852b..4e2b73ad91b4fc12da123b22910a7e3a + if (this.raidCooldownTicks < 40) { + n4 = 2; + } -+ this.waveSpawnPos = this.getValidSpawnPos(n4); ++ this.waveSpawnPos = this.getValidSpawnPos(level, n4); + } + // Leaves End - old FindSpawnPosition } if (this.raidCooldownTicks == 300 || this.raidCooldownTicks % 20 == 0) { -@@ -353,7 +366,14 @@ public class Raid { +@@ -368,7 +381,14 @@ public class Raid { int i = 0; while (this.shouldSpawnGroup()) { -- BlockPos blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(20)); +- BlockPos blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20)); + // Leaves Start - old FindSpawnPosition + BlockPos blockPos; + if (!org.leavesmc.leaves.LeavesConfig.modify.oldMC.raid.useOldFindSpawnPosition) { -+ blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(20)); ++ blockPos = this.waveSpawnPos.orElseGet(() -> this.findRandomSpawnPos(level, 20)); + } else { -+ blockPos = this.waveSpawnPos.isPresent() ? this.waveSpawnPos.get() : this.findRandomSpawnPos(i, 20); ++ blockPos = this.waveSpawnPos.isPresent() ? this.waveSpawnPos.get() : this.findRandomSpawnPos(level, i, 20); + } + // Leaves End - old FindSpawnPosition if (blockPos != null) { this.started = true; - this.spawnGroup(blockPos); -@@ -365,7 +385,7 @@ public class Raid { + this.spawnGroup(level, blockPos); +@@ -380,7 +400,7 @@ public class Raid { i++; } - if (i > 5) { + if (i > (org.leavesmc.leaves.LeavesConfig.modify.oldMC.raid.useOldFindSpawnPosition ? 3 : 5)) { // Leaves - old FindSpawnPosition - org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit + org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(level, this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit this.stop(); break; -@@ -680,6 +700,35 @@ public class Raid { +@@ -686,6 +706,36 @@ public class Raid { return null; } + // Leaves Start - old FindSpawnPosition + @Nullable -+ private BlockPos findRandomSpawnPos(int n, int n2) { ++ private BlockPos findRandomSpawnPos(ServerLevel level, int n, int n2) { + int n3 = 2 - n; + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + SpawnPlacementType spawnPlacementType = SpawnPlacements.getPlacementType(EntityType.RAVAGER); + for (int i = 0; i < n2; ++i) { -+ float f = this.level.random.nextFloat() * ((float)Math.PI * 2); -+ int n4 = this.center.getX() + Mth.floor(Mth.cos(f) * 32.0f * (float)n3) + this.level.random.nextInt(5); -+ int n5 = this.center.getZ() + Mth.floor(Mth.sin(f) * 32.0f * (float)n3) + this.level.random.nextInt(5); -+ int n6 = this.level.getHeight(Heightmap.Types.WORLD_SURFACE, n4, n5); ++ float f = level.random.nextFloat() * ((float)Math.PI * 2); ++ int n4 = this.center.getX() + Mth.floor(Mth.cos(f) * 32.0f * (float)n3) + level.random.nextInt(5); ++ int n5 = this.center.getZ() + Mth.floor(Mth.sin(f) * 32.0f * (float)n3) + level.random.nextInt(5); ++ int n6 = level.getHeight(Heightmap.Types.WORLD_SURFACE, n4, n5); + mutableBlockPos.set(n4, n6, n5); -+ if (this.level.isVillage(mutableBlockPos) && n < 2) continue; -+ if (!this.level.hasChunksAt(mutableBlockPos.getX() - 10, mutableBlockPos.getZ() - 10, mutableBlockPos.getX() + 10, mutableBlockPos.getZ() + 10) || !this.level.isPositionEntityTicking(mutableBlockPos) || !spawnPlacementType.isSpawnPositionOk(this.level, mutableBlockPos, EntityType.RAVAGER) && (!this.level.getBlockState((BlockPos)mutableBlockPos.below()).is(Blocks.SNOW) || !this.level.getBlockState(mutableBlockPos).isAir())) continue; ++ if (level.isVillage(mutableBlockPos) && n < 2) continue; ++ if (!level.hasChunksAt(mutableBlockPos.getX() - 10, mutableBlockPos.getZ() - 10, mutableBlockPos.getX() + 10, mutableBlockPos.getZ() + 10) || !level.isPositionEntityTicking(mutableBlockPos) || !spawnPlacementType.isSpawnPositionOk(level, mutableBlockPos, EntityType.RAVAGER) && (!level.getBlockState((BlockPos)mutableBlockPos.below()).is(Blocks.SNOW) || !level.getBlockState(mutableBlockPos).isAir())) continue; + return mutableBlockPos; + } + return null; + } + -+ private Optional getValidSpawnPos(int n) { ++ private Optional getValidSpawnPos(ServerLevel level, int n) { + for (int i = 0; i < 3; ++i) { -+ BlockPos blockPos = this.findRandomSpawnPos(n, 1); ++ BlockPos blockPos = this.findRandomSpawnPos(level, n, 1); + if (blockPos == null) continue; + return Optional.of(blockPos); + } @@ -104,26 +104,27 @@ index 41b0db439b425b052bd1469daa6620a435ca852b..4e2b73ad91b4fc12da123b22910a7e3a + } + // Leaves End - old FindSpawnPosition + - private boolean addWaveMob(int wave, Raider raider) { - return this.addWaveMob(wave, raider, true); ++ + private boolean addWaveMob(ServerLevel level, int wave, Raider raider) { + return this.addWaveMob(level, wave, raider, true); } diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java -index f58a20e7dd6b8dc3fc431d4aba9f91a7c25f2c33..ce692698260d4751b13d5b26f7d9403c72b413c6 100644 +index 39a6a4579931d7edb7ab8c072d62cfc9b02791c8..23c0581ad4e3921f89070609ec7c01d8a5a9b2de 100644 --- a/net/minecraft/world/entity/raid/Raider.java +++ b/net/minecraft/world/entity/raid/Raider.java -@@ -125,6 +125,43 @@ public abstract class Raider extends PatrollingMonster { +@@ -127,6 +127,43 @@ public abstract class Raider extends PatrollingMonster { - currentRaid.removeFromRaid(this, false); + currentRaid.removeFromRaid(serverLevel, this, false); } + + // Leaves start - Revert raid changes -+ if (this.level() instanceof ServerLevel serverLevel) { ++ if (this.level() instanceof ServerLevel) { + if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.raid.giveBadOmenWhenKillPatrolLeader && !this.hasRaid()) { + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); + net.minecraft.world.entity.player.Player entityhuman = null; + if (entity instanceof net.minecraft.world.entity.player.Player player) { + entityhuman = player; -+ } else if (entity instanceof net.minecraft.world.entity.animal.Wolf wolf) { ++ } else if (entity instanceof net.minecraft.world.entity.animal.wolf.Wolf wolf) { + LivingEntity entityliving = wolf.getOwner(); + if (wolf.isTame() && entityliving instanceof net.minecraft.world.entity.player.Player player) { + entityhuman = player; diff --git a/leaves-server/minecraft-patches/features/0109-Allow-anvil-destroy-item-entities.patch b/leaves-server/minecraft-patches/features/0109-Allow-anvil-destroy-item-entities.patch index e50f564d..dcf72837 100644 --- a/leaves-server/minecraft-patches/features/0109-Allow-anvil-destroy-item-entities.patch +++ b/leaves-server/minecraft-patches/features/0109-Allow-anvil-destroy-item-entities.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Allow anvil destroy item entities diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java -index 35d5dd7ca192ae384ecfd858e7c898c9f4b841b4..ce4995fe70e885aa7ad1cc191ccd4cdd5e5b9681 100644 +index b6e188cf9f224a9c4b75339acd0306758bf0cb71..ff8cd3d52bf9f3d117abfd7022d7f2ac8525e46a 100644 --- a/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -278,7 +278,7 @@ public class FallingBlockEntity extends Entity { +@@ -275,7 +275,7 @@ public class FallingBlockEntity extends Entity { if (ceil < 0) { return false; } else { - Predicate predicate = EntitySelector.NO_CREATIVE_OR_SPECTATOR.and(EntitySelector.LIVING_ENTITY_STILL_ALIVE); + Predicate predicate = org.leavesmc.leaves.LeavesConfig.modify.oldMC.allowAnvilDestroyItemEntities ? EntitySelector.NO_CREATIVE_OR_SPECTATOR : EntitySelector.NO_CREATIVE_OR_SPECTATOR.and(EntitySelector.LIVING_ENTITY_STILL_ALIVE); // Leaves - Allow anvil destroy item entities - DamageSource damageSource = this.blockState.getBlock() instanceof Fallable fallable + DamageSource damageSource1 = this.blockState.getBlock() instanceof Fallable fallable ? fallable.getFallDamageSource(this) : this.damageSources().fallingBlock(this); diff --git a/leaves-server/minecraft-patches/features/0110-Configurable-collision-behavior.patch b/leaves-server/minecraft-patches/features/0110-Configurable-collision-behavior.patch new file mode 100644 index 00000000..66fdd2a6 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0110-Configurable-collision-behavior.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fortern +Date: Thu, 24 Oct 2024 23:10:34 +0800 +Subject: [PATCH] Configurable collision behavior + + +diff --git a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java +index a97a2a8492f3858e3b622d26768b4d819c9b47a7..7178f8477d5c3840225b21ec1fb6612e660b85d3 100644 +--- a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java ++++ b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java +@@ -101,6 +101,14 @@ public final class CollisionUtil { + (box1.minZ - box2.maxZ) < -COLLISION_EPSILON && (box1.maxZ - box2.minZ) > COLLISION_EPSILON; + } + ++ // Leaves start - Configurable collision behavior ++ public static boolean voxelShapeIntersectVanilla(final AABB box1, final AABB box2) { ++ return box1.minX < box2.maxX && box1.maxX > box2.minX && ++ box1.minY < box2.maxY && box1.maxY > box2.minY && ++ box1.minZ < box2.maxZ && box1.maxZ > box2.minZ; ++ } ++ // Leaves end - Configurable collision behavior ++ + // assume !isEmpty(target) && abs(source_move) >= COLLISION_EPSILON + public static double collideX(final AABB target, final AABB source, final double source_move) { + if ((source.minY - target.maxY) < -COLLISION_EPSILON && (source.maxY - target.minY) > COLLISION_EPSILON && +@@ -2014,7 +2022,9 @@ public final class CollisionUtil { + AABB singleAABB = ((CollisionVoxelShape)blockCollision).moonrise$getSingleAABBRepresentation(); + if (singleAABB != null) { + singleAABB = singleAABB.move((double)blockX, (double)blockY, (double)blockZ); +- if (!voxelShapeIntersect(aabb, singleAABB)) { ++ // Leaves start - Configurable collision behavior ++ if (shouldSkip(aabb, blockCollision, singleAABB)) { ++ // Leaves end - Configurable collision behavior + continue; + } + +@@ -2067,6 +2077,17 @@ public final class CollisionUtil { + return ret; + } + ++ // Leaves start - Configurable collision behavior ++ private static boolean shouldSkip(net.minecraft.world.phys.AABB aabb, net.minecraft.world.phys.shapes.VoxelShape blockCollision, net.minecraft.world.phys.AABB singleAABB) { ++ boolean isBlockShape = blockCollision == net.minecraft.world.phys.shapes.Shapes.block(); ++ return switch (org.leavesmc.leaves.LeavesConfig.fix.collisionBehavior) { ++ case PAPER -> !voxelShapeIntersect(aabb, singleAABB); ++ case VANILLA -> !voxelShapeIntersectVanilla(aabb, singleAABB); ++ case BLOCK_SHAPE_VANILLA -> isBlockShape && !voxelShapeIntersectVanilla(aabb, singleAABB) || !isBlockShape && !voxelShapeIntersect(aabb, singleAABB); ++ }; ++ } ++ // Leaves end - Configurable collision behavior ++ + public static boolean getEntityHardCollisions(final Level world, final Entity entity, AABB aabb, + final List into, final int collisionFlags, final Predicate predicate) { + final boolean checkOnly = (collisionFlags & COLLISION_FLAG_CHECK_ONLY) != 0; diff --git a/leaves-server/minecraft-patches/features/0110-Fix-Incorrect-Collision-Behavior-for-Block-Shape.patch b/leaves-server/minecraft-patches/features/0110-Fix-Incorrect-Collision-Behavior-for-Block-Shape.patch deleted file mode 100644 index be3df604..00000000 --- a/leaves-server/minecraft-patches/features/0110-Fix-Incorrect-Collision-Behavior-for-Block-Shape.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Fortern -Date: Thu, 24 Oct 2024 23:10:34 +0800 -Subject: [PATCH] Fix Incorrect Collision Behavior for Block Shape - - -diff --git a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java -index e04bd54744335fb5398c6e4f7ce8b981f35bfb7d..b3c9d4f5f2ebf8fe981999ea9465e0f5754c5d6f 100644 ---- a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java -+++ b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java -@@ -101,6 +101,14 @@ public final class CollisionUtil { - (box1.minZ - box2.maxZ) < -COLLISION_EPSILON && (box1.maxZ - box2.minZ) > COLLISION_EPSILON; - } - -+ // Leaves start -+ public static boolean voxelShapeIntersectVanilla(final net.minecraft.world.phys.AABB box1, final net.minecraft.world.phys.AABB box2) { -+ return box1.minX < box2.maxX && box1.maxX > box2.minX && -+ box1.minY < box2.maxY && box1.maxY > box2.minY && -+ box1.minZ < box2.maxZ && box1.maxZ > box2.minZ; -+ } -+ // Leaves end -+ - // assume !isEmpty(target) && abs(source_move) >= COLLISION_EPSILON - public static double collideX(final AABB target, final AABB source, final double source_move) { - if ((source.minY - target.maxY) < -COLLISION_EPSILON && (source.maxY - target.minY) > COLLISION_EPSILON && -@@ -2015,7 +2023,10 @@ public final class CollisionUtil { - AABB singleAABB = ((CollisionVoxelShape)blockCollision).moonrise$getSingleAABBRepresentation(); - if (singleAABB != null) { - singleAABB = singleAABB.move((double)blockX, (double)blockY, (double)blockZ); -- if (!voxelShapeIntersect(aabb, singleAABB)) { -+ // Leaves start - Fix incorrect collision behavior for block shape -+ boolean isBlockShape = blockCollision == net.minecraft.world.phys.shapes.Shapes.block(); -+ if (isBlockShape && !voxelShapeIntersectVanilla(aabb, singleAABB) || !isBlockShape && !voxelShapeIntersect(aabb, singleAABB)) { -+ // Leaves end - Fix incorrect collision behavior for block shape - continue; - } - diff --git a/leaves-server/minecraft-patches/features/0111-Disable-vault-blacklist.patch b/leaves-server/minecraft-patches/features/0111-Disable-vault-blacklist.patch index 94bdd3f8..7ba37e28 100644 --- a/leaves-server/minecraft-patches/features/0111-Disable-vault-blacklist.patch +++ b/leaves-server/minecraft-patches/features/0111-Disable-vault-blacklist.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Disable vault blacklist diff --git a/net/minecraft/world/level/block/entity/vault/VaultServerData.java b/net/minecraft/world/level/block/entity/vault/VaultServerData.java -index 9bf95455f93a17c53bf457d90fd30a3595227569..f580b2431edf8768a60c57de84da64682d017d8f 100644 +index c73ccb38eb4cd5995a9005f3319acad2605c6a2b..5500eeafb5c8d15049a5308c18323f549d7fde3e 100644 --- a/net/minecraft/world/level/block/entity/vault/VaultServerData.java +++ b/net/minecraft/world/level/block/entity/vault/VaultServerData.java -@@ -61,7 +61,7 @@ public class VaultServerData { +@@ -57,7 +57,7 @@ public class VaultServerData { } boolean hasRewardedPlayer(Player player) { @@ -17,7 +17,7 @@ index 9bf95455f93a17c53bf457d90fd30a3595227569..f580b2431edf8768a60c57de84da6468 } @VisibleForTesting -@@ -70,6 +70,7 @@ public class VaultServerData { +@@ -66,6 +66,7 @@ public class VaultServerData { addToRewardedPlayers(player.getUUID()); } public boolean addToRewardedPlayers(final java.util.UUID player) { @@ -26,7 +26,7 @@ index 9bf95455f93a17c53bf457d90fd30a3595227569..f580b2431edf8768a60c57de84da6468 // Paper end - Vault API if (this.rewardedPlayers.size() > 128) { diff --git a/net/minecraft/world/level/block/entity/vault/VaultSharedData.java b/net/minecraft/world/level/block/entity/vault/VaultSharedData.java -index 50d6ff126a35ce8613175b550dac50cd82c43f9d..13ba4407b639ca64224348dd898c30d1256b13fa 100644 +index 036087f8085f05b43703ceca3413e0b8ac0a412b..a55c773f37cf8a50954d9a0f28868e42d94ad90e 100644 --- a/net/minecraft/world/level/block/entity/vault/VaultSharedData.java +++ b/net/minecraft/world/level/block/entity/vault/VaultSharedData.java @@ -68,8 +68,8 @@ public class VaultSharedData { diff --git a/leaves-server/minecraft-patches/features/0112-Fix-EntityPortalExitEvent-logic.patch b/leaves-server/minecraft-patches/features/0112-Fix-EntityPortalExitEvent-logic.patch index 93182e4f..b93951f9 100644 --- a/leaves-server/minecraft-patches/features/0112-Fix-EntityPortalExitEvent-logic.patch +++ b/leaves-server/minecraft-patches/features/0112-Fix-EntityPortalExitEvent-logic.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix EntityPortalExitEvent logic diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index ca599cbb240f9ae0a7d83cc13684e37e4bbeeb65..4de7f2a2257c7071ecf1f06ab30cc6e31c5ce065 100644 +index a85e8e4df0247ff6b3d4048c9c7a0f1134970c93..91038b21164d3e1bf6406117478454d38b24bb81 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -3790,19 +3790,29 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3774,19 +3774,29 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } if (this.portalProcess != null) { // if in a portal org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity = this.getBukkitEntity(); @@ -23,20 +23,20 @@ index ca599cbb240f9ae0a7d83cc13684e37e4bbeeb65..4de7f2a2257c7071ecf1f06ab30cc6e3 + // Leaves start - fix // Only change the target if actually needed, since we reset relative flags -- if (!event.isCancelled() && event.getTo() != null && (!event.getTo().equals(event.getFrom()) || !event.getAfter().equals(event.getBefore()))) { +- if (!event.isCancelled() && event.getTo() != null && (!event.getTo().equals(event.getFrom()) || !event.getAfter().equals(event.getBefore()))) { // todo this looks broken - to = event.getTo().clone(); -- velocity = org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getAfter()); +- velocity = org.bukkit.craftbukkit.util.CraftVector.toVec3(event.getAfter()); + if (event.isCancelled() || (!to.equals(event.getTo()) || !after.equals(event.getAfter()))) { + if (!event.isCancelled()) { + if (event.getTo() != null) { + to = event.getTo().clone(); + } -+ velocity = org.bukkit.craftbukkit.util.CraftVector.toNMS(event.getAfter()); ++ velocity = org.bukkit.craftbukkit.util.CraftVector.toVec3(event.getAfter()); + } else { + to = event.getFrom().clone(); + velocity = Vec3.ZERO; + } - teleportTransition = new TeleportTransition(((org.bukkit.craftbukkit.CraftWorld) to.getWorld()).getHandle(), org.bukkit.craftbukkit.util.CraftLocation.toVec3D(to), velocity, to.getYaw(), to.getPitch(), teleportTransition.missingRespawnBlock(), teleportTransition.asPassenger(), Set.of(), teleportTransition.postTeleportTransition(), teleportTransition.cause()); + teleportTransition = new TeleportTransition(((org.bukkit.craftbukkit.CraftWorld) to.getWorld()).getHandle(), org.bukkit.craftbukkit.util.CraftLocation.toVec3(to), velocity, to.getYaw(), to.getPitch(), teleportTransition.missingRespawnBlock(), teleportTransition.asPassenger(), Set.of(), teleportTransition.postTeleportTransition(), teleportTransition.cause()); } + // Leaves end - fix } diff --git a/leaves-server/minecraft-patches/features/0113-Fix-CraftPortalEvent-logic.patch b/leaves-server/minecraft-patches/features/0113-Fix-CraftPortalEvent-logic.patch index dd8181e5..cca040dc 100644 --- a/leaves-server/minecraft-patches/features/0113-Fix-CraftPortalEvent-logic.patch +++ b/leaves-server/minecraft-patches/features/0113-Fix-CraftPortalEvent-logic.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix CraftPortalEvent logic diff --git a/net/minecraft/world/level/block/EndPortalBlock.java b/net/minecraft/world/level/block/EndPortalBlock.java -index c11366dd69e1c51bdab45c625b07c15ce2e42cb6..31ac2e7047065333d5033ea2ef4c56877a425ee7 100644 +index cf2b105c98a3b22b9bea59cbafcd598657dc92b5..22ffa5743f95d28f29084f1dd357015aee032711 100644 --- a/net/minecraft/world/level/block/EndPortalBlock.java +++ b/net/minecraft/world/level/block/EndPortalBlock.java -@@ -102,9 +102,9 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { +@@ -103,9 +103,9 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { } // CraftBukkit start diff --git a/leaves-server/minecraft-patches/features/0114-Xaero-Map-Protocol.patch b/leaves-server/minecraft-patches/features/0114-Xaero-Map-Protocol.patch index 12a417ab..15d45284 100644 --- a/leaves-server/minecraft-patches/features/0114-Xaero-Map-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0114-Xaero-Map-Protocol.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Xaero Map Protocol diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 9187e876a3e226a9f28af32630122f2ead72b6f3..2aafa4a3e5314b69bbb8deedb5df3a8979efc5d9 100644 +index 28456eab6d5c31cf33fd9918d7306b078a97bd41..4b28145e73664ad3149d978b7ec1e1d3915f3cdc 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -1323,6 +1323,7 @@ public abstract class PlayerList { +@@ -1340,6 +1340,7 @@ public abstract class PlayerList { player.connection.send(new ClientboundInitializeBorderPacket(worldBorder)); player.connection.send(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle())); diff --git a/leaves-server/minecraft-patches/features/0115-Skip-negligible-planar-movement-multiplication.patch b/leaves-server/minecraft-patches/features/0115-Skip-negligible-planar-movement-multiplication.patch index 5f9323fb..fae0c2bd 100644 --- a/leaves-server/minecraft-patches/features/0115-Skip-negligible-planar-movement-multiplication.patch +++ b/leaves-server/minecraft-patches/features/0115-Skip-negligible-planar-movement-multiplication.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Skip negligible planar movement multiplication This patch is Powered by Gale(https://github.com/Dreeam-qwq/Gale) diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 7bb90470233aaaf13b71dddbef7d227018c4622f..1871a020dc3a66abef4acce3d2953a90262d3f3b 100644 +index 91038b21164d3e1bf6406117478454d38b24bb81..d768b1de1bc75ab73198379b1099cc09f58d1ca4 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -1223,8 +1223,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1218,8 +1218,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } diff --git a/leaves-server/minecraft-patches/features/0116-Skippable-raid-height-check.patch b/leaves-server/minecraft-patches/features/0116-Skippable-raid-height-check.patch index daeaa96c..f344d36b 100644 --- a/leaves-server/minecraft-patches/features/0116-Skippable-raid-height-check.patch +++ b/leaves-server/minecraft-patches/features/0116-Skippable-raid-height-check.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Skippable raid height check diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java -index 9712dc3da64e5c5f653eef353c0247805ccca685..e24260e808b50ad0eb7e2d2e41d11e20d0067a69 100644 +index 6a45e00490f0067d25010371f7c5fa40bbe7671c..8e08a187da6f40d1b3bc990401af36e510537777 100644 --- a/net/minecraft/world/entity/raid/Raid.java +++ b/net/minecraft/world/entity/raid/Raid.java -@@ -680,7 +680,7 @@ public class Raid { - int i2 = this.center.getX() + Mth.floor(Mth.cos(f2) * 32.0F * f) + this.level.random.nextInt(3) * Mth.floor(f); - int i3 = this.center.getZ() + Mth.floor(Mth.sin(f2) * 32.0F * f) + this.level.random.nextInt(3) * Mth.floor(f); - int height = this.level.getHeight(Heightmap.Types.WORLD_SURFACE, i2, i3); +@@ -687,7 +687,7 @@ public class Raid { + int i2 = this.center.getX() + Mth.floor(Mth.cos(f2) * 32.0F * f) + level.random.nextInt(3) * Mth.floor(f); + int i3 = this.center.getZ() + Mth.floor(Mth.sin(f2) * 32.0F * f) + level.random.nextInt(3) * Mth.floor(f); + int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, i2, i3); - if (Mth.abs(height - this.center.getY()) <= 96) { + if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.raid.skipHeightCheck || Mth.abs(height - this.center.getY()) <= 96) { // Leaves - skippable mutableBlockPos.set(i2, height, i3); - if (!this.level.isVillage(mutableBlockPos) || i <= 7) { + if (!level.isVillage(mutableBlockPos) || i <= 7) { int i4 = 10; diff --git a/leaves-server/minecraft-patches/features/0117-Support-REI-protocol.patch b/leaves-server/minecraft-patches/features/0117-Support-REI-protocol.patch index e51de136..31eca217 100644 --- a/leaves-server/minecraft-patches/features/0117-Support-REI-protocol.patch +++ b/leaves-server/minecraft-patches/features/0117-Support-REI-protocol.patch @@ -4,32 +4,37 @@ Date: Thu, 27 Mar 2025 13:04:35 +0800 Subject: [PATCH] Support REI protocol -diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index d89a1aa9355205883412eaaf535dad30f945a4dc..33e05636164144b3d2bdbd091c72583728cc294e 100644 ---- a/net/minecraft/server/players/PlayerList.java -+++ b/net/minecraft/server/players/PlayerList.java -@@ -1624,6 +1624,7 @@ public abstract class PlayerList { - serverPlayer.getRecipeBook().sendInitialRecipeBook(serverPlayer); - } - org.leavesmc.leaves.protocol.BBORProtocol.onDataPackReload(); // Leaves - bbor -+ org.leavesmc.leaves.protocol.rei.REIServerProtocol.onRecipeReload(); // Leaves - rei - } - - public boolean isAllowCommandsForAllPlayers() { diff --git a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java -index 143601053a6aeea4396f8e0ee0746ff7d5bbb323..0af83ec1fe3aa85c6bfc814a1339a54e9d3725d6 100644 +index 9bc0a9c3577d63a0ad5489bfd4c07d5006245c5f..bb2e891539b7eb49dc7925630695149aa531f672 100644 --- a/net/minecraft/world/item/crafting/SmithingTransformRecipe.java +++ b/net/minecraft/world/item/crafting/SmithingTransformRecipe.java -@@ -87,6 +87,12 @@ public class SmithingTransformRecipe implements SmithingRecipe { +@@ -83,6 +83,12 @@ public class SmithingTransformRecipe implements SmithingRecipe { ); } -+ // Leaves start -+ public ItemStack getResult() { -+ return this.result.copy(); ++ // Leaves start - REI ++ public SlotDisplay getResult() { ++ return this.result.display(); + } -+ // Leaves end ++ // Leaves end - REI + // CraftBukkit start @Override public org.bukkit.inventory.Recipe toBukkitRecipe(org.bukkit.NamespacedKey id) { +diff --git a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java +index c324896afc2ee28ebb4d426ce4a469ee847ce24d..d5b26ff7be916e07e1162536cb2ddf5674c82f46 100644 +--- a/net/minecraft/world/item/crafting/SmithingTrimRecipe.java ++++ b/net/minecraft/world/item/crafting/SmithingTrimRecipe.java +@@ -85,6 +85,12 @@ public class SmithingTrimRecipe implements SmithingRecipe { + return Optional.of(this.addition); + } + ++ // Leaves start ++ public Holder pattern() { ++ return pattern; ++ } ++ // Leaves end ++ + @Override + public RecipeSerializer getSerializer() { + return RecipeSerializer.SMITHING_TRIM; diff --git a/leaves-server/minecraft-patches/features/0118-Vanilla-player-display-name.patch b/leaves-server/minecraft-patches/features/0118-Vanilla-player-display-name.patch index b028ef14..3e7f52c6 100644 --- a/leaves-server/minecraft-patches/features/0118-Vanilla-player-display-name.patch +++ b/leaves-server/minecraft-patches/features/0118-Vanilla-player-display-name.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Vanilla player display name diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index eba1717566a8ea534bbf149e0593cc7656df2db9..311d4abc9cbd99e6b03135dadbd8ee93e7bc4a48 100644 +index f144a8bd5eb55ce093ad92ffd1304860dc52c1b1..fa93076169e19c7d2d1134dea297968a650dc220 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -449,7 +449,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -471,7 +471,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc // CraftBukkit start this.displayName = this.getScoreboardName(); diff --git a/leaves-server/minecraft-patches/features/0120-Fix-SculkCatalyst-exp-skip.patch b/leaves-server/minecraft-patches/features/0119-Fix-SculkCatalyst-exp-skip.patch similarity index 83% rename from leaves-server/minecraft-patches/features/0120-Fix-SculkCatalyst-exp-skip.patch rename to leaves-server/minecraft-patches/features/0119-Fix-SculkCatalyst-exp-skip.patch index c714d0d4..00868387 100644 --- a/leaves-server/minecraft-patches/features/0120-Fix-SculkCatalyst-exp-skip.patch +++ b/leaves-server/minecraft-patches/features/0119-Fix-SculkCatalyst-exp-skip.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix SculkCatalyst exp skip diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 311d4abc9cbd99e6b03135dadbd8ee93e7bc4a48..43fcd9c0fa419ed36c677003d75cfa84ea93baa2 100644 +index fa93076169e19c7d2d1134dea297968a650dc220..d4984c919a88fa930dfec823cd9b471fa47f3565 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -1153,7 +1153,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1087,7 +1087,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc } // SPIGOT-5478 must be called manually now @@ -17,7 +17,7 @@ index 311d4abc9cbd99e6b03135dadbd8ee93e7bc4a48..43fcd9c0fa419ed36c677003d75cfa84 // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. if (!event.getKeepInventory()) { // Paper start - PlayerDeathEvent#getItemsToKeep -@@ -1187,6 +1187,15 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1134,6 +1134,15 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.setClientLoaded(false); } @@ -34,18 +34,18 @@ index 311d4abc9cbd99e6b03135dadbd8ee93e7bc4a48..43fcd9c0fa419ed36c677003d75cfa84 AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0); this.level() diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index b1b738bcd20cbc927bdbac6ab10e28f79fd8a23b..e61e5c5b3777c8861f090ada2a4ddaaf88116329 100644 +index d2f5118ceeebf95496daabf7597655d6565ad116..8975acf713dd806693e3b3045c98e53321a2e5f4 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -293,6 +293,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - protected float appliedScale = 1.0F; +@@ -264,6 +264,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + protected final EntityEquipment equipment; // CraftBukkit start public int expToDrop; + public int expToReward; // Leaves - exp fix - public ArrayList drops = new ArrayList<>(); // Paper - Restore vanilla drops behavior + public List drops = new java.util.ArrayList<>(); // Paper - Restore vanilla drops behavior public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes; public boolean collides = true; -@@ -1743,6 +1744,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1829,6 +1830,7 @@ public abstract class LivingEntity extends Entity implements Attackable { entity.killedEntity((ServerLevel) this.level(), this); } this.gameEvent(GameEvent.ENTITY_DIE); @@ -53,8 +53,8 @@ index b1b738bcd20cbc927bdbac6ab10e28f79fd8a23b..e61e5c5b3777c8861f090ada2a4ddaaf } else { this.dead = false; this.setHealth((float) deathEvent.getReviveHealth()); -@@ -1817,7 +1819,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.drops = new ArrayList<>(); +@@ -1902,7 +1904,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + this.drops = new java.util.ArrayList<>(); // this.dropEquipment(level); // CraftBukkit - moved up // CraftBukkit end - this.dropExperience(level, damageSource.getEntity()); @@ -63,7 +63,7 @@ index b1b738bcd20cbc927bdbac6ab10e28f79fd8a23b..e61e5c5b3777c8861f090ada2a4ddaaf } diff --git a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -index 1638eccef431fb68775af624110f1968f0c6dabd..117748f385cecabef890d27af55d88abee6adf4b 100644 +index 2627583ab12d886b1fba0b1d1e599f942926b499..be09fa81ed1e58a271156299dacf49be649eecfc 100644 --- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java @@ -96,8 +96,7 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi diff --git a/leaves-server/minecraft-patches/features/0120-Vanilla-creative-pickup-behavior.patch b/leaves-server/minecraft-patches/features/0120-Vanilla-creative-pickup-behavior.patch new file mode 100644 index 00000000..dfef9d82 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0120-Vanilla-creative-pickup-behavior.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> +Date: Sat, 10 May 2025 00:49:51 +0800 +Subject: [PATCH] Vanilla creative pickup behavior + + +diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java +index 57bf2819271b3293a065b58d31b609f8463811b4..1d61b01d32783357ea5d766cb716ba4c7edb1407 100644 +--- a/net/minecraft/world/entity/player/Inventory.java ++++ b/net/minecraft/world/entity/player/Inventory.java +@@ -159,6 +159,13 @@ public class Inventory implements Container, Nameable { + // CraftBukkit start - Watch method above! :D + public int canHold(ItemStack itemStack) { + int remains = itemStack.getCount(); ++ ++ // Leaves start - vanilla creative pickup behavior ++ if (player.hasInfiniteMaterials()) { ++ return remains; ++ } ++ // Leaves end - vanilla creative pickup behavior ++ + for (int slot = 0; slot < this.items.size(); ++slot) { + ItemStack itemInSlot = this.getItem(slot); + if (itemInSlot.isEmpty()) { diff --git a/leaves-server/minecraft-patches/features/0121-Vanilla-portal-handle.patch b/leaves-server/minecraft-patches/features/0121-Vanilla-portal-handle.patch new file mode 100644 index 00000000..76da4617 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0121-Vanilla-portal-handle.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: violetc <58360096+s-yh-china@users.noreply.github.com> +Date: Thu, 15 May 2025 12:17:30 +0800 +Subject: [PATCH] Vanilla portal handle + + +diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java +index d768b1de1bc75ab73198379b1099cc09f58d1ca4..0ec5603097a984713bc3ae7a03a7535e552cf851 100644 +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -807,6 +807,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + + // CraftBukkit start + public void postTick() { ++ if (org.leavesmc.leaves.LeavesConfig.fix.vanillaPortalHandle) return; // Leaves - vanilla + // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle + if (!(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities + this.handlePortal(); +@@ -827,7 +828,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + this.boardingCooldown--; + } + +- if (this instanceof ServerPlayer) this.handlePortal(); // CraftBukkit - Moved up to postTick ++ if (org.leavesmc.leaves.LeavesConfig.fix.vanillaPortalHandle || this instanceof ServerPlayer) this.handlePortal(); // CraftBukkit - Moved up to postTick // Leaves - vanilla + if (this.canSpawnSprintParticle()) { + this.spawnSprintParticle(); + } +diff --git a/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 99617c08cbd989092ba357d8df928786fd04c89a..619f87b4ce69629b230229f33487fc653f6a39a7 100644 +--- a/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -294,7 +294,7 @@ public abstract class AbstractMinecart extends VehicleEntity { + } + + this.checkBelowWorld(); +- // this.handlePortal(); // CraftBukkit - handled in postTick ++ if (org.leavesmc.leaves.LeavesConfig.fix.vanillaPortalHandle) this.handlePortal(); // CraftBukkit - handled in postTick // Leaves - vanilla + this.behavior.tick(); + // CraftBukkit start + org.bukkit.World bworld = this.level().getWorld(); diff --git a/leaves-server/minecraft-patches/features/0122-Fix-chunk-reload-detector.patch b/leaves-server/minecraft-patches/features/0122-Fix-chunk-reload-detector.patch new file mode 100644 index 00000000..713f4f29 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0122-Fix-chunk-reload-detector.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Fortern +Date: Sat, 17 May 2025 03:01:48 +0000 +Subject: [PATCH] Fix chunk reload detector + + +diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java +index 7681195587d361acf524d09ad3958e628aad73b6..edf9c01fd64d269a5d78d805db91177095edffc7 100644 +--- a/net/minecraft/server/level/ServerEntity.java ++++ b/net/minecraft/server/level/ServerEntity.java +@@ -396,7 +396,7 @@ public class ServerEntity { + if (!list.isEmpty()) { + consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list, true)); // Paper - data sanitization + } +- ((LivingEntity) this.entity).detectEquipmentUpdates(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending ++ if (this.entity.totalEntityAge == 0) ((LivingEntity) this.entity).detectEquipmentUpdates(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending // Leaves - fix chunk reload detector (#492) + } + + if (!this.entity.getPassengers().isEmpty()) { diff --git a/leaves-server/minecraft-patches/features/0123-Do-not-reset-placed-block-on-exception.patch b/leaves-server/minecraft-patches/features/0123-Do-not-reset-placed-block-on-exception.patch new file mode 100644 index 00000000..6610df3b --- /dev/null +++ b/leaves-server/minecraft-patches/features/0123-Do-not-reset-placed-block-on-exception.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MC_XiaoHei +Date: Sat, 17 May 2025 11:38:56 +0000 +Subject: [PATCH] Do not reset placed block on exception + + +diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java +index 5cbd5d04de525c33715bc45826bd2ed446355505..c320cd4b7d994b3a0d23bec1713a8bf910f4ef95 100644 +--- a/net/minecraft/world/item/BlockItem.java ++++ b/net/minecraft/world/item/BlockItem.java +@@ -92,20 +92,22 @@ public class BlockItem extends Item { + BlockState blockState = level.getBlockState(clickedPos); + if (blockState.is(placementState.getBlock())) { + blockState = this.updateBlockStateFromTag(clickedPos, level, itemInHand, blockState); ++ // Leaves start - we do not need this + // Paper start - Reset placed block on exception +- try { ++ // try { + this.updateCustomBlockEntityTag(clickedPos, level, player, itemInHand, blockState); + updateBlockEntityComponents(level, clickedPos, itemInHand); +- } catch (Exception ex) { +- ((org.bukkit.craftbukkit.block.CraftBlockState) oldBukkitState).revertPlace(); +- if (player instanceof ServerPlayer serverPlayer) { +- org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), ex); +- serverPlayer.getBukkitEntity().kickPlayer("Packet processing error"); +- return InteractionResult.FAIL; +- } +- throw ex; // Rethrow exception if not placed by a player +- } ++ // } catch (Exception ex) { ++ // ((org.bukkit.craftbukkit.block.CraftBlockState) oldBukkitState).revertPlace(); ++ // if (player instanceof ServerPlayer serverPlayer) { ++ // org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), ex); ++ // serverPlayer.getBukkitEntity().kickPlayer("Packet processing error"); ++ // return InteractionResult.FAIL; ++ // } ++ // throw ex; // Rethrow exception if not placed by a player ++ // } + // Paper end - Reset placed block on exception ++ // Leaves end - we dot not need this + blockState.getBlock().setPlacedBy(level, clickedPos, blockState, player, itemInHand); + // CraftBukkit start + if (bukkitState != null) { diff --git a/leaves-server/minecraft-patches/features/0124-Do-not-prevent-block-entity-and-entity-crash-at-Leve.patch b/leaves-server/minecraft-patches/features/0124-Do-not-prevent-block-entity-and-entity-crash-at-Leve.patch new file mode 100644 index 00000000..4d1c59f2 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0124-Do-not-prevent-block-entity-and-entity-crash-at-Leve.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MC_XiaoHei +Date: Sun, 18 May 2025 03:21:56 +0000 +Subject: [PATCH] Do not prevent block entity and entity crash at LevelChunk + + +diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java +index d1b25a1e698253e1dfaf203536e4f10d8705be0f..bea00fb701cbd11aa73188f8e3aa9a5163f2f157 100644 +--- a/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/net/minecraft/world/level/chunk/LevelChunk.java +@@ -945,12 +945,14 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p + + profilerFiller.pop(); + } catch (Throwable var5) { ++ // Leaves start - do not prevent here + // Paper start - Prevent block entity and entity crashes +- final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ()); +- net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5); +- net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, var5))); // Paper - ServerExceptionEvent +- LevelChunk.this.removeBlockEntity(this.getPos()); ++ // final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ()); ++ // net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5); ++ // net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, var5))); // Paper - ServerExceptionEvent ++ // LevelChunk.this.removeBlockEntity(this.getPos()); + // Paper end - Prevent block entity and entity crashes ++ // Leaves end - do not prevent here + } + } + } diff --git a/leaves-server/minecraft-patches/features/0125-Tripwire-behavior-modifier.patch b/leaves-server/minecraft-patches/features/0125-Tripwire-behavior-modifier.patch new file mode 100644 index 00000000..089308fc --- /dev/null +++ b/leaves-server/minecraft-patches/features/0125-Tripwire-behavior-modifier.patch @@ -0,0 +1,86 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Helvetica Volubi +Date: Sat, 17 May 2025 21:03:00 +0800 +Subject: [PATCH] Tripwire behavior modifier + + +diff --git a/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java b/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java +index dfe8b815987a0ee385846616e4845428a81f2782..1c13fc84a50afdafcb68a068a2d19404f90fecc5 100644 +--- a/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java ++++ b/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java +@@ -28,14 +28,40 @@ public class EndPlatformFeature extends Feature { + // CraftBukkit end + BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); + ++ // Leaves start - tripwire behavior modifier ++ java.util.List blockList1 = new java.util.ArrayList<>(); ++ java.util.List blockList2 = new java.util.ArrayList<>(); ++ boolean flag21 = org.leavesmc.leaves.LeavesConfig.modify.oldMC.tripwire.tripwireBehavior == org.leavesmc.leaves.LeavesConfig.ModifyConfig.MinecraftOLDConfig.TripwireConfig.TripwireBehavior.VANILLA_21; + for (int i = -2; i <= 2; i++) { + for (int i1 = -2; i1 <= 2; i1++) { + for (int i2 = -1; i2 < 3; i2++) { + BlockPos blockPos = mutableBlockPos.set(pos).move(i1, i2, i); + Block block = i2 == -1 ? Blocks.OBSIDIAN : Blocks.AIR; +- if (!blockList.getBlockState(blockPos).is(block)) { // CraftBukkit ++ if (!blockList.getBlockState(blockPos).is(block)) { + if (dropBlocks) { +- blockList.destroyBlock(blockPos, true, null); // CraftBukkit ++ boolean flag = false; ++ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.tripwire.stringTripwireHookDuplicate) { ++ switch (org.leavesmc.leaves.LeavesConfig.modify.oldMC.tripwire.tripwireBehavior) { ++ case org.leavesmc.leaves.LeavesConfig.ModifyConfig.MinecraftOLDConfig.TripwireConfig.TripwireBehavior.VANILLA_20 -> { ++ flag = true; ++ } ++ case org.leavesmc.leaves.LeavesConfig.ModifyConfig.MinecraftOLDConfig.TripwireConfig.TripwireBehavior.MIXED -> { ++ net.minecraft.world.level.block.state.BlockState state = level.getBlockState(blockPos); ++ if (state.is(Blocks.TRIPWIRE)) { ++ if (state.getValue(net.minecraft.world.level.block.TripWireBlock.DISARMED)) { ++ flag = true; ++ blockList2.add(blockPos.immutable()); ++ } ++ if (!flag) { ++ flag = checkString(blockList2, blockPos); ++ } ++ } ++ } ++ default -> {} // Leaves - 1.21 & default Logic - default empty ++ } ++ } ++ if (flag) blockList1.add(blockPos.immutable()); ++ else blockList.destroyBlock(blockPos, true, null); + } + + blockList.setBlock(blockPos, block.defaultBlockState(), 3); // CraftBukkit +@@ -53,11 +79,29 @@ public class EndPlatformFeature extends Feature { + if (portalEvent.isCancelled()) return; + } + +- if (dropBlocks) { +- blockList.placeBlocks(state -> level.destroyBlock(state.getPosition(), true, null)); ++ if (flag21 || !org.leavesmc.leaves.LeavesConfig.modify.oldMC.tripwire.stringTripwireHookDuplicate) { ++ if (dropBlocks) { ++ blockList.placeBlocks(state -> level.destroyBlock(state.getPosition(), !blockList1.contains(state.getPosition()), null)); ++ } else { ++ blockList.placeBlocks(); ++ } + } else { +- blockList.placeBlocks(); ++ if (dropBlocks) { ++ blockList.getSnapshotBlocks().forEach((state) -> { ++ level.destroyBlock(state.getPosition(), !blockList1.contains(state.getPosition()), null); ++ state.update(); ++ }); ++ } + } + // CraftBukkit end + } ++ ++ private static boolean checkString(java.util.List blockList, BlockPos blockPos) { ++ for (BlockPos pos : blockList) { ++ if (pos.getY() != blockPos.getY()) continue; ++ if (pos.getX() == blockPos.getX() || pos.getZ() == blockPos.getZ()) return true; ++ } ++ return false; ++ } ++ // Leaves end - tripwire behavior modifier + } diff --git a/leaves-server/minecraft-patches/features/0126-Old-nether-portal-collision.patch b/leaves-server/minecraft-patches/features/0126-Old-nether-portal-collision.patch new file mode 100644 index 00000000..72e8d499 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0126-Old-nether-portal-collision.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Helvetica Volubi +Date: Sun, 18 May 2025 23:48:59 +0800 +Subject: [PATCH] Old nether portal collision + +It will be removed in 1.21.6 mojang revert it again. + +diff --git a/net/minecraft/world/level/block/NetherPortalBlock.java b/net/minecraft/world/level/block/NetherPortalBlock.java +index 171b383efabbbe849aff28832c47076f85a46307..173e97c27e9373a41d33cda6a877b17a38f516a1 100644 +--- a/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -65,7 +65,7 @@ public class NetherPortalBlock extends Block implements Portal { + + @Override + protected VoxelShape getEntityInsideCollisionShape(BlockState state, BlockGetter level, BlockPos pos, Entity entity) { +- return state.getShape(level, pos); ++ return org.leavesmc.leaves.LeavesConfig.modify.oldMC.oldNetherPortalCollision ? Shapes.block() : state.getShape(level, pos); // Leaves - Old nether portal collision + } + + @Override diff --git a/leaves-server/minecraft-patches/features/0127-Spawn-invulnerable-time.patch b/leaves-server/minecraft-patches/features/0127-Spawn-invulnerable-time.patch new file mode 100644 index 00000000..2cc8560e --- /dev/null +++ b/leaves-server/minecraft-patches/features/0127-Spawn-invulnerable-time.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Helvetica Volubi +Date: Mon, 19 May 2025 00:06:03 +0800 +Subject: [PATCH] Spawn invulnerable time + + +diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java +index d4984c919a88fa930dfec823cd9b471fa47f3565..6f845730bb0a9dcd1b26e68171e80edc669b6430 100644 +--- a/net/minecraft/server/level/ServerPlayer.java ++++ b/net/minecraft/server/level/ServerPlayer.java +@@ -221,6 +221,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + private int lastSentFood = -99999999; + private boolean lastFoodSaturationZero = true; + public int lastSentExp = -99999999; ++ private int spawnInvulnerableTime = 60; // Leaves - spawn invulnerable time + private ChatVisiblity chatVisibility = ChatVisiblity.FULL; + public ParticleStatus particleStatus = ParticleStatus.ALL; + private boolean canChatColor = true; +@@ -751,6 +752,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + this.resetOperationCountPerTick(); // Leaves - player operation limiter + this.gameMode.tick(); + this.wardenSpawnTracker.tick(); ++ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.spawnInvulnerableTime && this.invulnerableTime > 0) --this.spawnInvulnerableTime; // Leaves - spawn invulnerable time + if (this.invulnerableTime > 0) { + this.invulnerableTime--; + } +@@ -1185,6 +1187,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + if (this.isInvulnerableTo(level, damageSource)) { + return false; + } else { ++ // Leaves start - spawn invulnerable time ++ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.spawnInvulnerableTime) { ++ if (this.spawnInvulnerableTime > 0 && !damageSource.is(net.minecraft.tags.DamageTypeTags.BYPASSES_INVULNERABILITY)) { ++ return false; ++ } ++ } ++ // Leaves end - spawn invulnerable time + Entity entity = damageSource.getEntity(); + if (!( // Paper - split the if statement. If below statement is false, hurtServer would not have been evaluated. Return false. + !(entity instanceof Player player && !this.canHarmPlayer(player)) diff --git a/leaves-server/minecraft-patches/features/0128-Old-zombie-reinforcement.patch b/leaves-server/minecraft-patches/features/0128-Old-zombie-reinforcement.patch new file mode 100644 index 00000000..4a82f5f7 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0128-Old-zombie-reinforcement.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Helvetica Volubi +Date: Mon, 19 May 2025 00:42:17 +0800 +Subject: [PATCH] Old zombie reinforcement + + +diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java +index 39b65970a48568c95ff482b9636e7391f300ffa8..50417ae5883374113cf820c064570b6aeda4fbb8 100644 +--- a/net/minecraft/world/entity/monster/Zombie.java ++++ b/net/minecraft/world/entity/monster/Zombie.java +@@ -342,7 +342,7 @@ public class Zombie extends Monster { + int floor = Mth.floor(this.getX()); + int floor1 = Mth.floor(this.getY()); + int floor2 = Mth.floor(this.getZ()); +- EntityType type = this.getType(); ++ EntityType type = org.leavesmc.leaves.LeavesConfig.modify.oldMC.oldZombieReinforcement ? EntityType.ZOMBIE : this.getType(); // Leaves end - old zombie reinforcement + Zombie zombie = type.create(level, EntitySpawnReason.REINFORCEMENT); + if (zombie == null) { + return true; diff --git a/leaves-server/minecraft-patches/features/0129-Sound-update-suppression.patch b/leaves-server/minecraft-patches/features/0129-Sound-update-suppression.patch new file mode 100644 index 00000000..3f407e7d --- /dev/null +++ b/leaves-server/minecraft-patches/features/0129-Sound-update-suppression.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MC_XiaoHei +Date: Tue, 20 May 2025 12:08:40 +0000 +Subject: [PATCH] Sound update suppression + + +diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java +index fa9cb4c40a41eea7fd63a4513d0b0f39067de9ba..331276f4464d78dc86f35fe7d9c42864d7e73a6c 100644 +--- a/net/minecraft/world/level/block/SculkSensorBlock.java ++++ b/net/minecraft/world/level/block/SculkSensorBlock.java +@@ -97,7 +97,7 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg + @Override + public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { + if (!level.isClientSide() +- && canActivate(state) ++ && canActivate(state, pos) // Leaves - Sound update suppression + && entity.getType() != EntityType.WARDEN + && level.getBlockEntity(pos) instanceof SculkSensorBlockEntity sculkSensorBlockEntity + && level instanceof ServerLevel serverLevel +@@ -214,6 +214,13 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg + return state.getValue(PHASE); + } + ++ // Leaves start - Sound update suppression ++ public static boolean canActivate(BlockState state, BlockPos pos) { ++ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.soundUpdateSuppression && !(state.getBlock() instanceof SculkSensorBlock)) throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, state.getBlock()); ++ return canActivate(state); ++ } ++ // Leaves end - Sound update suppression ++ + public static boolean canActivate(BlockState state) { + return state.getBlock() instanceof SculkSensorBlock && getPhase(state) == SculkSensorPhase.INACTIVE; // Paper - Check for a valid type + } +diff --git a/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java b/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java +index 26d2205fe7c1322f52e7d162e1be9dc23349f3b6..9cbba9cdeddd0a722554aca0a1fb41c2def4a46b 100644 +--- a/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java +@@ -118,7 +118,7 @@ public class SculkSensorBlockEntity extends BlockEntity implements GameEventList + public boolean canReceiveVibration(ServerLevel level, BlockPos pos, Holder gameEvent, @Nullable GameEvent.Context context) { + return (!pos.equals(this.blockPos) || !gameEvent.is(GameEvent.BLOCK_DESTROY) && !gameEvent.is(GameEvent.BLOCK_PLACE)) + && VibrationSystem.getGameEventFrequency(gameEvent) != 0 +- && SculkSensorBlock.canActivate(SculkSensorBlockEntity.this.getBlockState()); ++ && SculkSensorBlock.canActivate(SculkSensorBlockEntity.this.getBlockState(), pos); // Leaves - Sound update suppression + } + + @Override +@@ -126,7 +126,7 @@ public class SculkSensorBlockEntity extends BlockEntity implements GameEventList + ServerLevel level, BlockPos pos, Holder gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance + ) { + BlockState blockState = SculkSensorBlockEntity.this.getBlockState(); +- if (SculkSensorBlock.canActivate(blockState)) { ++ if (SculkSensorBlock.canActivate(blockState, pos)) { // Leaves - Sound update suppression + int gameEventFrequency = VibrationSystem.getGameEventFrequency(gameEvent); + SculkSensorBlockEntity.this.setLastVibrationFrequency(gameEventFrequency); + int redstoneStrengthForDistance = VibrationSystem.getRedstoneStrengthForDistance(distance, this.getListenerRadius()); diff --git a/leaves-server/minecraft-patches/features/0130-Old-zombie-piglin-drop-behavior.patch b/leaves-server/minecraft-patches/features/0130-Old-zombie-piglin-drop-behavior.patch new file mode 100644 index 00000000..b9eefe24 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0130-Old-zombie-piglin-drop-behavior.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> +Date: Fri, 23 May 2025 08:05:45 +0800 +Subject: [PATCH] Old zombie piglin drop behavior + + +diff --git a/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/net/minecraft/world/entity/monster/ZombifiedPiglin.java +index 05de183ce7b0be9b41f005b2ca36807a109fc634..6c3895f96ef0c3bd69dc5cd0fae56c83116537a3 100644 +--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -159,6 +159,10 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + this.ticksUntilNextAlert = ALERT_INTERVAL.sample(this.random); + } + ++ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.oldZombiePiglinDrop && livingEntity instanceof Player player) { ++ this.setLastHurtByPlayer(player, super.tickCount); ++ } ++ + return super.setTarget(livingEntity, reason); // CraftBukkit + } + diff --git a/leaves-server/minecraft-patches/features/0131-Fast-exp-orb-absorb.patch b/leaves-server/minecraft-patches/features/0131-Fast-exp-orb-absorb.patch new file mode 100644 index 00000000..58f5e9bd --- /dev/null +++ b/leaves-server/minecraft-patches/features/0131-Fast-exp-orb-absorb.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> +Date: Sun, 1 Jun 2025 13:13:23 +0800 +Subject: [PATCH] Fast exp orb absorb + + +diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java +index c97a0e500e889b406cb2d679a3870715775f5393..9ebc2fdf9de21bb4533e4184ec9fb92b698902bd 100644 +--- a/net/minecraft/world/entity/ExperienceOrb.java ++++ b/net/minecraft/world/entity/ExperienceOrb.java +@@ -328,6 +328,20 @@ public class ExperienceOrb extends Entity { + public void playerTouch(Player entity) { + if (entity instanceof ServerPlayer serverPlayer) { + if (entity.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent ++ if (org.leavesmc.leaves.LeavesConfig.modify.fastAbsorbPredicate.test(serverPlayer)) { ++ entity.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(entity, 0, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; ++ while (this.count > 0) { ++ entity.take(this, 1); ++ int i = this.repairPlayerItems(serverPlayer, this.getValue()); ++ if (i > 0) { ++ entity.giveExperiencePoints(org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerExpChangeEvent(entity, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object ++ } ++ this.count--; ++ } ++ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause ++ return; ++ } ++ + entity.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(entity, 2, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; + entity.take(this, 1); + int i = this.repairPlayerItems(serverPlayer, this.getValue()); diff --git a/leaves-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch b/leaves-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch deleted file mode 100644 index f7bcdc23..00000000 --- a/leaves-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- a/net/minecraft/world/entity/Entity.java -+++ b/net/minecraft/world/entity/Entity.java -@@ -347,6 +_,7 @@ - public void inactiveTick() { - } - // Paper end - EAR 2 -+ private CompoundTag leavesData = new CompoundTag(); // Leaves - Leaves ex data - - public void setOrigin(@javax.annotation.Nonnull org.bukkit.Location location) { - this.origin = location.toVector(); -@@ -2522,6 +_,7 @@ - compound.putBoolean("Paper.FreezeLock", true); - } - // Paper end -+ compound.put("Leaves.Data", leavesData); // Leaves - leaves ex data - return compound; - } catch (Throwable var9) { - CrashReport crashReport = CrashReport.forThrowable(var9, "Saving entity NBT"); -@@ -2671,6 +_,11 @@ - freezeLocked = compound.getBoolean("Paper.FreezeLock"); - } - // Paper end -+ // Leaves start - leaves ex data -+ if (compound.contains("Leaves.Data")) { -+ leavesData = compound.getCompound("Leaves.Data"); -+ } -+ // Leaves end - leaves ex data - } catch (Throwable var17) { - CrashReport crashReport = CrashReport.forThrowable(var17, "Loading entity NBT"); - CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded"); -@@ -5078,4 +_,9 @@ - return ((ServerLevel) this.level).isPositionEntityTicking(this.blockPosition()); - } - // Paper end - Expose entity id counter -+ // Leaves start - leaves ex data -+ public CompoundTag getLeavesData() { -+ return leavesData; -+ } -+ // Leaves end - leaves ex data - } diff --git a/leaves-server/paper-patches/features/0001-Build-changes.patch b/leaves-server/paper-patches/features/0001-Build-changes.patch index af0f07a3..445a4eed 100644 --- a/leaves-server/paper-patches/features/0001-Build-changes.patch +++ b/leaves-server/paper-patches/features/0001-Build-changes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Build changes diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 8f62879582195d8ae4f64bd23f752fa133b1c973..783fe9b3b2ca3ef6de91086a33264368164530eb 100644 +index 6abc57669e87f7f98f3b76af3c0e50825fea6eb1..c7ee6d3a158ca7d3de54bc12622affbf01584e7b 100644 --- a/src/main/java/com/destroystokyo/paper/Metrics.java +++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -592,7 +592,8 @@ public class Metrics { +@@ -593,7 +593,8 @@ public class Metrics { boolean logFailedRequests = config.getBoolean("logFailedRequests", false); // Only start Metrics, if it's enabled in the config if (config.getBoolean("enabled", true)) { @@ -18,7 +18,7 @@ index 8f62879582195d8ae4f64bd23f752fa133b1c973..783fe9b3b2ca3ef6de91086a33264368 metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { String minecraftVersion = Bukkit.getVersion(); -@@ -600,17 +601,21 @@ public class Metrics { +@@ -601,17 +602,21 @@ public class Metrics { return minecraftVersion; })); @@ -49,7 +49,7 @@ index 8f62879582195d8ae4f64bd23f752fa133b1c973..783fe9b3b2ca3ef6de91086a33264368 metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { Map> map = new HashMap<>(); -@@ -642,41 +647,8 @@ public class Metrics { +@@ -643,41 +648,8 @@ public class Metrics { return map; })); @@ -106,18 +106,31 @@ index 790bad0494454ca12ee152e3de6da3da634d9b20..c060857cb0551fff8f5033553b887f3a private static final String BUILD_DEV = "DEV"; diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index bf5343b0847e9f57ffbc7f33714ae6ca62f14332..c07481501358cd55c610cebd4891c804003795fa 100644 +index a11fc64b4933a5abce0182ba46f1da22043eb0d8..c311381d7d6841153f9f29f9a2e6718811bdf1c7 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -267,7 +267,7 @@ public class Main { +@@ -232,7 +232,7 @@ public class Main { if (buildDate.before(deadline.getTime())) { // Paper start - This is some stupid bullshit System.err.println("*** Warning, you've not updated in a while! ***"); -- System.err.println("*** Please download a new build from https://papermc.io/downloads/paper ***"); // Paper -+ System.err.println("*** Please download a new build from https://leavesmc.org/downloads/leaves ***"); //Paper // Leaves - //System.err.println("*** Server will start in 20 seconds ***"); - //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); +- System.err.println("*** Please download a new build from https://papermc.io/downloads/paper ***"); ++ System.err.println("*** Please download a new build from https://leavesmc.org/downloads/leaves ***"); // Leaves // Paper end + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index a287ad5cce532229f2a514956d34a9358175bc45..27f1a050882c7b00649ab2bea2e4d00c575080eb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -485,7 +485,7 @@ public final class CraftMagicNumbers implements UnsafeValues { + + @Override + public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { +- return new com.destroystokyo.paper.PaperVersionFetcher(); ++ return new org.leavesmc.leaves.util.LeavesVersionFetcher(); // Leaves + } + + @Override diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java index 774556a62eb240da42e84db4502e2ed43495be17..fdef98a7796d84c7b0ee61241859e10cc514534c 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java @@ -132,12 +145,12 @@ index 774556a62eb240da42e84db4502e2ed43495be17..fdef98a7796d84c7b0ee61241859e10c if (stream != null) { diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index dced8899be0bb8d562093dc3a7673ed8185b85a6..a4894aea1618cf1b18243bab3faffc5f286e346b 100644 +index c77748061f1c8bb2b0dc8dbd80f608d431752015..7dac2652e3d4964682982e50f533bd4b38ee5b4b 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -77,14 +77,14 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre +@@ -75,14 +75,14 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre + this.lastEarlyWarning = currentTime; if (isLongTimeout) { - // Paper end logger.log(Level.SEVERE, "------------------------------"); - logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug."); // Paper + logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Leaves bug."); // Paper // Leaves @@ -153,7 +166,7 @@ index dced8899be0bb8d562093dc3a7673ed8185b85a6..a4894aea1618cf1b18243bab3faffc5f if (net.minecraft.world.level.Level.lastPhysicsProblem != null) { logger.log(Level.SEVERE, "------------------------------"); -@@ -104,12 +104,12 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre +@@ -102,12 +102,12 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre } // Paper end } else { @@ -166,9 +179,9 @@ index dced8899be0bb8d562093dc3a7673ed8185b85a6..a4894aea1618cf1b18243bab3faffc5f - logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):"); // Paper + logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Leaves!):"); // Paper // Leaevs FeatureHooks.dumpAllChunkLoadInfo(MinecraftServer.getServer(), isLongTimeout); // Paper - log detailed tick information - WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE), logger); + WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.threadId(), Integer.MAX_VALUE), logger); logger.log(Level.SEVERE, "------------------------------"); -@@ -122,7 +122,7 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre +@@ -120,7 +120,7 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre WatchdogThread.dumpThread(thread, logger); } } else { diff --git a/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch b/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch index 53e55f64..dd8e365d 100644 --- a/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch +++ b/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch @@ -18,10 +18,10 @@ index 62e2d5704c348955bc8284dc2d54c933b7bcdd06..7ef20f0138fad39a1d23edd7b26ddc88 public void executeAsync(final Runnable runnable) { MCUtil.scheduleAsyncTask(this.catching(runnable, "asynchronous")); diff --git a/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java b/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -index 1814cd072aaca3e72249f0509a9c3b3cb154eaba..11b394f479eb268b248fae8a72ea97886853d797 100644 +index 5c52b1563d20d7e977a5bb958c18b19dec5c365a..e227cb58989c32a2e1dff1b731efe771db33b26e 100644 --- a/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java +++ b/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -@@ -105,6 +105,14 @@ public class BukkitCommandNode extends LiteralCommandNode { +@@ -106,6 +106,14 @@ public class BukkitCommandNode extends LiteralCommandNode { List results = null; Location pos = context.getSource().getLocation(); try { @@ -35,12 +35,12 @@ index 1814cd072aaca3e72249f0509a9c3b3cb154eaba..11b394f479eb268b248fae8a72ea9788 + // Leaves end - custom suggestion results = this.command.tabComplete(sender, this.literal, args, pos.clone()); } catch (CommandException ex) { - sender.sendMessage(ChatColor.RED + "An internal error occurred while attempting to tab-complete this command"); + sender.sendMessage(Component.text("An internal error occurred while attempting to tab-complete this command", NamedTextColor.RED)); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 59eddee7e75e1de332346ffe73fb88eb1ae14db6..faa2d73c8a9664110d954b833da0dca9ca21dbef 100644 +index 1da86b25e3b89c79d4f3920c8d2ef10ee2757f65..8dc17473e580df2ba9273e612868ad325a952bee 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1116,6 +1116,7 @@ public final class CraftServer implements Server { +@@ -1101,6 +1101,7 @@ public final class CraftServer implements Server { playerMetadata.removeAll(plugin); } // Paper end @@ -49,13 +49,13 @@ index 59eddee7e75e1de332346ffe73fb88eb1ae14db6..faa2d73c8a9664110d954b833da0dca9 org.spigotmc.SpigotConfig.registerCommands(); // Spigot io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index c07481501358cd55c610cebd4891c804003795fa..b6a60aac952c1275da203215119d65934602c113 100644 +index c311381d7d6841153f9f29f9a2e6718811bdf1c7..d855a6543433ce520fb26e536f32c22b847ea0b6 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -183,6 +183,14 @@ public class Main { +@@ -170,6 +170,14 @@ public class Main { + .ofType(String.class) .defaultsTo("Unknown Server") .describedAs("Name"); - // Paper end + + // Leaves start - Server Config + acceptsAll(asList("leaves", "leaves-settings"), "File for leaves settings") diff --git a/leaves-server/paper-patches/features/0004-Leaves-Protocol-Core.patch b/leaves-server/paper-patches/features/0004-Leaves-Protocol-Core.patch index 2fdcaa53..dd0ca8db 100644 --- a/leaves-server/paper-patches/features/0004-Leaves-Protocol-Core.patch +++ b/leaves-server/paper-patches/features/0004-Leaves-Protocol-Core.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Leaves Protocol Core diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c6fbb091c513fb9e5527ac9cb08af607f14468b4..16fdeed9bb0d088cd811c83c93517c0e51a7e9c3 100644 +index 8dc17473e580df2ba9273e612868ad325a952bee..4ffe2623badcaca80c192b3ea79488f274c125e9 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -493,6 +493,7 @@ public final class CraftServer implements Server { +@@ -497,6 +497,7 @@ public final class CraftServer implements Server { this.potionBrewer = new io.papermc.paper.potion.PaperPotionBrewer(console); // Paper - custom potion mixes datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark @@ -16,7 +16,7 @@ index c6fbb091c513fb9e5527ac9cb08af607f14468b4..16fdeed9bb0d088cd811c83c93517c0e } public boolean getCommandBlockOverride(String command) { -@@ -1123,6 +1124,7 @@ public final class CraftServer implements Server { +@@ -1108,6 +1109,7 @@ public final class CraftServer implements Server { this.spark.registerCommandBeforePlugins(this); // Paper - spark this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); diff --git a/leaves-server/paper-patches/features/0005-Leaves-Fakeplayer.patch b/leaves-server/paper-patches/features/0005-Leaves-Fakeplayer.patch index bb7d9b27..58c69748 100644 --- a/leaves-server/paper-patches/features/0005-Leaves-Fakeplayer.patch +++ b/leaves-server/paper-patches/features/0005-Leaves-Fakeplayer.patch @@ -22,10 +22,10 @@ index a589689e3a9de1fffef62e0e3dcd79bb2e848c5b..a0a6cde96322df8e455b26b32b1c593f RegisteredListener[] listeners = handlers.getRegisteredListeners(); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java -index adc6741e0e017660fbd39a62b69be1e67e0e143f..9bc40b07b8eebded4f748fd053b45571df6286a5 100644 +index 1775eb659ef1a10868cfc6721aedd5096fe0a17c..1eb1a3c9736bf97fbdcd1e17a86f49c030a6cdf3 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java -@@ -434,6 +434,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor { +@@ -424,6 +424,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor { @SuppressWarnings("unchecked") public T addEntity(T entity) { Preconditions.checkArgument(!entity.isInWorld(), "Entity has already been added to a world"); @@ -34,18 +34,18 @@ index adc6741e0e017660fbd39a62b69be1e67e0e143f..9bc40b07b8eebded4f748fd053b45571 if (nmsEntity.level() != this.getHandle().getLevel()) { nmsEntity = nmsEntity.teleport(new TeleportTransition(this.getHandle().getLevel(), nmsEntity, TeleportTransition.DO_NOTHING)); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c06b12e9d5535c8018c5b7f305946758dd9afd99..7e93baa65715383092fd43132b6f4da9eddcf39c 100644 +index 4ffe2623badcaca80c192b3ea79488f274c125e9..25c11fbe0b4e0cdc0aa63982d185935e2016ba79 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -315,6 +315,7 @@ public final class CraftServer implements Server { - private final io.papermc.paper.logging.SysoutCatcher sysoutCatcher = new io.papermc.paper.logging.SysoutCatcher(); // Paper - private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer; // Paper - Custom Potion Mixes - public final io.papermc.paper.SparksFly spark; // Paper - spark +@@ -316,6 +316,7 @@ public final class CraftServer implements Server { + private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer; + public final io.papermc.paper.SparksFly spark; + private final ServerConfiguration serverConfig = new PaperServerConfiguration(); + private final org.leavesmc.leaves.entity.CraftBotManager botManager; // Leaves // Paper start - Folia region threading API private final io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler(); -@@ -494,6 +495,7 @@ public final class CraftServer implements Server { +@@ -498,6 +499,7 @@ public final class CraftServer implements Server { datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark org.leavesmc.leaves.protocol.core.LeavesProtocolManager.init(); // Leaves - protocol @@ -53,19 +53,19 @@ index c06b12e9d5535c8018c5b7f305946758dd9afd99..7e93baa65715383092fd43132b6f4da9 } public boolean getCommandBlockOverride(String command) { -@@ -1500,7 +1502,7 @@ public final class CraftServer implements Server { +@@ -1469,7 +1471,7 @@ public final class CraftServer implements Server { return false; } -- if (handle.players().size() > 0) { -+ if (handle.realPlayers().size() > 0) { // Leaves - skip +- if (!handle.players().isEmpty()) { ++ if (!handle.realPlayers().isEmpty()) { // Leaves - skip return false; } -@@ -3294,4 +3296,11 @@ public final class CraftServer implements Server { +@@ -3209,4 +3211,11 @@ public final class CraftServer implements Server { + public void allowPausing(final Plugin plugin, final boolean value) { this.console.addPluginAllowingSleep(plugin.getName(), value); } - // Paper end - API to check if the server is sleeping + + // Leaves start - Bot API + @Override @@ -75,10 +75,10 @@ index c06b12e9d5535c8018c5b7f305946758dd9afd99..7e93baa65715383092fd43132b6f4da9 + // Leaves end - Bot API } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 1439d282167dc8a2e66f4896849153b810112988..f357e705290eda063ab659e05fea53fd8fe98a95 100644 +index aae378697b2f2e388d2a5dfaca24c9197b8abf3e..6773681bfaf0edb03cc17bcdfa43b98c8b7c9c20 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -237,7 +237,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -238,7 +238,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getPlayerCount() { @@ -87,7 +87,7 @@ index 1439d282167dc8a2e66f4896849153b810112988..f357e705290eda063ab659e05fea53fd } @Override -@@ -1241,9 +1241,9 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1242,9 +1242,9 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public List getPlayers() { @@ -99,7 +99,7 @@ index 1439d282167dc8a2e66f4896849153b810112988..f357e705290eda063ab659e05fea53fd HumanEntity bukkitEntity = human.getBukkitEntity(); if ((bukkitEntity != null) && (bukkitEntity instanceof Player)) { -@@ -1920,7 +1920,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1926,7 +1926,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { public void playSound(final net.kyori.adventure.sound.Sound sound) { org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper final long seed = sound.seed().orElseGet(this.world.getRandom()::nextLong); @@ -108,7 +108,7 @@ index 1439d282167dc8a2e66f4896849153b810112988..f357e705290eda063ab659e05fea53fd player.connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, player.getX(), player.getY(), player.getZ(), seed, null)); } } -@@ -1948,7 +1948,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1954,7 +1954,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper final long seed = sound.seed().orElseGet(this.getHandle().getRandom()::nextLong); if (emitter == net.kyori.adventure.sound.Sound.Emitter.self()) { @@ -117,7 +117,7 @@ index 1439d282167dc8a2e66f4896849153b810112988..f357e705290eda063ab659e05fea53fd player.connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, player, seed, null)); } } else if (emitter instanceof CraftEntity craftEntity) { -@@ -2178,7 +2178,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2184,7 +2184,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { Preconditions.checkArgument(particle.getDataType().isInstance(data), "data (%s) should be %s", data.getClass(), particle.getDataType()); } this.getHandle().sendParticlesSource( @@ -127,10 +127,10 @@ index 1439d282167dc8a2e66f4896849153b810112988..f357e705290eda063ab659e05fea53fd CraftParticle.createParticleParam(particle, data), // Particle force, diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 1ee0ad266955e36b729ba31eb75aad9289acd8e4..2b441ba89c603903267db63c7515b0de2cbe09b1 100644 +index 3b41a37f852c3b494b158e447eade9b030f26556..656586dc3bda8aefc8b2e648e9f3d008cb2908fd 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -98,6 +98,8 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -108,6 +108,8 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return new CraftHumanEntity(server, (net.minecraft.world.entity.player.Player) entity); } @@ -140,10 +140,10 @@ index 1ee0ad266955e36b729ba31eb75aad9289acd8e4..2b441ba89c603903267db63c7515b0de if (entity instanceof EnderDragonPart complexPart) { if (complexPart.parentMob instanceof EnderDragon) { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 57c3f8531bf85b53af3a4aad6e9e369d5cff0ce3..8d85c78b2769be4269e8342138448edac631ce9f 100644 +index 9774c9c72a910ccd919b903d92f4068c06d199d7..03778c286144d8f04147f37aa59fb73fcc584833 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1025,7 +1025,11 @@ public class CraftEventFactory { +@@ -885,7 +885,11 @@ public class CraftEventFactory { event.setKeepInventory(keepInventory); event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel populateFields(victim, event); // Paper - make cancellable diff --git a/leaves-server/paper-patches/features/0006-No-chat-sign.patch b/leaves-server/paper-patches/features/0006-No-chat-sign.patch index 69406958..7efef224 100644 --- a/leaves-server/paper-patches/features/0006-No-chat-sign.patch +++ b/leaves-server/paper-patches/features/0006-No-chat-sign.patch @@ -5,7 +5,7 @@ Subject: [PATCH] No chat sign diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -index 14e412ebf75b0e06ab53a1c8f9dd1be6ad1e2680..73d239536b373e292ee2883edac0049541b59ba0 100644 +index f6266b3ca9c031ef9e96df23e0413c7db5211bd8..7516581e3ce033d676330390a37e0f9c08409a82 100644 --- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java @@ -317,7 +317,7 @@ public final class ChatProcessor { diff --git a/leaves-server/paper-patches/features/0007-MC-Technical-Survival-Mode.patch b/leaves-server/paper-patches/features/0007-MC-Technical-Survival-Mode.patch index a16af288..d327f801 100644 --- a/leaves-server/paper-patches/features/0007-MC-Technical-Survival-Mode.patch +++ b/leaves-server/paper-patches/features/0007-MC-Technical-Survival-Mode.patch @@ -6,10 +6,10 @@ Subject: [PATCH] MC Technical Survival Mode Will automatically overwrite some configuration after startup diff --git a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java -index e48fa405d92fab221fa8331b65c8f324e801d439..4697237ede3ec3960c57eec549b73b0f785f6377 100644 +index 266932720ae0af0f17df18ad1570b29631ed2c2a..d0cd9675d166de95904fcb1767089b9430e37934 100644 --- a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java +++ b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java -@@ -325,6 +325,7 @@ public class PaperConfigurations extends Configurations -Date: Thu, 20 Jul 2023 15:03:28 +0800 -Subject: [PATCH] Reduce array allocations - -This patch is Powered by Gale(https://github.com/GaleMC/Gale) - -diff --git a/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java b/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java -index ae60bd96b5284d54676d8e7e4dd5d170b526ec1e..0c474b1eb4dbef547890b7db5fcf9c13c86092a2 100644 ---- a/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java -+++ b/src/main/java/io/papermc/paper/command/subcommands/VersionCommand.java -@@ -7,6 +7,7 @@ import org.bukkit.command.CommandSender; - import org.checkerframework.checker.nullness.qual.NonNull; - import org.checkerframework.checker.nullness.qual.Nullable; - import org.checkerframework.framework.qual.DefaultQualifier; -+import org.leavesmc.leaves.util.ArrayConstants; - - @DefaultQualifier(NonNull.class) - public final class VersionCommand implements PaperSubcommand { -@@ -14,7 +15,7 @@ public final class VersionCommand implements PaperSubcommand { - public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { - final @Nullable Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version"); - if (ver != null) { -- ver.execute(sender, "paper", new String[0]); -+ ver.execute(sender, "paper", ArrayConstants.emptyStringArray); // Leaves - reduce array allocations - } - return true; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -index fdcc414f4fa246082ad0732133c870d915ae3084..556247696cde0d31cbb70907648d2970acf81153 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -@@ -165,7 +165,7 @@ public class CraftEntityEquipment implements EntityEquipment { - - @Override - public void clear() { -- for (net.minecraft.world.entity.EquipmentSlot slot : net.minecraft.world.entity.EquipmentSlot.values()) { -+ for (net.minecraft.world.entity.EquipmentSlot slot : net.minecraft.world.entity.EquipmentSlot.VALUES) { // Leaves - reduce array allocations - this.setEquipment(slot, null, false); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java b/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java -index b25dc23b81687dd4d4e70b3615ffb91f8c03c68b..8fdadf58054b2475f2023f76824af7bbe1303383 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java -@@ -6,6 +6,7 @@ import java.util.ArrayList; - import java.util.Collection; - import java.util.Iterator; - import java.util.NoSuchElementException; -+import org.leavesmc.leaves.util.ArrayConstants; - - public final class WeakCollection implements Collection { - static final Object NO_VALUE = new Object(); -@@ -164,7 +165,7 @@ public final class WeakCollection implements Collection { - - @Override - public Object[] toArray() { -- return this.toArray(new Object[0]); -+ return this.toArray(ArrayConstants.emptyObjectArray); // Leaves - reduce array allocations - } - - @Override diff --git a/leaves-server/paper-patches/features/0012-Replay-Mod-API.patch b/leaves-server/paper-patches/features/0011-Replay-Mod-API.patch similarity index 82% rename from leaves-server/paper-patches/features/0012-Replay-Mod-API.patch rename to leaves-server/paper-patches/features/0011-Replay-Mod-API.patch index ecf56bba..dad99d9f 100644 --- a/leaves-server/paper-patches/features/0012-Replay-Mod-API.patch +++ b/leaves-server/paper-patches/features/0011-Replay-Mod-API.patch @@ -3,7 +3,6 @@ From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Tue, 4 Feb 2025 19:45:21 +0800 Subject: [PATCH] Replay Mod API -This patch is Powered by ReplayMod(https://github.com/ReplayMod) diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java index a0a6cde96322df8e455b26b32b1c593f332d4db6..b5031ba5c48c7d007a7c05766a2beff422504c3e 100644 @@ -19,18 +18,18 @@ index a0a6cde96322df8e455b26b32b1c593f332d4db6..b5031ba5c48c7d007a7c05766a2beff4 } // Leaves end - skip bot diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 7e93baa65715383092fd43132b6f4da9eddcf39c..af648b9301a7a964af88a55e181b68780a9f4ca5 100644 +index 25c11fbe0b4e0cdc0aa63982d185935e2016ba79..b6c8536c143b9ff64e7a7cb7016d113e7f766fb1 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -316,6 +316,7 @@ public final class CraftServer implements Server { - private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer; // Paper - Custom Potion Mixes - public final io.papermc.paper.SparksFly spark; // Paper - spark +@@ -317,6 +317,7 @@ public final class CraftServer implements Server { + public final io.papermc.paper.SparksFly spark; + private final ServerConfiguration serverConfig = new PaperServerConfiguration(); private final org.leavesmc.leaves.entity.CraftBotManager botManager; // Leaves + private final org.leavesmc.leaves.entity.CraftPhotographerManager photographerManager = new org.leavesmc.leaves.entity.CraftPhotographerManager(); // Leaves // Paper start - Folia region threading API private final io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler(); -@@ -410,7 +411,7 @@ public final class CraftServer implements Server { +@@ -411,7 +412,7 @@ public final class CraftServer implements Server { public CraftServer(DedicatedServer console, PlayerList playerList) { this.console = console; this.playerList = (DedicatedPlayerList) playerList; @@ -39,7 +38,7 @@ index 7e93baa65715383092fd43132b6f4da9eddcf39c..af648b9301a7a964af88a55e181b6878 @Override public CraftPlayer apply(ServerPlayer player) { return player.getBukkitEntity(); -@@ -3303,4 +3304,11 @@ public final class CraftServer implements Server { +@@ -3218,4 +3219,11 @@ public final class CraftServer implements Server { return botManager; } // Leaves end - Bot API @@ -52,10 +51,10 @@ index 7e93baa65715383092fd43132b6f4da9eddcf39c..af648b9301a7a964af88a55e181b6878 + // Leaves end - replay mod api } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 2b441ba89c603903267db63c7515b0de2cbe09b1..81c8a0a236a892afd56b8fbc56427bb61b24ebcd 100644 +index 656586dc3bda8aefc8b2e648e9f3d008cb2908fd..b0e3471b3f18994c9ccaea4afe34a31709e68571 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -99,6 +99,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -109,6 +109,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } if (entity instanceof org.leavesmc.leaves.bot.ServerBot bot) { return new org.leavesmc.leaves.entity.CraftBot(server, bot); } @@ -64,10 +63,10 @@ index 2b441ba89c603903267db63c7515b0de2cbe09b1..81c8a0a236a892afd56b8fbc56427bb6 // Special case complex part, since there is no extra entity type for them if (entity instanceof EnderDragonPart complexPart) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index cc4b2061ae9cbd5a30b297be477cde703203b3f5..ed687326dfda04f006815f66c48e978221ce653c 100644 +index 1db6276ae7a547860cf2c6f85b37ec4d6b33655a..e09e9daadb9f8d8230d72f50ab34bffd1c5c3ecd 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2255,7 +2255,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2257,7 +2257,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public boolean canSee(Player player) { diff --git a/leaves-server/paper-patches/features/0013-Force-minecraft-command.patch b/leaves-server/paper-patches/features/0012-Force-minecraft-command.patch similarity index 100% rename from leaves-server/paper-patches/features/0013-Force-minecraft-command.patch rename to leaves-server/paper-patches/features/0012-Force-minecraft-command.patch diff --git a/leaves-server/paper-patches/features/0014-Bytebuf-API.patch b/leaves-server/paper-patches/features/0013-Bytebuf-API.patch similarity index 79% rename from leaves-server/paper-patches/features/0014-Bytebuf-API.patch rename to leaves-server/paper-patches/features/0013-Bytebuf-API.patch index d9e6aef5..4cbacb50 100644 --- a/leaves-server/paper-patches/features/0014-Bytebuf-API.patch +++ b/leaves-server/paper-patches/features/0013-Bytebuf-API.patch @@ -5,18 +5,18 @@ Subject: [PATCH] Bytebuf API diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index af648b9301a7a964af88a55e181b68780a9f4ca5..09a9c062a0ad15df3896fba161bdfb17d34181ba 100644 +index b6c8536c143b9ff64e7a7cb7016d113e7f766fb1..eb49cf958cbbd1d53f0bb4556ade8bc407ae7a20 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -317,6 +317,7 @@ public final class CraftServer implements Server { - public final io.papermc.paper.SparksFly spark; // Paper - spark +@@ -318,6 +318,7 @@ public final class CraftServer implements Server { + private final ServerConfiguration serverConfig = new PaperServerConfiguration(); private final org.leavesmc.leaves.entity.CraftBotManager botManager; // Leaves private final org.leavesmc.leaves.entity.CraftPhotographerManager photographerManager = new org.leavesmc.leaves.entity.CraftPhotographerManager(); // Leaves + private final org.leavesmc.leaves.bytebuf.internal.InternalBytebufHandler internalBytebufHandler = new org.leavesmc.leaves.bytebuf.internal.InternalBytebufHandler(); // Leaves // Paper start - Folia region threading API private final io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler(); -@@ -3311,4 +3312,15 @@ public final class CraftServer implements Server { +@@ -3226,4 +3227,15 @@ public final class CraftServer implements Server { return photographerManager; } // Leaves end - replay mod api @@ -33,12 +33,12 @@ index af648b9301a7a964af88a55e181b68780a9f4ca5..09a9c062a0ad15df3896fba161bdfb17 + // Leaves end - Bytebuf API } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ed687326dfda04f006815f66c48e978221ce653c..f6fb0b7e7ee67c5a1dfe1ff113c774f402af3d32 100644 +index e09e9daadb9f8d8230d72f50ab34bffd1c5c3ecd..32b866b5327634af3c5fdf80d80839e219789b21 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -3619,4 +3619,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void setSimplifyContainerDesyncCheck(final boolean simplifyContainerDesyncCheck) { - this.simplifyContainerDesyncCheck = simplifyContainerDesyncCheck; +@@ -3576,4 +3576,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void setDeathScreenScore(final int score) { + getHandle().setScore(score); } + + // Leaves start - Bytebuf API diff --git a/leaves-server/paper-patches/features/0014-Leaves-plugin.patch b/leaves-server/paper-patches/features/0014-Leaves-plugin.patch new file mode 100644 index 00000000..818b409d --- /dev/null +++ b/leaves-server/paper-patches/features/0014-Leaves-plugin.patch @@ -0,0 +1,262 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MC_XiaoHei +Date: Mon, 22 Jul 2024 09:05:56 +0000 +Subject: [PATCH] Leaves plugin + +This patch is licensed under the MIT license. + +diff --git a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java +index 41c95f00b4b2bea6d31f85e268c33d7f6184823e..a9154645554379d80b43171562f6f64a01ed3792 100644 +--- a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java ++++ b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java +@@ -172,28 +172,41 @@ public class PaperPluginsCommand extends BukkitCommand { + + final TreeMap> paperPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + final TreeMap> spigotPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); ++ // Leaves start - leaves plugin ++ final TreeMap> leavesPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + for (final PluginProvider provider : LaunchEntryPointHandler.INSTANCE.get(Entrypoint.PLUGIN).getRegisteredProviders()) { + final PluginMeta configuration = provider.getMeta(); + + if (provider instanceof SpigotPluginProvider) { + spigotPlugins.put(configuration.getDisplayName(), provider); ++ } else if (provider instanceof PaperPluginParent.LeavesServerPluginProvider) { ++ leavesPlugins.put(configuration.getDisplayName(), provider); + } else if (provider instanceof PaperPluginParent.PaperServerPluginProvider) { + paperPlugins.put(configuration.getDisplayName(), provider); + } + } + ++ final int sizeLeavesPlugins = leavesPlugins.size(); + final int sizePaperPlugins = paperPlugins.size(); + final int sizeSpigotPlugins = spigotPlugins.size(); +- final int sizePlugins = sizePaperPlugins + sizeSpigotPlugins; +- final boolean hasAllPluginTypes = (sizePaperPlugins > 0 && sizeSpigotPlugins > 0); ++ final int sizePlugins = sizePaperPlugins + sizeSpigotPlugins + sizeLeavesPlugins; ++ final boolean showSize = (sizePaperPlugins > 0 && sizeSpigotPlugins > 0) || (sizePaperPlugins > 0 && sizeLeavesPlugins > 0) || (sizeSpigotPlugins > 0 && sizeLeavesPlugins > 0); + + final Component infoMessage = Component.text().append(INFO_ICON_SERVER_PLUGIN).append(Component.text("Server Plugins (%s):".formatted(sizePlugins), NamedTextColor.WHITE)).build(); + + sender.sendMessage(infoMessage); + ++ if (!leavesPlugins.isEmpty()) { ++ sender.sendMessage(header("Leaves Plugins", 0x37D1AB, sizeLeavesPlugins, showSize)); ++ } ++ ++ for (final Component component : formatProviders(leavesPlugins)) { ++ sender.sendMessage(component); ++ } ++ + if (!paperPlugins.isEmpty()) { +- sender.sendMessage(header("Paper Plugins", 0x0288D1, sizePaperPlugins, hasAllPluginTypes)); ++ sender.sendMessage(header("Paper Plugins", 0x0288D1, sizePaperPlugins, showSize)); + } + + for (final Component component : formatProviders(paperPlugins)) { +@@ -201,8 +214,9 @@ public class PaperPluginsCommand extends BukkitCommand { + } + + if (!spigotPlugins.isEmpty()) { +- sender.sendMessage(header("Bukkit Plugins", 0xED8106, sizeSpigotPlugins, hasAllPluginTypes)); ++ sender.sendMessage(header("Bukkit Plugins", 0xED8106, sizeSpigotPlugins, showSize)); + } ++ // Leaves end - leaves plugin + + for (final Component component : formatProviders(spigotPlugins)) { + sender.sendMessage(component); +diff --git a/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java b/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java +index 70413fddd23ca1165cb5090cce4fddcb1bbca93f..2cdf32d5f08b575cf0fe755634242ddb05b59774 100644 +--- a/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java ++++ b/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java +@@ -117,19 +117,30 @@ public class PluginInitializerManager { + java.util.List files = ((java.util.List) optionSet.valuesOf("add-plugin")).stream().map(File::toPath).toList(); + io.papermc.paper.plugin.util.EntrypointUtil.registerProvidersFromSource(io.papermc.paper.plugin.provider.source.PluginFlagProviderSource.INSTANCE, files); + ++ // Leaves start - leaves plugin ++ final Set leavesPluginNames = new TreeSet<>(); + final Set paperPluginNames = new TreeSet<>(); + final Set legacyPluginNames = new TreeSet<>(); + LaunchEntryPointHandler.INSTANCE.getStorage().forEach((entrypoint, providerStorage) -> { + providerStorage.getRegisteredProviders().forEach(provider -> { + if (provider instanceof final SpigotPluginProvider legacy) { + legacyPluginNames.add(String.format("%s (%s)", legacy.getMeta().getName(), legacy.getMeta().getVersion())); ++ } else if (provider instanceof final PaperPluginParent.LeavesServerPluginProvider leaves) { ++ leavesPluginNames.add(String.format("%s (%s)", provider.getMeta().getName(), provider.getMeta().getVersion())); + } else if (provider instanceof final PaperPluginParent.PaperServerPluginProvider paper) { + paperPluginNames.add(String.format("%s (%s)", provider.getMeta().getName(), provider.getMeta().getVersion())); + } + }); + }); +- final int total = paperPluginNames.size() + legacyPluginNames.size(); ++ final int total = leavesPluginNames.size() + paperPluginNames.size() + legacyPluginNames.size(); + LOGGER.info("Initialized {} plugin{}", total, total == 1 ? "" : "s"); ++ if (!leavesPluginNames.isEmpty()) { ++ if (LOGGER.isDebugEnabled()) { ++ LOGGER.info("Leaves plugins ({}):\n - {}", leavesPluginNames.size(), String.join("\n - ", leavesPluginNames)); ++ } else { ++ LOGGER.info("Leaves plugins ({}):\n - {}", leavesPluginNames.size(), String.join(", ", leavesPluginNames)); ++ } ++ } // Leaves end - leaves plugin + if (!paperPluginNames.isEmpty()) { + if (LOGGER.isDebugEnabled()) { + LOGGER.info("Paper plugins ({}):\n - {}", paperPluginNames.size(), String.join("\n - ", paperPluginNames)); +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java +index 8cd649c977172f6b757d68565fcbb9eb8ae100a3..c18a94af99c827d73c31279e324e15ec8217a31d 100644 +--- a/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java +@@ -18,7 +18,7 @@ import java.util.List; + import java.util.Map; + import java.util.Set; + +-class LegacyPaperMeta { ++public class LegacyPaperMeta { + + + private static final TypeToken>> TYPE_TOKEN = new TypeToken<>() { +@@ -28,6 +28,12 @@ class LegacyPaperMeta { + ConfigurationTransformation.chain(notVersioned()).apply(node); + } + ++ // Leaves start - leaves plugin ++ public static void migrate(org.spongepowered.configurate.ConfigurationNode node) throws ConfigurateException { ++ ConfigurationTransformation.chain(notVersioned()).apply(node); ++ } ++ // Leaves end - leaves plugin ++ + private static ConfigurationTransformation notVersioned() { + return ConfigurationTransformation.builder() + .addAction(NodePath.path(), (path, value) -> { +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java +index d3b3a8baca013909fa9c6204d964d7d7efeb2719..753fdb9782ee6b4cb8e232ebfdd52dea5d9e2a66 100644 +--- a/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java +@@ -55,7 +55,7 @@ public class PaperPluginMeta implements PluginMeta { + @Required + private String version; + private String description; +- private List authors = List.of(); ++ protected List authors = List.of(); // Leaves - leaves plugin + private List contributors = List.of(); + private String website; + private String prefix; +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java b/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java +index 8d0da6e46d4eb5eb05c3144510c4ef083559d0ec..331a4e98699f65adfad275bde923c0f57ef4dd18 100644 +--- a/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java +@@ -23,6 +23,7 @@ import java.util.jar.JarFile; + public abstract class PluginFileType { + + public static final String PAPER_PLUGIN_YML = "paper-plugin.yml"; ++ public static final String LEAVES_PLUGIN_JSON = "leaves-plugin.json"; // Leaves - leaves plugin + private static final List CONFIG_TYPES = new ArrayList<>(); + + public static final PluginFileType PAPER = new PluginFileType<>(PAPER_PLUGIN_YML, PaperPluginParent.FACTORY) { +@@ -43,8 +44,21 @@ public abstract class PluginFileType { + entrypointHandler.register(Entrypoint.PLUGIN, provider); + } + }; ++ // Leaves start - leaves plugin ++ public static final PluginFileType LEAVES = new PluginFileType<>(LEAVES_PLUGIN_JSON, PaperPluginParent.LEAVES_FACTORY) { ++ @Override ++ protected void register(EntrypointHandler entrypointHandler, PaperPluginParent parent) { ++ PaperPluginParent.LeavesBootstrapProvider bootstrapPluginProvider = null; ++ if (parent.shouldCreateBootstrap()) { ++ bootstrapPluginProvider = parent.createLeavesBootstrapProvider(); ++ entrypointHandler.register(Entrypoint.BOOTSTRAPPER, bootstrapPluginProvider); ++ } ++ entrypointHandler.register(Entrypoint.PLUGIN, parent.createLeavesPluginProvider(bootstrapPluginProvider)); ++ } ++ }; + +- private static final List> VALUES = List.of(PAPER, SPIGOT); ++ private static final List> VALUES = List.of(LEAVES, PAPER, SPIGOT); ++ // Leaves end - leaves plugin + + private final String config; + private final PluginTypeFactory factory; +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java +index 55a6898e95704cddafda1ca5dc0951c7102fe10b..283f046c6f34c83f01e1ca1d80cbd7cc35a2b7d2 100644 +--- a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java +@@ -27,6 +27,7 @@ import java.util.jar.JarFile; + public class PaperPluginParent { + + public static final PluginTypeFactory FACTORY = new PaperPluginProviderFactory(); ++ public static final PluginTypeFactory LEAVES_FACTORY = new org.leavesmc.leaves.plugin.provider.LeavesPluginProviderFactory(); // Leaves - leaves plugin + private final Path path; + private final JarFile jarFile; + private final PaperPluginMeta description; +@@ -51,6 +52,32 @@ public class PaperPluginParent { + return new PaperBootstrapProvider(); + } + ++ // Leaves start - leaves plugin ++ public LeavesBootstrapProvider createLeavesBootstrapProvider() { ++ return new io.papermc.paper.plugin.provider.type.paper.PaperPluginParent.LeavesBootstrapProvider(); ++ } ++ public LeavesServerPluginProvider createLeavesPluginProvider(LeavesBootstrapProvider provider) { ++ return new LeavesServerPluginProvider(provider); ++ } ++ ++ public class LeavesBootstrapProvider extends PaperBootstrapProvider { ++ @Override ++ public org.leavesmc.leaves.plugin.provider.configuration.LeavesPluginMeta getMeta() { ++ return (org.leavesmc.leaves.plugin.provider.configuration.LeavesPluginMeta) super.getMeta(); ++ } ++ } ++ ++ public class LeavesServerPluginProvider extends PaperServerPluginProvider { ++ LeavesServerPluginProvider(PaperPluginParent.LeavesBootstrapProvider bootstrapProvider) { ++ super(bootstrapProvider); ++ } ++ @Override ++ public org.leavesmc.leaves.plugin.provider.configuration.LeavesPluginMeta getMeta() { ++ return (org.leavesmc.leaves.plugin.provider.configuration.LeavesPluginMeta) super.getMeta(); ++ } ++ } ++ // Leaves end - leaves plugin ++ + public PaperServerPluginProvider createPluginProvider(PaperBootstrapProvider provider) { + return new PaperServerPluginProvider(provider); + } +diff --git a/src/main/java/io/papermc/paper/plugin/storage/SimpleProviderStorage.java b/src/main/java/io/papermc/paper/plugin/storage/SimpleProviderStorage.java +index 26422904751647a061397ce978bba752149003cd..884ed63dab16acca83fe8f421762f2561400b1fb 100644 +--- a/src/main/java/io/papermc/paper/plugin/storage/SimpleProviderStorage.java ++++ b/src/main/java/io/papermc/paper/plugin/storage/SimpleProviderStorage.java +@@ -26,6 +26,16 @@ public abstract class SimpleProviderStorage implements ProviderStorage { + + @Override + public void register(PluginProvider provider) { ++ // Leaves start - leaves plugin ++ if (provider instanceof final io.papermc.paper.plugin.provider.type.paper.PaperPluginParent.LeavesServerPluginProvider leaves) { ++ org.leavesmc.leaves.plugin.provider.configuration.LeavesPluginMeta meta = leaves.getMeta(); ++ java.util.List unavailableFeatures = meta.getFeatures().getRequired().stream().filter(feature -> !org.leavesmc.leaves.plugin.ServerFeatureManager.INSTANCE.isFeatureAvailable(feature)).toList(); ++ if (!unavailableFeatures.isEmpty()) { ++ LOGGER.warn("The plugin {} ({}) requires some unavailable feature(s) {}. The plugin has been skipped.", meta.getName(), meta.getVersion(), unavailableFeatures); ++ return; ++ } ++ } ++ // Leaves end - leaves plugin + this.providers.add(provider); + } + +diff --git a/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java b/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java +index fbad4a2242aa1ab910b2e2ae4cce973ff63fda84..89d4fa952d072dd6e071dc9eef51f4050f7e750e 100644 +--- a/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java ++++ b/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java +@@ -337,7 +337,13 @@ public final class PluginRemapper { + } + index.skip(inputFile); + return CompletableFuture.completedFuture(inputFile); +- } ++ } else if (ns == null && Files.exists(fs.getPath(PluginFileType.LEAVES_PLUGIN_JSON))) { // Leaves start - leaves plugin ++ if (DEBUG_LOGGING) { ++ LOGGER.info("Plugin '{}' is a Leaves plugin with no namespace specified.", inputFile); ++ } ++ index.skip(inputFile); ++ return CompletableFuture.completedFuture(inputFile); ++ } // Leaves end - leaves plugin + } + } catch (final IOException ex) { + return CompletableFuture.failedFuture(new RuntimeException("Failed to open plugin jar " + inputFile, ex)); diff --git a/leaves-server/paper-patches/features/0016-Fix-SculkCatalyst-exp-skip.patch b/leaves-server/paper-patches/features/0015-Fix-SculkCatalyst-exp-skip.patch similarity index 87% rename from leaves-server/paper-patches/features/0016-Fix-SculkCatalyst-exp-skip.patch rename to leaves-server/paper-patches/features/0015-Fix-SculkCatalyst-exp-skip.patch index f0d02db7..493379ad 100644 --- a/leaves-server/paper-patches/features/0016-Fix-SculkCatalyst-exp-skip.patch +++ b/leaves-server/paper-patches/features/0015-Fix-SculkCatalyst-exp-skip.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix SculkCatalyst exp skip diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index fa122a6a0c56cab95d366618845c3afd2654def7..2c61032304461cecd0843dec15ef06492ba23f7a 100644 +index 03778c286144d8f04147f37aa59fb73fcc584833..daea37a117101a9f3b463e87bfc8f0f9db394aca 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -991,7 +991,7 @@ public class CraftEventFactory { +@@ -851,7 +851,7 @@ public class CraftEventFactory { CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource); CraftWorld world = (CraftWorld) entity.getWorld(); @@ -17,15 +17,15 @@ index fa122a6a0c56cab95d366618845c3afd2654def7..2c61032304461cecd0843dec15ef0649 populateFields(victim, event); // Paper - make cancellable Bukkit.getServer().getPluginManager().callEvent(event); -@@ -1002,6 +1002,7 @@ public class CraftEventFactory { - playDeathSound(victim, event); +@@ -862,6 +862,7 @@ public class CraftEventFactory { + playDeathSound(victim, event, damageSource); // Paper end victim.expToDrop = event.getDroppedExp(); + victim.expToReward = event.getRewardExp(); // Leaves - exp fix lootCheck.run(); // Paper - advancement triggers before destroying items // Paper start - Restore vanilla drops behavior -@@ -1041,6 +1042,7 @@ public class CraftEventFactory { +@@ -901,6 +902,7 @@ public class CraftEventFactory { victim.newLevel = event.getNewLevel(); victim.newTotalExp = event.getNewTotalExp(); victim.expToDrop = event.getDroppedExp(); diff --git a/leaves-server/paper-patches/features/0015-Leaves-plugins.patch b/leaves-server/paper-patches/features/0015-Leaves-plugins.patch deleted file mode 100644 index 202af35e..00000000 --- a/leaves-server/paper-patches/features/0015-Leaves-plugins.patch +++ /dev/null @@ -1,145 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MC_XiaoHei -Date: Mon, 22 Jul 2024 09:05:56 +0000 -Subject: [PATCH] Leaves plugins - - -diff --git a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java -index 41c95f00b4b2bea6d31f85e268c33d7f6184823e..9f87a63ec3bd568b187a8358b6a364174fae5493 100644 ---- a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java -+++ b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java -@@ -172,6 +172,8 @@ public class PaperPluginsCommand extends BukkitCommand { - - final TreeMap> paperPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - final TreeMap> spigotPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); -+ // Leaves start - leaves plugin -+ final TreeMap> leavesPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - - for (final PluginProvider provider : LaunchEntryPointHandler.INSTANCE.get(Entrypoint.PLUGIN).getRegisteredProviders()) { - final PluginMeta configuration = provider.getMeta(); -@@ -179,19 +181,30 @@ public class PaperPluginsCommand extends BukkitCommand { - if (provider instanceof SpigotPluginProvider) { - spigotPlugins.put(configuration.getDisplayName(), provider); - } else if (provider instanceof PaperPluginParent.PaperServerPluginProvider) { -- paperPlugins.put(configuration.getDisplayName(), provider); -+ if (provider.getMeta() instanceof org.leavesmc.leaves.plugin.provider.configuration.LeavesPluginMeta) leavesPlugins.put(configuration.getDisplayName(), provider); -+ else paperPlugins.put(configuration.getDisplayName(), provider); - } - } - -+ final int sizeLeavesPlugins = leavesPlugins.size(); - final int sizePaperPlugins = paperPlugins.size(); - final int sizeSpigotPlugins = spigotPlugins.size(); -- final int sizePlugins = sizePaperPlugins + sizeSpigotPlugins; -- final boolean hasAllPluginTypes = (sizePaperPlugins > 0 && sizeSpigotPlugins > 0); -+ final int sizePlugins = sizePaperPlugins + sizeSpigotPlugins + sizeLeavesPlugins; -+ final boolean hasAllPluginTypes = (sizePaperPlugins > 0 && sizeSpigotPlugins > 0 && sizeLeavesPlugins > 0); - - final Component infoMessage = Component.text().append(INFO_ICON_SERVER_PLUGIN).append(Component.text("Server Plugins (%s):".formatted(sizePlugins), NamedTextColor.WHITE)).build(); - - sender.sendMessage(infoMessage); - -+ if (!leavesPlugins.isEmpty()) { -+ sender.sendMessage(header("Leaves Plugins", 0x37D1AB, sizeLeavesPlugins, hasAllPluginTypes)); -+ } -+ -+ for (final Component component : formatProviders(leavesPlugins)) { -+ sender.sendMessage(component); -+ } -+ // Leaves end - leaves plugin -+ - if (!paperPlugins.isEmpty()) { - sender.sendMessage(header("Paper Plugins", 0x0288D1, sizePaperPlugins, hasAllPluginTypes)); - } -diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java -index 8cd649c977172f6b757d68565fcbb9eb8ae100a3..390625fbf54139b205a23b94d89a860fbb2c92d9 100644 ---- a/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java -+++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/LegacyPaperMeta.java -@@ -18,7 +18,7 @@ import java.util.List; - import java.util.Map; - import java.util.Set; - --class LegacyPaperMeta { -+public class LegacyPaperMeta { // Leaves - leaves plugins - - - private static final TypeToken>> TYPE_TOKEN = new TypeToken<>() { -diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java -index d3b3a8baca013909fa9c6204d964d7d7efeb2719..cdde16a4999fbf56c334c65e23d995b7a3604518 100644 ---- a/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java -+++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java -@@ -55,7 +55,7 @@ public class PaperPluginMeta implements PluginMeta { - @Required - private String version; - private String description; -- private List authors = List.of(); -+ protected List authors = List.of(); // Leaves - leaves plugins - private List contributors = List.of(); - private String website; - private String prefix; -diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java b/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java -index 8d0da6e46d4eb5eb05c3144510c4ef083559d0ec..72a69ed1d4cdeecd25bfa4fddc3ecc2b21550bad 100644 ---- a/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java -+++ b/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java -@@ -23,6 +23,7 @@ import java.util.jar.JarFile; - public abstract class PluginFileType { - - public static final String PAPER_PLUGIN_YML = "paper-plugin.yml"; -+ public static final String LEAVES_PLUGIN_CONF = "leaves-plugin.conf"; // Leaves - leaves plugins - private static final List CONFIG_TYPES = new ArrayList<>(); - - public static final PluginFileType PAPER = new PluginFileType<>(PAPER_PLUGIN_YML, PaperPluginParent.FACTORY) { -@@ -43,8 +44,21 @@ public abstract class PluginFileType { - entrypointHandler.register(Entrypoint.PLUGIN, provider); - } - }; -+ // Leaves start - leaves plugins -+ public static final PluginFileType LEAVES = new PluginFileType<>(LEAVES_PLUGIN_CONF, PaperPluginParent.LEAVES_FACTORY) { -+ @Override -+ protected void register(EntrypointHandler entrypointHandler, PaperPluginParent parent) { -+ PaperPluginParent.PaperBootstrapProvider bootstrapPluginProvider = null; -+ if (parent.shouldCreateBootstrap()) { -+ bootstrapPluginProvider = parent.createBootstrapProvider(); -+ entrypointHandler.register(Entrypoint.BOOTSTRAPPER, bootstrapPluginProvider); -+ } -+ entrypointHandler.register(Entrypoint.PLUGIN, parent.createPluginProvider(bootstrapPluginProvider)); -+ } -+ }; - -- private static final List> VALUES = List.of(PAPER, SPIGOT); -+ private static final List> VALUES = List.of(LEAVES, PAPER, SPIGOT); -+ // Leaves end - leaves plugins - - private final String config; - private final PluginTypeFactory factory; -diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java -index 55a6898e95704cddafda1ca5dc0951c7102fe10b..ebde8a79143a5e314d5054f2d125d276eaa1e734 100644 ---- a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java -+++ b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java -@@ -27,6 +27,7 @@ import java.util.jar.JarFile; - public class PaperPluginParent { - - public static final PluginTypeFactory FACTORY = new PaperPluginProviderFactory(); -+ public static final PluginTypeFactory LEAVES_FACTORY = new org.leavesmc.leaves.plugin.provider.LeavesPluginProviderFactory(); // Leaves - leaves plugins - private final Path path; - private final JarFile jarFile; - private final PaperPluginMeta description; -diff --git a/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java b/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java -index 28857d0c9b53f2068d51b8f09ef40df7a2b97502..b4d2d7280237a9ad7df095e26773e01211201b84 100644 ---- a/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java -+++ b/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java -@@ -333,7 +333,13 @@ public final class PluginRemapper { - } - index.skip(inputFile); - return CompletableFuture.completedFuture(inputFile); -- } -+ } else if (ns == null && Files.exists(fs.getPath(PluginFileType.LEAVES_PLUGIN_CONF))) { // Leaves start - leaves plugins -+ if (DEBUG_LOGGING) { -+ LOGGER.info("Plugin '{}' is a Leaves plugin with no namespace specified.", inputFile); -+ } -+ index.skip(inputFile); -+ return CompletableFuture.completedFuture(inputFile); -+ } // Leaves end - leaves plugins - } - } catch (final IOException ex) { - return CompletableFuture.failedFuture(new RuntimeException("Failed to open plugin jar " + inputFile, ex)); diff --git a/leaves-server/paper-patches/features/0016-Leaves-Config-API.patch b/leaves-server/paper-patches/features/0016-Leaves-Config-API.patch new file mode 100644 index 00000000..39743d72 --- /dev/null +++ b/leaves-server/paper-patches/features/0016-Leaves-Config-API.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> +Date: Sun, 18 May 2025 19:58:42 +0800 +Subject: [PATCH] Leaves Config API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index eb49cf958cbbd1d53f0bb4556ade8bc407ae7a20..6fbcde3248ec35d0188eea0e99922759d5f1d5cf 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -3238,4 +3238,11 @@ public final class CraftServer implements Server { + return internalBytebufHandler; + } + // Leaves end - Bytebuf API ++ ++ // Leaves start - Config API ++ @Override ++ public org.leavesmc.leaves.config.LeavesConfigProvider getLeavesConfig() { ++ return org.leavesmc.leaves.config.InternalConfigProvider.INSTANCE; ++ } ++ // Leaves end - Config API + } diff --git a/leaves-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch b/leaves-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch deleted file mode 100644 index 5b262f98..00000000 --- a/leaves-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -508,7 +_,7 @@ - // Paper start - @Override - public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -- return new com.destroystokyo.paper.PaperVersionFetcher(); -+ return new org.leavesmc.leaves.util.LeavesVersionFetcher(); // Leaves - Leaves version fetcher - } - - @Override diff --git a/leaves-server/src/main/java/co/aikar/timings/Timings.java b/leaves-server/src/main/java/co/aikar/timings/Timings.java new file mode 100644 index 00000000..df57811a --- /dev/null +++ b/leaves-server/src/main/java/co/aikar/timings/Timings.java @@ -0,0 +1,6 @@ +package co.aikar.timings; + +// It is only used to make certain plugin "confirm" that this is a Paper server +// since we removed all timings related codes and classes +public class Timings { +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index 66367762..4167771c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -4,7 +4,9 @@ import com.destroystokyo.paper.util.SneakyThrow; import io.papermc.paper.configuration.GlobalConfiguration; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; import org.bukkit.command.Command; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.permissions.Permission; @@ -28,6 +30,7 @@ import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRules; import org.leavesmc.leaves.protocol.bladeren.BladerenProtocol.LeavesFeature; import org.leavesmc.leaves.protocol.bladeren.BladerenProtocol.LeavesFeatureSet; import org.leavesmc.leaves.region.RegionFileFormat; +import org.leavesmc.leaves.util.ElytraAeronauticsHelper; import org.leavesmc.leaves.util.ForcePeacefulModeSwitchType; import org.leavesmc.leaves.util.MathUtils; @@ -39,6 +42,7 @@ import java.util.List; import java.util.Locale; import java.util.Random; import java.util.Set; +import java.util.function.Predicate; public final class LeavesConfig { @@ -216,14 +220,19 @@ public final class LeavesConfig { @GlobalConfig("cce-update-suppression") public boolean cceUpdateSuppression = false; + @GlobalConfig("sound-update-suppression") + public boolean soundUpdateSuppression = false; + @RemovedConfig(name = "redstone-wire-dont-connect-if-on-trapdoor", category = "modify", transform = true) @RemovedConfig(name = "redstone-wire-dont-connect-if-on-trapdoor", category = {"modify", "minecraft-old"}, transform = true) - @GlobalConfig("redstone-wire-dont-connect-if-on-trapdoor") - public boolean redstoneDontCantOnTrapDoor = false; + @RemovedConfig(name = "redstone-wire-dont-connect-if-on-trapdoor", category = {"modify", "minecraft-old", "block-updater"}, transform = true) + @GlobalConfig("redstone-ignore-upwards-update") + public boolean redstoneIgnoreUpwardsUpdate = false; @RemovedConfig(name = "old-block-entity-behaviour", category = {"modify", "minecraft-old"}, transform = true) - @GlobalConfig("old-block-entity-behaviour") - public boolean oldBlockEntityBehaviour = false; + @RemovedConfig(name = "old-block-entity-behaviour", category = {"modify", "minecraft-old", "block-updater"}, transform = true) + @GlobalConfig("old-block-remove-behaviour") + public boolean oldBlockRemoveBehaviour = false; } @RemovedConfig(name = "shears-in-dispenser-can-zero-amount", category = {}, transform = true) @@ -235,7 +244,7 @@ public final class LeavesConfig { public boolean armorStandCantKillByMobProjectile = false; @GlobalConfig(value = "villager-infinite-discounts", validator = VillagerInfiniteDiscountsValidator.class) - public boolean villagerInfiniteDiscounts = false; + private boolean villagerInfiniteDiscounts = false; private static class VillagerInfiniteDiscountsValidator extends BooleanConfigValidator { @Override @@ -277,12 +286,18 @@ public final class LeavesConfig { @GlobalConfig("disable-LivingEntity-ai-step-alive-check") public boolean disableLivingEntityAiStepAliveCheck = false; - @GlobalConfig("fix-fortress-mob-spawn") - public boolean fixFortressMobSpawn = false; + @GlobalConfig("spawn-invulnerable-time") + public boolean spawnInvulnerableTime = false; @GlobalConfig("old-hopper-suck-in-behavior") public boolean oldHopperSuckInBehavior = false; + @GlobalConfig("old-nether-portal-collision") // Should remove in 1.21.6 + public boolean oldNetherPortalCollision = false; + + @GlobalConfig("old-zombie-piglin-drop") + public boolean oldZombiePiglinDrop = false; + public RaidConfig raid = new RaidConfig(); @GlobalConfigCategory("revert-raid-changes") @@ -300,11 +315,27 @@ public final class LeavesConfig { public boolean skipHeightCheck = false; } + @GlobalConfig("old-zombie-reinforcement") + public boolean oldZombieReinforcement = false; + @GlobalConfig("allow-anvil-destroy-item-entities") public boolean allowAnvilDestroyItemEntities = false; - @GlobalConfig("string-tripwire-hook-duplicate") - public boolean stringTripwireHookDuplicate = false; + public TripwireConfig tripwire = new TripwireConfig(); + + @GlobalConfigCategory("tripwire-and-hook-behavior") + public static class TripwireConfig { + @RemovedConfig(name = "string-tripwire-hook-duplicate", category = {"modify", "minecraft-old"}, transform = true) + @GlobalConfig("string-tripwire-hook-duplicate") + public boolean stringTripwireHookDuplicate = false; + + @GlobalConfig("tripwire-behavior") + public TripwireBehavior tripwireBehavior = TripwireBehavior.VANILLA_21; + + public enum TripwireBehavior { + VANILLA_20, VANILLA_21, MIXED + } + } } public ElytraAeronauticsConfig elytraAeronautics = new ElytraAeronauticsConfig(); @@ -312,7 +343,7 @@ public final class LeavesConfig { @GlobalConfigCategory("elytra-aeronautics") public static class ElytraAeronauticsConfig { @GlobalConfig("no-chunk-load") - public boolean noChunk = false; + public boolean enableNoChunkLoad = false; @GlobalConfig(value = "no-chunk-height") public double noChunkHeight = 500.0D; @@ -321,13 +352,13 @@ public final class LeavesConfig { public double noChunkSpeed = -1.0D; @GlobalConfig("message") - public boolean noChunkMes = true; + public boolean doSendMessages = true; @GlobalConfig(value = "message-start") - public String noChunkStartMes = "Flight enter cruise mode"; + public String startMessage = "Flight enter cruise mode"; @GlobalConfig(value = "message-end") - public String noChunkEndMes = "Flight exit cruise mode"; + public String endMessage = "Flight exit cruise mode"; } @RemovedConfig(name = "redstone-shears-wrench", category = {}, transform = true) @@ -451,9 +482,6 @@ public final class LeavesConfig { @GlobalConfig("shave-snow-layers") public boolean shaveSnowLayers = true; - @GlobalConfig("ignore-lc") - public boolean ignoreLC = false; - @GlobalConfig("disable-packet-limit") public boolean disablePacketLimit = false; @@ -580,11 +608,33 @@ public final class LeavesConfig { @GlobalConfig("disable-vault-blacklist") public boolean disableVaultBlacklist = false; + @GlobalConfig(value = "exp-orb-absorb-mode", validator = ExpOrbModeValidator.class) + private ExpOrbAbsorbMode expOrbAbsorbMode = ExpOrbAbsorbMode.VANILLA; + + public Predicate fastAbsorbPredicate = player -> false; + + public enum ExpOrbAbsorbMode { + VANILLA, FAST, FAST_CREATIVE + } + + private static class ExpOrbModeValidator extends EnumConfigValidator { + @Override + public void verify(ExpOrbAbsorbMode old, ExpOrbAbsorbMode value) throws IllegalArgumentException { + LeavesConfig.modify.fastAbsorbPredicate = switch (value) { + case FAST -> player -> true; + case VANILLA -> player -> false; + case FAST_CREATIVE -> Player::hasInfiniteMaterials; + }; + } + } + @RemovedConfig(name = "tick-command", category = "modify") @RemovedConfig(name = "player-can-edit-sign", category = "modify") @RemovedConfig(name = "mending-compatibility-infinity", category = {"modify", "minecraft-old"}) @RemovedConfig(name = "protection-stacking", category = {"modify", "minecraft-old"}) - @RemovedConfig(name = "disable-moved-wrongly-threshold", category = {"modify"}) + @RemovedConfig(name = "disable-moved-wrongly-threshold", category = "modify") + @RemovedConfig(name = "ignore-lc", category = "modify") + @RemovedConfig(name = "fix-fortress-mob-spawn", category = {"modify", "minecraft-old"}) private final boolean removed = false; } @@ -947,7 +997,7 @@ public final class LeavesConfig { public boolean loginProtect = false; @GlobalConfig(value = "urls", lock = true, validator = ExtraYggdrasilUrlsValidator.class) - public List serviceList = List.of("https://url.with.authlib-injector-yggdrasil"); + private List serviceList = List.of("https://url.with.authlib-injector-yggdrasil"); public static class ExtraYggdrasilUrlsValidator extends ListConfigValidator.STRING { @Override @@ -1022,9 +1072,6 @@ public final class LeavesConfig { @GlobalConfig(value = "version", lock = true) public org.leavesmc.leaves.region.linear.LinearVersion version = org.leavesmc.leaves.region.linear.LinearVersion.V2; - @GlobalConfig(value = "auto-convert-anvil-to-linear", lock = true) - public boolean autoConvertAnvilToLinear = false; - @GlobalConfig(value = "flush-max-threads", lock = true) public int flushThreads = 6; @@ -1056,7 +1103,8 @@ public final class LeavesConfig { @RemovedConfig(name = "flush-frequency", category = {"region", "linear"}) @RemovedConfig(name = "crash-on-broken-symlink", category = {"region", "linear"}) - private final boolean linearCrashOnBrokenSymlink = true; + @RemovedConfig(name = "auto-convert-anvil-to-linear", category = {"region", "linear"}) + private final boolean removed = true; } } @@ -1070,6 +1118,16 @@ public final class LeavesConfig { @GlobalConfig("vanilla-display-name") public boolean vanillaDisplayName = false; + @GlobalConfig(value = "collision-behavior") + public CollisionBehavior collisionBehavior = CollisionBehavior.BLOCK_SHAPE_VANILLA; + + public enum CollisionBehavior { + VANILLA, BLOCK_SHAPE_VANILLA, PAPER + } + + @GlobalConfig("vanilla-portal-handle") + public boolean vanillaPortalHandle = false; + @RemovedConfig(name = "spigot-EndPlatform-destroy", category = "fix") private final boolean spigotEndPlatformDestroy = false; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java index 5c235e89..55b517d8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java @@ -1,5 +1,7 @@ package org.leavesmc.leaves.bot; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; import it.unimi.dsi.fastutil.Pair; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -23,13 +25,24 @@ import org.leavesmc.leaves.bot.subcommands.BotRemoveCommand; import org.leavesmc.leaves.bot.subcommands.BotSaveCommand; import org.leavesmc.leaves.command.LeavesCommandUtil; import org.leavesmc.leaves.command.LeavesSubcommand; +import org.leavesmc.leaves.command.LeavesSuggestionCommand; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import static net.kyori.adventure.text.Component.text; -public class BotCommand extends Command { +//TODO rewrite +public class BotCommand extends Command implements LeavesSuggestionCommand { public BotCommand(String name) { super(name); @@ -74,6 +87,17 @@ public class BotCommand extends Command { return Collections.emptyList(); } + @Override + public @Nullable CompletableFuture tabSuggestion(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, @NotNull SuggestionsBuilder builder) throws IllegalArgumentException { + if (args.length > 1) { + final @Nullable Pair subCommand = resolveCommand(args[0]); + if (subCommand != null) { + return subCommand.second().tabSuggestion(sender, subCommand.first(), Arrays.copyOfRange(args, 1, args.length), location, builder); + } + } + return null; + } + @Override public boolean execute(final @NotNull CommandSender sender, final @NotNull String commandLabel, final String @NotNull [] args) { if (!testPermission(sender) || !LeavesConfig.modify.fakeplayer.enable) return true; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotDataStorage.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotDataStorage.java index 53bece66..6a28f733 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotDataStorage.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotDataStorage.java @@ -1,6 +1,7 @@ package org.leavesmc.leaves.bot; import com.mojang.logging.LogUtils; +import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtAccounter; import net.minecraft.nbt.NbtIo; @@ -64,7 +65,7 @@ public class BotDataStorage implements IPlayerDataStorage { if (flag && player instanceof ServerBot bot) { CompoundTag nbt = new CompoundTag(); nbt.putString("name", bot.createState.name()); - nbt.putUUID("uuid", bot.getUUID()); + nbt.store("uuid", UUIDUtil.CODEC, bot.getUUID()); nbt.putBoolean("resume", bot.resume); this.savedBotList.put(bot.createState.realName(), nbt); this.saveBotList(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotInventoryContainer.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotInventoryContainer.java index 4f5e6e5c..1a50675f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotInventoryContainer.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotInventoryContainer.java @@ -1,157 +1,114 @@ package org.leavesmc.leaves.bot; -import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Pair; -import net.minecraft.core.NonNullList; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; -import net.minecraft.world.ContainerHelper; -import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.component.CustomData; import javax.annotation.Nonnull; -import java.util.List; -// Power by gugle-carpet-addition(https://github.com/Gu-ZT/gugle-carpet-addition) -public class BotInventoryContainer extends SimpleContainer { +public class BotInventoryContainer extends Inventory { - public final NonNullList items; - public final NonNullList armor; - public final NonNullList offhand; - private final List> compartments; - private final NonNullList buttons = NonNullList.withSize(13, ItemStack.EMPTY); - private final ServerBot player; + private static final ItemStack button; - public BotInventoryContainer(ServerBot player) { - this.player = player; - this.items = this.player.getInventory().items; - this.armor = this.player.getInventory().armor; - this.offhand = this.player.getInventory().offhand; - this.compartments = ImmutableList.of(this.items, this.armor, this.offhand, this.buttons); - createButton(); + static { + CompoundTag customData = new CompoundTag(); + customData.putBoolean("Leaves.Gui.Placeholder", true); + + DataComponentPatch patch = DataComponentPatch.builder() + .set(DataComponents.CUSTOM_NAME, Component.empty()) + .set(DataComponents.CUSTOM_DATA, CustomData.of(customData)) + .build(); + + button = new ItemStack(Items.STRUCTURE_VOID); + button.applyComponents(patch); + } + + private final Inventory original; + + public BotInventoryContainer(Inventory original) { + super(original.player, original.equipment); + this.original = original; } @Override public int getContainerSize() { - return this.items.size() + this.armor.size() + this.offhand.size() + this.buttons.size(); - } - - @Override - public boolean isEmpty() { - for (ItemStack itemStack : this.items) { - if (itemStack.isEmpty()) { - continue; - } - return false; - } - for (ItemStack itemStack : this.armor) { - if (itemStack.isEmpty()) { - continue; - } - return false; - } - for (ItemStack itemStack : this.offhand) { - if (itemStack.isEmpty()) { - continue; - } - return false; - } - return true; + return 54; } @Override @Nonnull public ItemStack getItem(int slot) { - Pair, Integer> pair = getItemSlot(slot); - if (pair != null) { - return pair.getFirst().get(pair.getSecond()); - } else { - return ItemStack.EMPTY; + int realSlot = convertSlot(slot); + if (realSlot == -999) { + // buttons are the same + return button; } + return original.getItem(realSlot); } - public Pair, Integer> getItemSlot(int slot) { - switch (slot) { - case 0 -> { - return new Pair<>(buttons, 0); - } - case 1, 2, 3, 4 -> { - return new Pair<>(armor, 4 - slot); - } - case 5, 6 -> { - return new Pair<>(buttons, slot - 4); - } - case 7 -> { - return new Pair<>(offhand, 0); - } - case 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 -> { - return new Pair<>(buttons, slot - 5); - } + public int convertSlot(int slot) { + return switch (slot) { + // Mainhand is always store at slot 0 + case 6 -> 0; + + // Offhand + case 7 -> 40; + + // Equipment slot start at 36 + case 1, 2, 3, 4 -> 40 - slot; + + // Inventory storage case 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44 -> { - return new Pair<>(items, slot - 9); - } - case 45, 46, 47, 48, 49, 50, 51, 52, 53 -> { - return new Pair<>(items, slot - 45); - } - default -> { - return null; - } - } + 36, 37, 38, 39, 40, 41, 42, 43, 44 -> slot - 9; + + // Hotbar, 45 -> Mainhand (0) + case 45, 46, 47, 48, 49, 50, 51, 52, 53 -> slot - 45; + + // Buttons + default -> -999; + }; } @Override @Nonnull public ItemStack removeItem(int slot, int amount) { - Pair, Integer> pair = getItemSlot(slot); - NonNullList list = null; - ItemStack itemStack = ItemStack.EMPTY; - if (pair != null) { - list = pair.getFirst(); - slot = pair.getSecond(); + int realSlot = convertSlot(slot); + if (realSlot == -999) { + // Don't remove buttons + return ItemStack.EMPTY; } - if (list != null && !list.get(slot).isEmpty()) { - itemStack = ContainerHelper.removeItem(list, slot, amount); - player.detectEquipmentUpdatesPublic(); - } - return itemStack; + ItemStack removed = original.removeItem(realSlot, amount); + player.detectEquipmentUpdates(); + return removed; } @Override @Nonnull public ItemStack removeItemNoUpdate(int slot) { - Pair, Integer> pair = getItemSlot(slot); - NonNullList list = null; - if (pair != null) { - list = pair.getFirst(); - slot = pair.getSecond(); + int realSlot = convertSlot(slot); + if (realSlot == -999) { + // Don't remove buttons + return ItemStack.EMPTY; } - if (list != null && !list.get(slot).isEmpty()) { - ItemStack itemStack = list.get(slot); - list.set(slot, ItemStack.EMPTY); - return itemStack; - } - return ItemStack.EMPTY; + return original.removeItemNoUpdate(realSlot); } @Override public void setItem(int slot, @Nonnull ItemStack stack) { - Pair, Integer> pair = getItemSlot(slot); - NonNullList list = null; - if (pair != null) { - list = pair.getFirst(); - slot = pair.getSecond(); - } - if (list != null) { - list.set(slot, stack); - player.detectEquipmentUpdatesPublic(); + int realSlot = convertSlot(slot); + if (realSlot == -999) { + // Don't modify buttons + return; } + original.setItem(realSlot, stack); + player.detectEquipmentUpdates(); } @Override @@ -165,27 +122,4 @@ public class BotInventoryContainer extends SimpleContainer { } return !(player.distanceToSqr(this.player) > 64.0); } - - @Override - public void clearContent() { - for (List list : this.compartments) { - list.clear(); - } - } - - private void createButton() { - CompoundTag customData = new CompoundTag(); - customData.putBoolean("Leaves.Gui.Placeholder", true); - - DataComponentPatch patch = DataComponentPatch.builder() - .set(DataComponents.CUSTOM_NAME, Component.empty()) - .set(DataComponents.CUSTOM_DATA, CustomData.of(customData)) - .build(); - - for (int i = 0; i < 13; i++) { - ItemStack button = new ItemStack(Items.STRUCTURE_VOID); - button.applyComponents(patch); - buttons.set(i, button); - } - } -} +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java index fb950349..54d58b90 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java @@ -23,7 +23,6 @@ import org.bukkit.craftbukkit.CraftWorld; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.Configs; import org.leavesmc.leaves.event.bot.BotCreateEvent; import org.leavesmc.leaves.event.bot.BotJoinEvent; import org.leavesmc.leaves.event.bot.BotLoadEvent; @@ -60,7 +59,7 @@ public class BotList { public ServerBot createNewBot(BotCreateState state) { BotCreateEvent event = new BotCreateEvent(state.name(), state.skinName(), state.location(), state.createReason(), state.creator()); - event.setCancelled(!isCreateLegal(state.name())); + event.setCancelled(!BotUtil.isCreateLegal(state.name())); this.server.server.getPluginManager().callEvent(event); if (event.isCancelled()) { @@ -100,10 +99,11 @@ public class BotList { if (optional.isEmpty()) { return null; } + CompoundTag nbt = optional.get(); ResourceKey resourcekey = null; - if (optional.get().contains("WorldUUIDMost") && optional.get().contains("WorldUUIDLeast")) { - org.bukkit.World bWorld = Bukkit.getServer().getWorld(new UUID(optional.get().getLong("WorldUUIDMost"), optional.get().getLong("WorldUUIDLeast"))); + if (nbt.contains("WorldUUIDMost") && nbt.contains("WorldUUIDLeast")) { + org.bukkit.World bWorld = Bukkit.getServer().getWorld(new UUID(nbt.getLong("WorldUUIDMost").orElseThrow(), nbt.getLong("WorldUUIDLeast").orElseThrow())); if (bWorld != null) { resourcekey = ((CraftWorld) bWorld).getHandle().dimension(); } @@ -113,11 +113,11 @@ public class BotList { } ServerLevel world = this.server.getLevel(resourcekey); - return this.placeNewBot(bot, world, bot.getLocation(), optional.get()); + return this.placeNewBot(bot, world, bot.getLocation(), nbt); } - public ServerBot placeNewBot(ServerBot bot, ServerLevel world, Location location, @Nullable CompoundTag nbt) { - Optional optional = Optional.ofNullable(nbt); + public ServerBot placeNewBot(@NotNull ServerBot bot, ServerLevel world, Location location, @Nullable CompoundTag save) { + Optional optional = Optional.ofNullable(save); bot.isRealPlayer = true; bot.loginTime = System.currentTimeMillis(); @@ -142,8 +142,10 @@ public class BotList { bot.supressTrackerForLogin = true; world.addNewPlayer(bot); - bot.loadAndSpawnEnderpearls(optional); - bot.loadAndSpawnParentVehicle(optional); + optional.ifPresent(nbt -> { + bot.loadAndSpawnEnderPearls(nbt); + bot.loadAndSpawnParentVehicle(nbt); + }); BotJoinEvent event1 = new BotJoinEvent(bot.getBukkitEntity(), PaperAdventure.asAdventure(Component.translatable("multiplayer.player.joined", bot.getDisplayName())).style(Style.style(NamedTextColor.YELLOW))); this.server.server.getPluginManager().callEvent(event1); @@ -178,17 +180,13 @@ public class BotList { bot.removeTaskId = -1; } - if (this.server.isSameThread()) { - bot.doTick(); - } - if (event.shouldSave()) { playerIO.save(bot); } else { - bot.dropAll(); + bot.dropAll(true); } - if (bot.isPassenger()) { + if (bot.isPassenger() && event.shouldSave()) { Entity entity = bot.getRootVehicle(); if (entity.hasExactlyOnePlayerPassenger()) { bot.stopRiding(); @@ -217,7 +215,7 @@ public class BotList { bot.removeTab(); for (ServerPlayer player : bot.serverLevel().players()) { - if (!(player instanceof ServerBot) && !bot.needSendFakeData(player)) { + if (!(player instanceof ServerBot)) { player.connection.send(new ClientboundRemoveEntitiesPacket(bot.getId())); } } @@ -239,9 +237,9 @@ public class BotList { public void loadResume() { if (LeavesConfig.modify.fakeplayer.enable && LeavesConfig.modify.fakeplayer.canResident) { CompoundTag savedBotList = this.getSavedBotList().copy(); - for (String realName : savedBotList.getAllKeys()) { - CompoundTag nbt = savedBotList.getCompound(realName); - if (nbt.getBoolean("resume")) { + for (String realName : savedBotList.keySet()) { + CompoundTag nbt = savedBotList.getCompound(realName).orElseThrow(); + if (nbt.getBoolean("resume").orElse(false)) { this.loadNewBot(realName); } } @@ -249,7 +247,7 @@ public class BotList { } public void networkTick() { - this.bots.stream().filter(bot -> bot.getConfigValue(Configs.TICK_TYPE) == ServerBot.TickType.NETWORK).forEach(ServerBot::doTick); // TODO perf? + this.bots.forEach(ServerBot::networkTick); } @Nullable @@ -266,22 +264,6 @@ public class BotList { return this.dataStorage.getSavedBotList(); } - public boolean isCreateLegal(@NotNull String name) { - if (!name.matches("^[a-zA-Z0-9_]{4,16}$")) { - return false; - } - - if (Bukkit.getPlayerExact(name) != null || this.getBotByName(name) != null) { - return false; - } - - if (LeavesConfig.modify.fakeplayer.unableNames.contains(name)) { - return false; - } - - return this.bots.size() < LeavesConfig.modify.fakeplayer.limit; - } - public static class CustomGameProfile extends GameProfile { public CustomGameProfile(UUID uuid, String name, String[] skin) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotUtil.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotUtil.java index 78414d1f..6504fa29 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotUtil.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotUtil.java @@ -4,7 +4,9 @@ import com.google.common.base.Charsets; import net.minecraft.core.NonNullList; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.item.ItemStack; +import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; import java.util.UUID; @@ -70,4 +72,24 @@ public class BotUtil { public static UUID getBotUUID(@NotNull String realName) { return UUID.nameUUIDFromBytes(("Fakeplayer:" + realName).getBytes(Charsets.UTF_8)); } + + public static String getFullName(String inputName) { + return LeavesConfig.modify.fakeplayer.prefix + inputName + LeavesConfig.modify.fakeplayer.suffix; + } + + public static boolean isCreateLegal(@NotNull String name) { + if (!name.matches("^[a-zA-Z0-9_]{4,16}$")) { + return false; + } + + if (Bukkit.getPlayerExact(name) != null || BotList.INSTANCE.getBotByName(name) != null) { + return false; + } + + if (LeavesConfig.modify.fakeplayer.unableNames.contains(name)) { + return false; + } + + return BotList.INSTANCE.bots.size() < LeavesConfig.modify.fakeplayer.limit; + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java index fad636d8..ac5fa319 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java @@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableMap; import com.mojang.authlib.GameProfile; import io.papermc.paper.adventure.PaperAdventure; import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; import net.minecraft.core.particles.BlockParticleOption; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; @@ -14,6 +15,7 @@ import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket; +import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ClientInformation; @@ -35,6 +37,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.ChestMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.portal.TeleportTransition; @@ -99,7 +102,7 @@ public class ServerBot extends ServerPlayer { this.configs = configBuilder.build(); this.stats = new BotStatsCounter(server); - this.container = new BotInventoryContainer(this); + this.container = new BotInventoryContainer(this.getInventory()); this.tracingRange = world.spigotConfig.playerTrackingRange * world.spigotConfig.playerTrackingRange; this.notSleepTicks = 0; @@ -130,7 +133,7 @@ public class ServerBot extends ServerPlayer { // copy ServerPlayer end if (this.getConfigValue(Configs.SPAWN_PHANTOM)) { - notSleepTicks++; + this.notSleepTicks++; } if (LeavesConfig.modify.fakeplayer.regenAmount > 0.0 && server.getTickCount() % 20 == 0) { @@ -155,7 +158,12 @@ public class ServerBot extends ServerPlayer { @Override public void doTick() { - this.absMoveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + if (!this.isAlive()) { + this.die(this.damageSources().generic()); + return; + } + + this.absSnapTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); if (this.isPassenger()) { this.setOnGround(false); @@ -172,7 +180,7 @@ public class ServerBot extends ServerPlayer { this.notSleepTicks = 0; } - if (!this.level().isClientSide && this.level().isDay()) { + if (!this.level().isClientSide && this.level().isBrightOutside()) { this.stopSleepInBed(false, true); } } else if (this.sleepCounter > 0) { @@ -212,27 +220,56 @@ public class ServerBot extends ServerPlayer { this.updatePlayerPose(); } - @Override - public @Nullable ServerBot teleport(@NotNull TeleportTransition teleportTarget) { - if (this.isSleeping() || this.isRemoved()) { - return null; - } - if (teleportTarget.newLevel().dimension() != this.serverLevel().dimension()) { - return null; - } else { - if (!teleportTarget.asPassenger()) { - this.stopRiding(); - } - - this.connection.internalTeleport(PositionMoveRotation.of(teleportTarget), teleportTarget.relatives()); - this.connection.resetPosition(); - teleportTarget.postTeleportTransition().onTransition(this); - return this; + public void networkTick() { + if (this.getConfigValue(Configs.TICK_TYPE) == TickType.NETWORK) { + this.doTick(); } } @Override - public void handlePortal() { + public @Nullable ServerBot teleport(@NotNull TeleportTransition teleportTransition) { + if (this.isSleeping() || this.isRemoved()) { + return null; + } + if (!teleportTransition.asPassenger()) { + this.removeVehicle(); + } + + ServerLevel fromLevel = this.serverLevel(); + ServerLevel toLevel = teleportTransition.newLevel(); + + if (toLevel.dimension() == fromLevel.dimension()) { + this.teleportSetPosition(PositionMoveRotation.of(teleportTransition), teleportTransition.relatives()); + teleportTransition.postTeleportTransition().onTransition(this); + return this; + } else { + this.isChangingDimension = true; + fromLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + this.unsetRemoved(); + this.setServerLevel(toLevel); + this.teleportSetPosition(PositionMoveRotation.of(teleportTransition), teleportTransition.relatives()); + toLevel.addDuringTeleport(this); + this.stopUsingItem(); + teleportTransition.postTeleportTransition().onTransition(this); + this.isChangingDimension = false; + + if (org.leavesmc.leaves.LeavesConfig.modify.netherPortalFix) { + final ResourceKey fromDim = fromLevel.dimension(); + final ResourceKey toDim = level().dimension(); + if (!((fromDim != Level.OVERWORLD || toDim != Level.NETHER) && (fromDim != Level.NETHER || toDim != Level.OVERWORLD))) { + BlockPos fromPortal = org.leavesmc.leaves.util.ReturnPortalManager.findPortalAt(this, fromDim, lastPos); + BlockPos toPos = this.blockPosition(); + if (fromPortal != null) { + org.leavesmc.leaves.util.ReturnPortalManager.storeReturnPortal(this, toDim, toPos, fromPortal); + } + } + } + if (this.isBlocking()) { + this.stopUsingItem(); + } + } + + return this; } @Override @@ -245,12 +282,12 @@ public class ServerBot extends ServerPlayer { ItemStack item = this.getItemInHand(hand); if (!item.isEmpty()) { - BotUtil.replenishment(item, getInventory().items); + BotUtil.replenishment(item, getInventory().getNonEquipmentItems()); if (BotUtil.isDamage(item, 10)) { BotUtil.replaceTool(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND, this); } } - this.detectEquipmentUpdatesPublic(); + this.detectEquipmentUpdates(); } @Override @@ -271,6 +308,9 @@ public class ServerBot extends ServerPlayer { @Override public void checkFallDamage(double y, boolean onGround, @NotNull BlockState state, @NotNull BlockPos pos) { ServerLevel serverLevel = this.serverLevel(); + if (!this.isInWater() && y < 0.0) { + this.fallDistance -= (float) y; + } if (onGround && this.fallDistance > 0.0F) { this.onChangedBlock(serverLevel, pos); double attributeValue = this.getAttributeValue(Attributes.SAFE_FALL_DISTANCE); @@ -354,21 +394,21 @@ public class ServerBot extends ServerPlayer { @Override public void readAdditionalSaveData(@NotNull CompoundTag nbt) { super.readAdditionalSaveData(nbt); - this.setShiftKeyDown(nbt.getBoolean("isShiftKeyDown")); + this.setShiftKeyDown(nbt.getBoolean("isShiftKeyDown").orElse(false)); - CompoundTag createNbt = nbt.getCompound("createStatus"); - BotCreateState.Builder createBuilder = BotCreateState.builder(createNbt.getString("realName"), null).name(createNbt.getString("name")); + CompoundTag createNbt = nbt.getCompound("createStatus").orElseThrow(); + BotCreateState.Builder createBuilder = BotCreateState.builder(createNbt.getString("realName").orElseThrow(), null).name(createNbt.getString("name").orElseThrow()); String[] skin = null; if (createNbt.contains("skin")) { - ListTag skinTag = createNbt.getList("skin", 8); + ListTag skinTag = createNbt.getList("skin").orElseThrow(); skin = new String[skinTag.size()]; for (int i = 0; i < skinTag.size(); i++) { - skin[i] = skinTag.getString(i); + skin[i] = skinTag.getString(i).orElseThrow(); } } - createBuilder.skinName(createNbt.getString("skinName")).skin(skin); + createBuilder.skinName(createNbt.getString("skinName").orElseThrow()).skin(skin); createBuilder.createReason(BotCreateEvent.CreateReason.INTERNAL).creator(null); this.createState = createBuilder.build(); @@ -376,10 +416,10 @@ public class ServerBot extends ServerPlayer { if (nbt.contains("actions")) { - ListTag actionNbt = nbt.getList("actions", 10); + ListTag actionNbt = nbt.getList("actions").orElseThrow(); for (int i = 0; i < actionNbt.size(); i++) { - CompoundTag actionTag = actionNbt.getCompound(i); - AbstractBotAction action = Actions.getForName(actionTag.getString("actionName")); + CompoundTag actionTag = actionNbt.getCompound(i).orElseThrow(); + AbstractBotAction action = Actions.getForName(actionTag.getString("actionName").orElseThrow()); if (action != null) { AbstractBotAction newAction = action.create(); newAction.load(actionTag); @@ -389,10 +429,10 @@ public class ServerBot extends ServerPlayer { } if (nbt.contains("configs")) { - ListTag configNbt = nbt.getList("configs", 10); + ListTag configNbt = nbt.getList("configs").orElseThrow(); for (int i = 0; i < configNbt.size(); i++) { - CompoundTag configTag = configNbt.getCompound(i); - Configs configKey = Configs.getConfig(configTag.getString("configName")); + CompoundTag configTag = configNbt.getCompound(i).orElseThrow(); + Configs configKey = Configs.getConfig(configTag.getString("configName").orElseThrow()); if (configKey != null) { this.configs.get(configKey).load(configTag); } @@ -400,6 +440,11 @@ public class ServerBot extends ServerPlayer { } } + @Override + public boolean isClientAuthoritative() { + return false; + } + public void sendPlayerInfo(ServerPlayer player) { player.connection.send(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME), List.of(this))); } @@ -510,9 +555,23 @@ public class ServerBot extends ServerPlayer { return null; } - public void dropAll() { - this.getInventory().dropAll(); - this.detectEquipmentUpdatesPublic(); + public void dropAll(boolean death) { + NonNullList items = this.getInventory().getNonEquipmentItems(); + for (int i = 0; i < items.size(); i++) { + ItemStack itemStack = items.get(i); + if (!itemStack.isEmpty()) { + this.drop(itemStack, death, false); + items.set(i, ItemStack.EMPTY); + } + } + for (EquipmentSlot slot : EquipmentSlot.values()) { + ItemStack itemStack; + if (!(itemStack = this.equipment.get(slot)).isEmpty()) { + this.drop(itemStack, death, false); + this.equipment.set(slot, ItemStack.EMPTY); + } + } + this.detectEquipmentUpdates(); } private void runAction() { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotAction.java index 50a874e8..72ea8fc5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotAction.java @@ -1,7 +1,10 @@ package org.leavesmc.leaves.bot.agent; +import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.ServerBot; @@ -12,21 +15,24 @@ import org.leavesmc.leaves.event.bot.BotActionStopEvent; import java.util.List; import java.util.UUID; +import java.util.function.BiFunction; import java.util.function.Supplier; +//TODO onStop for fully terminate action (use, etc.) public abstract class AbstractBotAction> { private final String name; private final CommandArgument argument; private final Supplier creator; - - private boolean cancel; - private int tickDelay; - private int number; private UUID uuid; - private int needWaitTick; - private int canDoNumber; + private int initialTickDelay; + private int initialTickInterval; + private int initialNumber; + + private int tickToNext; + private int numberRemaining; + private boolean cancel; public AbstractBotAction(String name, CommandArgument argument, Supplier creator) { this.name = name; @@ -35,16 +41,98 @@ public abstract class AbstractBotAction> { this.creator = creator; this.cancel = false; - this.tickDelay = 20; - this.number = -1; + this.initialTickInterval = 20; + this.initialNumber = -1; } public void init() { - this.needWaitTick = 0; - this.canDoNumber = this.getNumber(); + this.tickToNext = initialTickDelay; + this.numberRemaining = this.getInitialNumber(); this.setCancelled(false); } + public void tryTick(ServerBot bot) { + if (this.numberRemaining == 0) { + this.stop(bot, BotActionStopEvent.Reason.DONE); + return; + } + + if (this.tickToNext <= 0) { + BotActionExecuteEvent event = new BotActionExecuteEvent(bot.getBukkitEntity(), name, uuid); + + event.callEvent(); + if (event.getResult() == BotActionExecuteEvent.Result.SOFT_CANCEL) { + this.tickToNext = this.getInitialTickInterval() - 1; + return; + } else if (event.getResult() == BotActionExecuteEvent.Result.HARD_CANCEL) { + if (this.numberRemaining > 0) { + this.numberRemaining--; + } + this.tickToNext = this.getInitialTickInterval() - 1; + return; + } + + if (this.doTick(bot)) { + if (this.numberRemaining > 0) { + this.numberRemaining--; + } + this.tickToNext = this.getInitialTickInterval() - 1; + } + } else { + this.tickToNext--; + } + } + + @NotNull + public CompoundTag save(@NotNull CompoundTag nbt) { + if (!this.cancel) { + nbt.putString("actionName", this.name); + nbt.store("actionUUID", UUIDUtil.CODEC, this.uuid); + + nbt.putInt("initialTickDelay", this.initialTickDelay); + nbt.putInt("initialTickInterval", this.initialTickInterval); + nbt.putInt("initialNumber", this.initialNumber); + + nbt.putInt("tickToNext", this.tickToNext); + nbt.putInt("numberRemaining", this.numberRemaining); + } + return nbt; + } + + public void load(@NotNull CompoundTag nbt) { + this.uuid = nbt.read("actionUUID", UUIDUtil.CODEC).orElse(UUID.randomUUID()); + + this.initialTickDelay = nbt.getInt("initialTickDelay").orElse(0); + this.initialTickInterval = nbt.getInt("initialTickInterval").orElse(0); + this.initialNumber = nbt.getInt("initialNumber").orElse(0); + + this.tickToNext = nbt.getInt("tickToNext").orElse(0); + this.numberRemaining = nbt.getInt("numberRemaining").orElse(0); + } + + public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) { + new BotActionStopEvent(bot.getBukkitEntity(), this.name, this.uuid, reason, null).callEvent(); + this.setCancelled(true); + } + + public abstract void loadCommand(@Nullable ServerPlayer player, @NotNull CommandArgumentResult result); + + public abstract boolean doTick(@NotNull ServerBot bot); + + @SuppressWarnings("unchecked") + public E setSuggestion(int n, BiFunction, String>> suggestion) { + this.argument.setSuggestion(n, suggestion); + return (E) this; + } + + public E setSuggestion(int n, Pair, String> suggestion) { + return this.setSuggestion(n, (sender, arg) -> suggestion); + } + + public E setSuggestion(int n, List tabComplete) { + return this.setSuggestion(n, Pair.of(tabComplete, null)); + } + public String getName() { return this.name; } @@ -53,28 +141,42 @@ public abstract class AbstractBotAction> { return uuid; } - public int getTickDelay() { - return this.tickDelay; - } - @SuppressWarnings("unchecked") - public E setTickDelay(int tickDelay) { - this.tickDelay = Math.max(0, tickDelay); + public E setInitialTickDelay(int initialTickDelay) { + this.initialTickDelay = initialTickDelay; return (E) this; } - public int getNumber() { - return this.number; + public int getInitialTickDelay() { + return this.initialTickDelay; + } + + public int getInitialTickInterval() { + return this.initialTickInterval; } @SuppressWarnings("unchecked") - public E setNumber(int number) { - this.number = Math.max(-1, number); + public E setInitialTickInterval(int initialTickInterval) { + this.initialTickInterval = Math.max(1, initialTickInterval); return (E) this; } - public int getCanDoNumber() { - return this.canDoNumber; + public int getInitialNumber() { + return this.initialNumber; + } + + @SuppressWarnings("unchecked") + public E setInitialNumber(int initialNumber) { + this.initialNumber = Math.max(-1, initialNumber); + return (E) this; + } + + public int getTickToNext() { + return this.tickToNext; + } + + public int getNumberRemaining() { + return this.numberRemaining; } public boolean isCancelled() { @@ -85,79 +187,12 @@ public abstract class AbstractBotAction> { this.cancel = cancel; } - public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) { - new BotActionStopEvent(bot.getBukkitEntity(), this.name, this.uuid, reason, null).callEvent(); - this.setCancelled(true); - } - public CommandArgument getArgument() { return this.argument; } - @SuppressWarnings("unchecked") - public E setTabComplete(int index, List list) { - this.argument.setTabComplete(index, list); - return (E) this; - } - - public void tryTick(ServerBot bot) { - if (this.canDoNumber == 0) { - this.stop(bot, BotActionStopEvent.Reason.DONE); - return; - } - - if (this.needWaitTick <= 0) { - BotActionExecuteEvent event = new BotActionExecuteEvent(bot.getBukkitEntity(), name, uuid); - - event.callEvent(); - if (event.getResult() == BotActionExecuteEvent.Result.SOFT_CANCEL) { - this.needWaitTick = this.getTickDelay(); - return; - } else if (event.getResult() == BotActionExecuteEvent.Result.HARD_CANCEL) { - if (this.canDoNumber > 0) { - this.canDoNumber--; - } - this.needWaitTick = this.getTickDelay(); - return; - } - - if (this.doTick(bot)) { - if (this.canDoNumber > 0) { - this.canDoNumber--; - } - this.needWaitTick = this.getTickDelay(); - } - } else { - this.needWaitTick--; - } - } - @NotNull public E create() { return this.creator.get(); } - - @NotNull - public CompoundTag save(@NotNull CompoundTag nbt) { - if (!this.cancel) { - nbt.putString("actionName", this.name); - nbt.putUUID("actionUUID", this.uuid); - - nbt.putInt("canDoNumber", this.canDoNumber); - nbt.putInt("needWaitTick", this.needWaitTick); - nbt.putInt("tickDelay", this.tickDelay); - } - return nbt; - } - - public void load(@NotNull CompoundTag nbt) { - this.tickDelay = nbt.getInt("tickDelay"); - this.needWaitTick = nbt.getInt("needWaitTick"); - this.canDoNumber = nbt.getInt("canDoNumber"); - this.uuid = nbt.getUUID("actionUUID"); - } - - public abstract void loadCommand(@Nullable ServerPlayer player, @NotNull CommandArgumentResult result); - - public abstract boolean doTick(@NotNull ServerBot bot); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java index cd3a8530..7651b61d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java @@ -31,6 +31,7 @@ public class Actions { register(new UseItemOnOffhandAction()); register(new UseItemToOffhandAction()); register(new RotationAction()); + register(new ShootAction()); } public static boolean register(@NotNull AbstractBotAction action) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerAction.java index 39b9bc97..7859594d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerAction.java @@ -1,6 +1,7 @@ package org.leavesmc.leaves.bot.agent.actions; import net.minecraft.server.level.ServerPlayer; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.agent.AbstractBotAction; @@ -8,18 +9,25 @@ import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.command.CommandArgumentResult; import org.leavesmc.leaves.command.CommandArgumentType; +import java.util.Collections; import java.util.List; import java.util.function.Supplier; public abstract class AbstractTimerAction> extends AbstractBotAction { public AbstractTimerAction(String name, Supplier creator) { - super(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), creator); - this.setTabComplete(0, List.of("[TickDelay]")).setTabComplete(1, List.of("[DoNumber]")); + this(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), creator); + } + + public AbstractTimerAction(String name, CommandArgument argument, Supplier creator) { + super(name, argument, creator); + this.setSuggestion(0, Pair.of(Collections.singletonList("0"), "[TickDelay]")); + this.setSuggestion(1, Pair.of(Collections.singletonList("20"), "[TickInterval]")); + this.setSuggestion(2, Pair.of(List.of("1", "-1"), "[DoNumber]")); } @Override public void loadCommand(@Nullable ServerPlayer player, @NotNull CommandArgumentResult result) { - this.setTickDelay(result.readInt(20)).setNumber(result.readInt(-1)); + this.setInitialTickDelay(result.readInt(0)).setInitialTickInterval(result.readInt(20)).setInitialNumber(result.readInt(1)); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/CraftBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/CraftBotAction.java index 51c939d3..27f2f46d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/CraftBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/CraftBotAction.java @@ -13,7 +13,7 @@ public class CraftBotAction extends LeavesBotAction { private final AbstractBotAction handle; public CraftBotAction(@NotNull AbstractBotAction action) { - super(BotActionType.valueOf(action.getName()), action.getTickDelay(), action.getCanDoNumber()); + super(BotActionType.valueOf(action.getName()), action.getInitialTickInterval(), action.getNumberRemaining()); this.handle = action; } @@ -31,7 +31,7 @@ public class CraftBotAction extends LeavesBotAction { } AbstractBotAction newAction = null; - String[] args = new String[]{String.valueOf(action.getExecuteInterval()), String.valueOf(action.getRemainingExecuteTime())}; + String[] args = new String[]{String.valueOf(action.getInitialTickDelay()), String.valueOf(action.getInitialTickInterval()), String.valueOf(action.getInitialNumber())}; try { if (act instanceof CraftCustomBotAction customBotAction) { newAction = customBotAction.createCraft(action.getActionPlayer(), args); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/CraftCustomBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/CraftCustomBotAction.java index 1a72cee7..bb96d671 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/CraftCustomBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/CraftCustomBotAction.java @@ -15,7 +15,7 @@ public class CraftCustomBotAction extends AbstractBotAction { @@ -12,14 +9,9 @@ public class DropAction extends AbstractTimerAction { super("drop", DropAction::new); } - @Override - public void loadCommand(@Nullable ServerPlayer player, @NotNull CommandArgumentResult result) { - this.setTickDelay(result.readInt(100)).setNumber(result.readInt(1)); - } - @Override public boolean doTick(@NotNull ServerBot bot) { - bot.dropAll(); + bot.dropAll(false); return true; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/FishAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/FishAction.java index 3a13f8ac..8610825e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/FishAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/FishAction.java @@ -14,13 +14,15 @@ public class FishAction extends AbstractTimerAction { super("fish", FishAction::new); } - private int delay = 0; - private int nowDelay = 0; + private static final int CATCH_ENTITY_DELAY = 20; + + private int initialFishInterval = 0; + private int tickToNextFish = 0; @Override - public FishAction setTickDelay(int tickDelay) { - super.setTickDelay(0); - this.delay = tickDelay; + public FishAction setInitialTickInterval(int initialTickInterval) { + super.setInitialTickInterval(1); + this.initialFishInterval = initialTickInterval; return this; } @@ -28,22 +30,22 @@ public class FishAction extends AbstractTimerAction { @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putInt("fishDelay", this.delay); - nbt.putInt("fishNowDelay", this.nowDelay); + nbt.putInt("initialFishInterval", this.initialFishInterval); + nbt.putInt("tickToNextFish", this.tickToNextFish); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { super.load(nbt); - this.delay = nbt.getInt("fishDelay"); - this.nowDelay = nbt.getInt("fishNowDelay"); + this.initialFishInterval = nbt.getInt("initialFishInterval").orElseThrow(); + this.tickToNextFish = nbt.getInt("tickToNextFish").orElseThrow(); } @Override public boolean doTick(@NotNull ServerBot bot) { - if (this.nowDelay > 0) { - this.nowDelay--; + if (this.tickToNextFish > 0) { + this.tickToNextFish--; return false; } @@ -56,12 +58,12 @@ public class FishAction extends AbstractTimerAction { if (fishingHook != null) { if (fishingHook.currentState == FishingHook.FishHookState.HOOKED_IN_ENTITY) { mainHand.use(bot.level(), bot, InteractionHand.MAIN_HAND); - this.nowDelay = 20; + this.tickToNextFish = CATCH_ENTITY_DELAY; return false; } if (fishingHook.nibble > 0) { mainHand.use(bot.level(), bot, InteractionHand.MAIN_HAND); - this.nowDelay = this.delay; + this.tickToNextFish = this.initialFishInterval - 1; return true; } } else { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/LookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/LookAction.java index 0bfc658f..d80f6059 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/LookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/LookAction.java @@ -2,6 +2,7 @@ package org.leavesmc.leaves.bot.agent.actions; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; +import org.apache.commons.lang3.tuple.Pair; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -11,15 +12,18 @@ import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.command.CommandArgumentResult; import org.leavesmc.leaves.command.CommandArgumentType; +import java.text.DecimalFormat; import java.util.List; public class LookAction extends AbstractBotAction { + private static final DecimalFormat DF = new DecimalFormat("0.0"); + public LookAction() { super("look", CommandArgument.of(CommandArgumentType.DOUBLE, CommandArgumentType.DOUBLE, CommandArgumentType.DOUBLE), LookAction::new); - this.setTabComplete(0, List.of("")); - this.setTabComplete(1, List.of("")); - this.setTabComplete(2, List.of("")); + this.setSuggestion(0, (sender, arg) -> sender instanceof ServerPlayer player ? Pair.of(List.of(DF.format(player.getX())), "") : Pair.of(List.of("0"), "")); + this.setSuggestion(1, (sender, arg) -> sender instanceof ServerPlayer player ? Pair.of(List.of(DF.format(player.getY())), "") : Pair.of(List.of("0"), "")); + this.setSuggestion(2, (sender, arg) -> sender instanceof ServerPlayer player ? Pair.of(List.of(DF.format(player.getZ())), "") : Pair.of(List.of("0"), "")); } private Vector pos; @@ -28,7 +32,7 @@ public class LookAction extends AbstractBotAction { public void loadCommand(@Nullable ServerPlayer player, @NotNull CommandArgumentResult result) throws IllegalArgumentException { Vector pos = result.readVector(); if (pos != null) { - this.setPos(pos).setTickDelay(0).setNumber(1); + this.setPos(pos).setInitialTickDelay(0).setInitialTickInterval(1).setInitialNumber(1); } else { throw new IllegalArgumentException("pos?"); } @@ -47,7 +51,13 @@ public class LookAction extends AbstractBotAction { @Override public void load(@NotNull CompoundTag nbt) { super.load(nbt); - this.setPos(new Vector(nbt.getDouble("x"), nbt.getDouble("y"), nbt.getDouble("z"))); + this.setPos( + new Vector( + nbt.getDouble("x").orElse(0.0), + nbt.getDouble("y").orElse(0.0), + nbt.getDouble("z").orElse(0.0) + ) + ); } public LookAction setPos(Vector pos) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/RotateAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/RotateAction.java index 8b339308..8d902607 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/RotateAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/RotateAction.java @@ -19,7 +19,7 @@ public class RotateAction extends AbstractBotAction { @Override public void loadCommand(@Nullable ServerPlayer player, @NotNull CommandArgumentResult result) { - this.setPlayer(player).setTickDelay(0).setNumber(1); + this.setPlayer(player).setInitialTickDelay(0).setInitialTickInterval(1).setInitialNumber(1); } public RotateAction setPlayer(ServerPlayer player) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/RotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/RotationAction.java index c56578c0..e0833dff 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/RotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/RotationAction.java @@ -2,6 +2,7 @@ package org.leavesmc.leaves.bot.agent.actions; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.ServerBot; @@ -10,14 +11,17 @@ import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.command.CommandArgumentResult; import org.leavesmc.leaves.command.CommandArgumentType; +import java.text.DecimalFormat; import java.util.List; public class RotationAction extends AbstractBotAction { + private static final DecimalFormat DF = new DecimalFormat("0.00"); + public RotationAction() { super("rotation", CommandArgument.of(CommandArgumentType.FLOAT, CommandArgumentType.FLOAT), RotationAction::new); - this.setTabComplete(0, List.of("")); - this.setTabComplete(1, List.of("")); + this.setSuggestion(0, (sender, arg) -> sender instanceof ServerPlayer player ? Pair.of(List.of(DF.format(player.getYRot())), "[yaw]") : Pair.of(List.of("0"), "")); + this.setSuggestion(0, (sender, arg) -> sender instanceof ServerPlayer player ? Pair.of(List.of(DF.format(player.getXRot())), "[pitch]") : Pair.of(List.of("0"), "")); } private float yaw; @@ -29,7 +33,7 @@ public class RotationAction extends AbstractBotAction { return; } - this.setYaw(result.readFloat(player.getYRot())).setPitch(result.readFloat(player.getXRot())).setTickDelay(0).setNumber(1); + this.setYaw(result.readFloat(player.getYRot())).setPitch(result.readFloat(player.getXRot())).setInitialTickDelay(0).setInitialTickInterval(1).setInitialNumber(1); } public RotationAction setYaw(float yaw) { @@ -54,7 +58,7 @@ public class RotationAction extends AbstractBotAction { @Override public void load(@NotNull CompoundTag nbt) { super.load(nbt); - this.setYaw(nbt.getFloat("yaw")).setPitch(nbt.getFloat("pitch")); + this.setYaw(nbt.getFloat("yaw").orElseThrow()).setPitch(nbt.getFloat("pitch").orElseThrow()); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ShootAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ShootAction.java new file mode 100644 index 00000000..1a0dbc72 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ShootAction.java @@ -0,0 +1,80 @@ +package org.leavesmc.leaves.bot.agent.actions; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.Items; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.command.CommandArgument; +import org.leavesmc.leaves.command.CommandArgumentResult; +import org.leavesmc.leaves.command.CommandArgumentType; + +import java.util.Collections; + +public class ShootAction extends AbstractTimerAction { + + private int drawingTick; + private int tickToRelease = -1; + + public ShootAction() { + super("shoot", CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), ShootAction::new); + this.setSuggestion(3, Pair.of(Collections.singletonList("20"), "[DrawingTick]")); + } + + @Override + public void init() { + super.init(); + tickToRelease = drawingTick; + } + + @Override + public boolean doTick(@NotNull ServerBot bot) { + if (!bot.getItemInHand(InteractionHand.MAIN_HAND).is(Items.BOW)) { + return false; + } + tickToRelease--; + if (tickToRelease >= 0) { + bot.gameMode.useItem(bot, bot.level(), bot.getItemInHand(InteractionHand.MAIN_HAND), InteractionHand.MAIN_HAND).consumesAction(); + bot.updateItemInHand(InteractionHand.MAIN_HAND); + return false; + } else { + bot.releaseUsingItem(); + tickToRelease = drawingTick; + return true; + } + } + + @Override + public void loadCommand(@Nullable ServerPlayer player, @NotNull CommandArgumentResult result) { + super.loadCommand(player, result); + this.setDrawingTick(result.readInt(20)); + } + + @Override + @NotNull + public CompoundTag save(@NotNull CompoundTag nbt) { + super.save(nbt); + nbt.putInt("drawingTick", this.drawingTick); + nbt.putInt("tickToRelease", this.tickToRelease); + return nbt; + } + + @Override + public void load(@NotNull CompoundTag nbt) { + super.load(nbt); + this.drawingTick = nbt.getInt("drawingTick").orElseThrow(); + this.tickToRelease = nbt.getInt("tickToRelease").orElseThrow(); + } + + public int getDrawingTick() { + return drawingTick; + } + + public ShootAction setDrawingTick(int drawingTick) { + this.drawingTick = drawingTick; + return this; + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/SneakAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/SneakAction.java index b2ca6f57..1218e556 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/SneakAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/SneakAction.java @@ -16,7 +16,7 @@ public class SneakAction extends AbstractBotAction { @Override public void loadCommand(@Nullable ServerPlayer player, @NotNull CommandArgumentResult result) { - this.setTickDelay(0).setNumber(1); + this.setInitialTickDelay(0).setInitialTickInterval(1).setInitialNumber(1); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/SwimAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/SwimAction.java index b53402b7..1c29a9ef 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/SwimAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/SwimAction.java @@ -17,7 +17,7 @@ public class SwimAction extends AbstractBotAction { @Override public void loadCommand(@Nullable ServerPlayer player, @NotNull CommandArgumentResult result) { - this.setTickDelay(0).setNumber(-1); + this.setInitialTickDelay(0).setInitialTickInterval(1).setInitialNumber(-1); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java index 5058ff92..3e42b990 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java @@ -16,7 +16,7 @@ public class AlwaysSendDataConfig extends AbstractBotConfig { private boolean value; public AlwaysSendDataConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setTabComplete(0, List.of("true", "false"))); + super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); this.value = LeavesConfig.modify.fakeplayer.canSendDataAlways; } @@ -40,6 +40,6 @@ public class AlwaysSendDataConfig extends AbstractBotConfig { @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBoolean(NAME)); + this.setValue(nbt.getBoolean(NAME).orElseThrow()); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java index 4863b822..4d7d72b1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java @@ -1,6 +1,7 @@ package org.leavesmc.leaves.bot.agent.configs; import net.minecraft.nbt.CompoundTag; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.agent.AbstractBotConfig; import org.leavesmc.leaves.command.CommandArgument; @@ -13,7 +14,7 @@ public class SimulationDistanceConfig extends AbstractBotConfig { public static final String NAME = "simulation_distance"; public SimulationDistanceConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.INTEGER).setTabComplete(0, List.of("2", "10", ""))); + super(NAME, CommandArgument.of(CommandArgumentType.INTEGER).setSuggestion(0, Pair.of(List.of("2", "10"), ""))); } @Override @@ -39,6 +40,6 @@ public class SimulationDistanceConfig extends AbstractBotConfig { @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getInt(NAME)); + this.setValue(nbt.getInt(NAME).orElseThrow()); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java index 10a0a67c..99b6e682 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java @@ -13,7 +13,7 @@ public class SkipSleepConfig extends AbstractBotConfig { public static final String NAME = "skip_sleep"; public SkipSleepConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setTabComplete(0, List.of("true", "false"))); + super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); } @Override @@ -35,6 +35,6 @@ public class SkipSleepConfig extends AbstractBotConfig { @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBoolean(NAME)); + this.setValue(nbt.getBoolean(NAME).orElseThrow()); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java index a5acc7ef..6d9840ea 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java @@ -16,7 +16,7 @@ public class SpawnPhantomConfig extends AbstractBotConfig { private boolean value; public SpawnPhantomConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setTabComplete(0, List.of("true", "false"))); + super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); this.value = LeavesConfig.modify.fakeplayer.canSpawnPhantom; } @@ -47,6 +47,6 @@ public class SpawnPhantomConfig extends AbstractBotConfig { @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBoolean(NAME)); + this.setValue(nbt.getBoolean(NAME).orElseThrow()); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java index 5ed4cfb5..66af8e40 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java @@ -18,7 +18,7 @@ public class TickTypeConfig extends AbstractBotConfig { private ServerBot.TickType value; public TickTypeConfig() { - super(NAME, CommandArgument.of(TICK_TYPE_ARGUMENT).setTabComplete(0, List.of("network", "entity_list"))); + super(NAME, CommandArgument.of(TICK_TYPE_ARGUMENT).setSuggestion(0, List.of("network", "entity_list"))); this.value = LeavesConfig.modify.fakeplayer.tickType; } @@ -42,6 +42,6 @@ public class TickTypeConfig extends AbstractBotConfig { @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(TICK_TYPE_ARGUMENT.parse(nbt.getString(NAME))); + this.setValue(TICK_TYPE_ARGUMENT.parse(nbt.getString(NAME).orElseThrow())); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java index 95eb4f5d..af98d824 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java @@ -1,6 +1,10 @@ package org.leavesmc.leaves.bot.subcommands; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.kyori.adventure.text.format.NamedTextColor; +import net.minecraft.network.chat.Component; +import org.apache.commons.lang3.tuple.Pair; import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.craftbukkit.entity.CraftPlayer; @@ -18,6 +22,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.CompletableFuture; import static net.kyori.adventure.text.Component.text; @@ -165,10 +170,7 @@ public class BotActionCommand implements LeavesSubcommand { list.add(String.valueOf(i)); } } else { - AbstractBotAction action = Actions.getForName(args[1]); - if (action != null) { - list.addAll(action.getArgument().tabComplete(args.length - 3)); - } + return Collections.singletonList("<" + args[1] + " not found>"); } } } @@ -176,6 +178,40 @@ public class BotActionCommand implements LeavesSubcommand { return list; } + @Override + public CompletableFuture tabSuggestion(CommandSender sender, String subCommand, String[] args, Location location, SuggestionsBuilder builder) { + if (!LeavesConfig.modify.fakeplayer.canUseAction) { + return null; + } + + if (args.length >= 3) { + if (args[1].equals("stop")) { + return null; + } + AbstractBotAction action = Actions.getForName(args[1]); + if (action != null) { + Pair, String> results = action.getArgument().suggestion(args.length - 3, sender, args[args.length - 1]); + + if (results == null || results.getLeft() == null) { + return builder.buildFuture(); + } + + builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); + for (String s : results.getLeft()) { + if (results.getRight() != null) { + builder.suggest(s, Component.literal(results.getRight())); + } else { + builder.suggest(s); + } + } + + return builder.buildFuture(); + } + } + + return null; + } + @Override public boolean tabCompletes() { return LeavesConfig.modify.fakeplayer.canUseAction; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java index 5141b5d0..aec1cb75 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java @@ -1,6 +1,10 @@ package org.leavesmc.leaves.bot.subcommands; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.kyori.adventure.text.format.NamedTextColor; +import net.minecraft.network.chat.Component; +import org.apache.commons.lang3.tuple.Pair; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.command.CommandSender; @@ -17,6 +21,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.concurrent.CompletableFuture; import static net.kyori.adventure.text.Component.text; @@ -90,12 +95,7 @@ public class BotConfigCommand implements LeavesSubcommand { } if (args.length >= 3) { - Configs config = Configs.getConfig(args[1]); - if (config != null) { - list.addAll(bot.getConfig(config).getArgument().tabComplete(args.length - 3)); - } else { - return Collections.singletonList("<" + args[1] + " not found>"); - } + return Collections.singletonList("<" + args[1] + " not found>"); } } } @@ -103,6 +103,43 @@ public class BotConfigCommand implements LeavesSubcommand { return list; } + @Override + public CompletableFuture tabSuggestion(CommandSender sender, String subCommand, String[] args, Location location, SuggestionsBuilder builder) { + if (!LeavesConfig.modify.fakeplayer.canModifyConfig) { + return null; + } + + if (args.length >= 3) { + ServerBot bot = BotList.INSTANCE.getBotByName(args[0]); + if (bot == null) { + return null; + } + + Configs config = Configs.getConfig(args[1]); + if (config != null) { + AbstractBotConfig botConfig = bot.getConfig(config); + Pair, String> results = botConfig.getArgument().suggestion(args.length - 3, sender, args[args.length - 1]); + + if (results == null || results.getLeft() == null) { + return builder.buildFuture(); + } + + builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); + for (String s : results.getLeft()) { + if (results.getRight() != null) { + builder.suggest(s, Component.literal(results.getRight())); + } else { + builder.suggest(s); + } + } + + return builder.buildFuture(); + } + } + + return null; + } + @Override public boolean tabCompletes() { return LeavesConfig.modify.fakeplayer.canModifyConfig; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java index 4ef82bbb..57eacbe0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java @@ -12,6 +12,7 @@ import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.bot.BotCreateState; import org.leavesmc.leaves.bot.BotList; +import org.leavesmc.leaves.bot.BotUtil; import org.leavesmc.leaves.command.LeavesSubcommand; import org.leavesmc.leaves.event.bot.BotCreateEvent; @@ -30,7 +31,8 @@ public class BotCreateCommand implements LeavesSubcommand { } String botName = args[0]; - if (this.canCreate(sender, botName)) { + String fullName = BotUtil.getFullName(botName); + if (this.canCreate(sender, fullName)) { BotCreateState.Builder builder = BotCreateState.builder(botName, Bukkit.getWorlds().getFirst().getSpawnLocation()).createReason(BotCreateEvent.CreateReason.COMMAND).creator(sender); if (args.length >= 2) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java index 1b35fa43..4809654b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java @@ -50,7 +50,7 @@ public class BotLoadCommand implements LeavesSubcommand { BotList botList = BotList.INSTANCE; if (args.length <= 1) { - list.addAll(botList.getSavedBotList().getAllKeys()); + list.addAll(botList.getSavedBotList().keySet()); } return list; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/SimpleBytebufManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/SimpleBytebufManager.java index 443f7f6e..87388491 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/SimpleBytebufManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/SimpleBytebufManager.java @@ -13,11 +13,13 @@ public class SimpleBytebufManager implements BytebufManager { this.internal = internal; } + @SuppressWarnings("deprecation") @Override public void registerListener(Plugin plugin, PacketListener listener) { internal.listenerMap.put(listener, plugin); } + @SuppressWarnings("deprecation") @Override public void unregisterListener(Plugin plugin, PacketListener listener) { internal.listenerMap.remove(listener); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/WrappedBytebuf.java b/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/WrappedBytebuf.java index e9b185b6..0c32c205 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/WrappedBytebuf.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/WrappedBytebuf.java @@ -270,6 +270,11 @@ public class WrappedBytebuf implements Bytebuf { return new WrappedBytebuf(this.buf.copy()); } + @Override + public void retain() { + this.buf.retain(); + } + @Override public boolean release() { return this.buf.release(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/internal/InternalBytebufHandler.java b/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/internal/InternalBytebufHandler.java index a3b35500..eba0cc48 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/internal/InternalBytebufHandler.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bytebuf/internal/InternalBytebufHandler.java @@ -31,10 +31,12 @@ import org.leavesmc.leaves.bytebuf.packet.PacketType; import java.lang.reflect.Field; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.leavesmc.leaves.bytebuf.packet.PacketType.*; +@SuppressWarnings({"deprecation", "rawtypes", "unchecked"}) public class InternalBytebufHandler { private class PacketHandler extends ChannelDuplexHandler { @@ -87,6 +89,17 @@ public class InternalBytebufHandler { } } + private static final List PACKET_PACKAGES = List.of( + "net.minecraft.network.protocol.common", + "net.minecraft.network.protocol.configuration", + "net.minecraft.network.protocol.cookie", + "net.minecraft.network.protocol.game", + "net.minecraft.network.protocol.handshake", + "net.minecraft.network.protocol.login", + "net.minecraft.network.protocol.ping", + "net.minecraft.network.protocol.status" + ); + public final Map listenerMap = new HashMap<>(); private final BytebufManager manager = new SimpleBytebufManager(this); private final ImmutableMap type2CodecMap; @@ -94,26 +107,18 @@ public class InternalBytebufHandler { public InternalBytebufHandler() { ImmutableMap.Builder builder = ImmutableMap.builder(); + for (PacketType packet : PacketType.values()) { - Class packetClass; - try { - packetClass = Class.forName("net.minecraft.network.protocol.game." + packet.name() + "Packet"); - } catch (ClassNotFoundException e) { + String className = packet.name() + "Packet"; + for (String basePackage : PACKET_PACKAGES) { try { - packetClass = Class.forName("net.minecraft.network.protocol.common." + packet.name() + "Packet"); - } catch (ClassNotFoundException e2) { - try { - packetClass = Class.forName("net.minecraft.network.protocol.ping." + packet.name() + "Packet"); - } catch (ClassNotFoundException ignored) { - continue; - } + Class packetClass = Class.forName(basePackage + "." + className); + Field field = packetClass.getDeclaredField("STREAM_CODEC"); + field.setAccessible(true); + builder.put(packet, (StreamCodec) field.get(null)); + } catch (Exception ignored) { } } - try { - Field field = packetClass.getDeclaredField("STREAM_CODEC"); - builder.put(packet, (StreamCodec>) field.get(null)); - } catch (Exception ignored) { - } } builder.put(ClientboundMoveEntityPos, ClientboundMoveEntityPacket.Pos.STREAM_CODEC); @@ -232,4 +237,4 @@ public class InternalBytebufHandler { codec.encode(buf, nmsPacket); return new Packet(type, new WrappedBytebuf(buf)); } -} +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java index 2e45a3b2..bc0c3dca 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java @@ -1,23 +1,29 @@ package org.leavesmc.leaves.command; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.BiFunction; public class CommandArgument { public static final CommandArgument EMPTY = new CommandArgument(); + private static final Pair, String> EMPTY_SUGGESTION_RESULT = Pair.of(List.of(), null); + private static final BiFunction, String>> EMPTY_SUGGESTION = (sender, arg) -> EMPTY_SUGGESTION_RESULT; + + private final List, String>>> suggestions; private final List> argumentTypes; - private final List> tabComplete; private CommandArgument(CommandArgumentType... argumentTypes) { this.argumentTypes = List.of(argumentTypes); - this.tabComplete = new ArrayList<>(); + this.suggestions = new ArrayList<>(); for (int i = 0; i < argumentTypes.length; i++) { - tabComplete.add(new ArrayList<>()); + suggestions.add(EMPTY_SUGGESTION); } } @@ -25,29 +31,31 @@ public class CommandArgument { return new CommandArgument(argumentTypes); } - public List tabComplete(int n) { - if (tabComplete.size() > n) { - return tabComplete.get(n); - } else { - return List.of(); - } - } - - public CommandArgument setTabComplete(int index, List list) { - tabComplete.set(index, list); - return this; - } - - public CommandArgument setAllTabComplete(List> tabComplete) { - this.tabComplete.clear(); - this.tabComplete.addAll(tabComplete); - return this; - } - public List> getArgumentTypes() { return argumentTypes; } + public CommandArgument setSuggestion(int n, BiFunction, String>> suggestion) { + this.suggestions.set(n, suggestion); + return this; + } + + public CommandArgument setSuggestion(int n, Pair, String> suggestion) { + return this.setSuggestion(n, (sender, arg) -> suggestion); + } + + public CommandArgument setSuggestion(int n, List tabComplete) { + return this.setSuggestion(n, Pair.of(tabComplete, null)); + } + + public Pair, String> suggestion(int n, CommandSender sender, String arg) { + if (suggestions.size() > n) { + return suggestions.get(n).apply(sender, arg); + } else { + return EMPTY_SUGGESTION.apply(sender, arg); + } + } + public CommandArgumentResult parse(int index, String @NotNull [] args) { Object[] result = new Object[argumentTypes.size()]; Arrays.fill(result, null); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java index c687f343..7ef85249 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java @@ -14,7 +14,12 @@ import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.PluginManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.command.subcommands.*; +import org.leavesmc.leaves.command.subcommands.ConfigCommand; +import org.leavesmc.leaves.command.subcommands.CounterCommand; +import org.leavesmc.leaves.command.subcommands.PeacefulModeSwitchCommand; +import org.leavesmc.leaves.command.subcommands.ReloadCommand; +import org.leavesmc.leaves.command.subcommands.ReportCommand; +import org.leavesmc.leaves.command.subcommands.UpdateCommand; import java.util.ArrayList; import java.util.Arrays; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java index 40fb2fd0..bb865157 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java @@ -15,7 +15,6 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; @@ -57,22 +56,15 @@ public class LeavesCommandUtil { ArrayList results = Lists.newArrayList(); if (!collection.isEmpty()) { - Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator(); - - while (iterator.hasNext()) { - String s1 = (String) iterator.next(); + for (String s1 : Iterables.transform(collection, Functions.toStringFunction())) { if (matches(last, s1) && (sender.hasPermission(basePermission + s1) || sender.hasPermission(overridePermission))) { results.add(s1); } } if (results.isEmpty()) { - iterator = collection.iterator(); - - while (iterator.hasNext()) { - Object object = iterator.next(); - + for (Object object : collection) { if (object instanceof ResourceLocation && matches(last, ((ResourceLocation) object).getPath())) { results.add(String.valueOf(object)); } @@ -122,6 +114,7 @@ public class LeavesCommandUtil { } // Copy from org/bukkit/command/defaults/HelpCommand.java + /** * Computes the Dameraur-Levenshtein Distance between two strings. Adapted * from the algorithm at Wikipedia: Damerau–Levenshtein distance diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/NoBlockUpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/NoBlockUpdateCommand.java index fffcac8c..7593a046 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/NoBlockUpdateCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/NoBlockUpdateCommand.java @@ -14,6 +14,7 @@ import org.leavesmc.leaves.LeavesConfig; import java.util.List; +// TODO merge to /leaves blockupdate public class NoBlockUpdateCommand extends Command { private static boolean noBlockUpdate = false; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/config/InternalConfigProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/config/InternalConfigProvider.java new file mode 100644 index 00000000..eabe9ffb --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/config/InternalConfigProvider.java @@ -0,0 +1,14 @@ +package org.leavesmc.leaves.config; + +public class InternalConfigProvider implements LeavesConfigProvider { + + public static final InternalConfigProvider INSTANCE = new InternalConfigProvider(); + + public LeavesConfigValue getConfig(String configNode) { + return new LeavesConfigValue(GlobalConfigManager.getVerifiedConfig(configNode).get()); + } + + public void setConfig(String configNode, LeavesConfigValue configValue) { + GlobalConfigManager.getVerifiedConfig(configNode); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/CraftBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/CraftBot.java index 6f2054b9..de52608d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/CraftBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/CraftBot.java @@ -72,7 +72,7 @@ public class CraftBot extends CraftPlayer implements Bot { } @Override - public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) { + public boolean teleport(Location location, PlayerTeleportEvent.@NotNull TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) { Preconditions.checkArgument(location != null, "location cannot be null"); Preconditions.checkState(location.getWorld().equals(this.getWorld()), "[Leaves] Fakeplayers do not support changing world, Please use leaves fakeplayer-api instead!"); return super.teleport(location, cause, flags); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/CraftBotManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/CraftBotManager.java index ee9b7708..d4e0a28a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/CraftBotManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/CraftBotManager.java @@ -26,12 +26,7 @@ public class CraftBotManager implements BotManager { public CraftBotManager() { this.botList = MinecraftServer.getServer().getBotList(); - this.botViews = Collections.unmodifiableList(Lists.transform(botList.bots, new Function() { - @Override - public CraftBot apply(ServerBot bot) { - return bot.getBukkitEntity(); - } - })); + this.botViews = Collections.unmodifiableList(Lists.transform(botList.bots, bot -> bot.getBukkitEntity())); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java new file mode 100644 index 00000000..a2d2c6e5 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/plugin/ServerFeatureManager.java @@ -0,0 +1,32 @@ +// This file is licensed under the MIT license. +package org.leavesmc.leaves.plugin; + +import java.util.HashSet; +import java.util.Set; + +import static org.leavesmc.leaves.plugin.Features.*; + +public class ServerFeatureManager implements FeatureManager { + public static ServerFeatureManager INSTANCE = new ServerFeatureManager(); + private final Set availableFeatures = new HashSet<>(); + + private ServerFeatureManager() { + availableFeatures.addAll(Set.of( + FAKEPLAYER, + PHOTOGRAPHER + )); + if (Boolean.getBoolean("leavesclip.enable.mixin")) { + availableFeatures.add(MIXIN); + } + } + + @Override + public Set getAvailableFeatures() { + return availableFeatures; + } + + @Override + public boolean isFeatureAvailable(String feature) { + return availableFeatures.contains(feature); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/FeaturesConfiguration.java b/leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/FeaturesConfiguration.java new file mode 100644 index 00000000..93ab67bc --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/FeaturesConfiguration.java @@ -0,0 +1,21 @@ +// This file is licensed under the MIT license. +package org.leavesmc.leaves.plugin.provider.configuration; + +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +import java.util.List; + +@SuppressWarnings("FieldMayBeFinal") +@ConfigSerializable +public class FeaturesConfiguration { + private List required = List.of(); + private List optional = List.of(); + + public List getRequired() { + return required; + } + + public List getOptional() { + return optional; + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/LeavesPluginMeta.java b/leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/LeavesPluginMeta.java index ae803e42..be84c598 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/LeavesPluginMeta.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/LeavesPluginMeta.java @@ -1,3 +1,4 @@ +// This file is licensed under the MIT license. package org.leavesmc.leaves.plugin.provider.configuration; import com.google.common.collect.ImmutableList; @@ -11,9 +12,10 @@ import io.papermc.paper.plugin.provider.configuration.serializer.PermissionConfi import io.papermc.paper.plugin.provider.configuration.serializer.constraints.PluginConfigConstraints; import io.papermc.paper.plugin.provider.configuration.type.PermissionConfiguration; import org.bukkit.craftbukkit.util.ApiVersion; -import org.spongepowered.configurate.CommentedConfigurationNode; +import org.jetbrains.annotations.NotNull; import org.spongepowered.configurate.ConfigurateException; -import org.spongepowered.configurate.hocon.HoconConfigurationLoader; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.gson.GsonConfigurationLoader; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.ObjectMapper; import org.spongepowered.configurate.serialize.ScalarSerializer; @@ -21,25 +23,23 @@ import org.spongepowered.configurate.serialize.SerializationException; import java.io.BufferedReader; import java.lang.reflect.Type; -import java.util.List; import java.util.function.Predicate; +@SuppressWarnings("FieldMayBeFinal") @ConfigSerializable public class LeavesPluginMeta extends PaperPluginMeta { - private List mixins; - static final ApiVersion MINIMUM = ApiVersion.getOrCreateVersion("1.21"); + private FeaturesConfiguration features = new FeaturesConfiguration(); + private MixinConfiguration mixin = new MixinConfiguration(); + static final ApiVersion MINIMUM = ApiVersion.getOrCreateVersion("1.21.4"); public static LeavesPluginMeta create(BufferedReader reader) throws ConfigurateException { - HoconConfigurationLoader loader = HoconConfigurationLoader.builder() - .prettyPrinting(true) - .emitComments(true) - .emitJsonCompatible(true) + GsonConfigurationLoader loader = GsonConfigurationLoader.builder() .source(() -> reader) .defaultOptions((options) -> options.serializers((serializers) -> serializers.register(new ScalarSerializer<>(ApiVersion.class) { @Override - public ApiVersion deserialize(final Type type, final Object obj) throws SerializationException { + public ApiVersion deserialize(final @NotNull Type type, final @NotNull Object obj) throws SerializationException { try { final ApiVersion version = ApiVersion.getOrCreateVersion(obj.toString()); if (version.isOlderThan(MINIMUM)) { @@ -52,7 +52,7 @@ public class LeavesPluginMeta extends PaperPluginMeta { } @Override - protected Object serialize(final ApiVersion item, final Predicate> typeSupported) { + protected @NotNull Object serialize(final ApiVersion item, final @NotNull Predicate> typeSupported) { return item.getVersionString(); } }) @@ -70,21 +70,30 @@ public class LeavesPluginMeta extends PaperPluginMeta { ) ) .build(); - CommentedConfigurationNode node = loader.load(); + ConfigurationNode node = loader.load(); LegacyPaperMeta.migrate(node); LeavesPluginMeta pluginConfiguration = node.require(LeavesPluginMeta.class); - if (!node.node("author").virtual()) { - pluginConfiguration.authors = ImmutableList.builder() + var authorNode = node.node("author"); + if (!authorNode.virtual()) { + String author = authorNode.getString(); + var authorsBuilder = ImmutableList.builder(); + if (author != null) { + authorsBuilder.add(author); + } + pluginConfiguration.authors = authorsBuilder .addAll(pluginConfiguration.authors) - .add(node.node("author").getString()) .build(); } return pluginConfiguration; } - public List getMixins() { - return mixins; + public FeaturesConfiguration getFeatures() { + return features; + } + + public MixinConfiguration getMixin() { + return mixin; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/MixinConfiguration.java b/leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/MixinConfiguration.java new file mode 100644 index 00000000..16462465 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/plugin/provider/configuration/MixinConfiguration.java @@ -0,0 +1,35 @@ +// This file is licensed under the MIT license. +package org.leavesmc.leaves.plugin.provider.configuration; + +import org.spongepowered.configurate.objectmapping.ConfigSerializable; +import org.spongepowered.configurate.objectmapping.meta.PostProcess; + +import java.util.List; + +@SuppressWarnings({"FieldMayBeFinal", "unused"}) +@ConfigSerializable +public class MixinConfiguration { + private String packageName; + private List mixins = List.of(); + private String accessWidener; + + @PostProcess + public void postProcess() { + if (mixins.isEmpty()) return; + if (packageName == null) { + throw new IllegalStateException("Already define mixins: " + mixins + ", but no mixin package-name provided"); + } + } + + public List getMixins() { + return mixins; + } + + public String getAccessWidener() { + return accessWidener; + } + + public String getPackageName() { + return packageName; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java index 2368f0ca..c5691277 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java @@ -17,8 +17,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -@LeavesProtocol(namespace = "appleskin") -public class AppleSkinProtocol { +@LeavesProtocol.Register(namespace = "appleskin") +public class AppleSkinProtocol implements LeavesProtocol { public static final String PROTOCOL_ID = "appleskin"; @@ -41,64 +41,52 @@ public class AppleSkinProtocol { @ProtocolHandler.PlayerJoin public static void onPlayerLoggedIn(@NotNull ServerPlayer player) { - if (LeavesConfig.protocol.appleskin.enable) { - resetPlayerData(player); - } + resetPlayerData(player); } @ProtocolHandler.PlayerLeave public static void onPlayerLoggedOut(@NotNull ServerPlayer player) { - if (LeavesConfig.protocol.appleskin.enable) { - subscribedChannels.remove(player); - resetPlayerData(player); - } + subscribedChannels.remove(player); + resetPlayerData(player); } - @ProtocolHandler.MinecraftRegister(ignoreId = true) - public static void onPlayerSubscribed(@NotNull ServerPlayer player, String channel) { - if (LeavesConfig.protocol.appleskin.enable) { - subscribedChannels.computeIfAbsent(player, k -> new HashSet<>()).add(channel); - } + @ProtocolHandler.MinecraftRegister(onlyNamespace = true) + public static void onPlayerSubscribed(@NotNull ServerPlayer player, ResourceLocation id) { + subscribedChannels.computeIfAbsent(player, k -> new HashSet<>()).add(id.getPath()); } @ProtocolHandler.Ticker public static void tick() { - if (LeavesConfig.protocol.appleskin.enable) { - if (MinecraftServer.getServer().getTickCount() % LeavesConfig.protocol.appleskin.syncTickInterval != 0) { - return; - } + for (Map.Entry> entry : subscribedChannels.entrySet()) { + ServerPlayer player = entry.getKey(); + FoodData data = player.getFoodData(); - for (Map.Entry> entry : subscribedChannels.entrySet()) { - ServerPlayer player = entry.getKey(); - FoodData data = player.getFoodData(); - - for (String channel : entry.getValue()) { - switch (channel) { - case "saturation" -> { - float saturation = data.getSaturationLevel(); - Float previousSaturation = previousSaturationLevels.get(player); - if (previousSaturation == null || saturation != previousSaturation) { - ProtocolUtils.sendPayloadPacket(player, SATURATION_KEY, buf -> buf.writeFloat(saturation)); - previousSaturationLevels.put(player, saturation); - } + for (String channel : entry.getValue()) { + switch (channel) { + case "saturation" -> { + float saturation = data.getSaturationLevel(); + Float previousSaturation = previousSaturationLevels.get(player); + if (previousSaturation == null || saturation != previousSaturation) { + ProtocolUtils.sendBytebufPacket(player, SATURATION_KEY, buf -> buf.writeFloat(saturation)); + previousSaturationLevels.put(player, saturation); } + } - case "exhaustion" -> { - float exhaustion = data.exhaustionLevel; - Float previousExhaustion = previousExhaustionLevels.get(player); - if (previousExhaustion == null || Math.abs(exhaustion - previousExhaustion) >= MINIMUM_EXHAUSTION_CHANGE_THRESHOLD) { - ProtocolUtils.sendPayloadPacket(player, EXHAUSTION_KEY, buf -> buf.writeFloat(exhaustion)); - previousExhaustionLevels.put(player, exhaustion); - } + case "exhaustion" -> { + float exhaustion = data.exhaustionLevel; + Float previousExhaustion = previousExhaustionLevels.get(player); + if (previousExhaustion == null || Math.abs(exhaustion - previousExhaustion) >= MINIMUM_EXHAUSTION_CHANGE_THRESHOLD) { + ProtocolUtils.sendBytebufPacket(player, EXHAUSTION_KEY, buf -> buf.writeFloat(exhaustion)); + previousExhaustionLevels.put(player, exhaustion); } + } - case "natural_regeneration" -> { - boolean regeneration = player.serverLevel().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION); - Boolean previousRegeneration = previousNaturalRegeneration.get(player); - if (previousRegeneration == null || regeneration != previousRegeneration) { - ProtocolUtils.sendPayloadPacket(player, NATURAL_REGENERATION_KEY, buf -> buf.writeBoolean(regeneration)); - previousNaturalRegeneration.put(player, regeneration); - } + case "natural_regeneration" -> { + boolean regeneration = player.serverLevel().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION); + Boolean previousRegeneration = previousNaturalRegeneration.get(player); + if (previousRegeneration == null || regeneration != previousRegeneration) { + ProtocolUtils.sendBytebufPacket(player, NATURAL_REGENERATION_KEY, buf -> buf.writeBoolean(regeneration)); + previousNaturalRegeneration.put(player, regeneration); } } } @@ -108,9 +96,7 @@ public class AppleSkinProtocol { @ProtocolHandler.ReloadServer public static void onServerReload() { - if (!LeavesConfig.protocol.appleskin.enable) { - disableAllPlayer(); - } + disableAllPlayer(); } public static void disableAllPlayer() { @@ -124,4 +110,14 @@ public class AppleSkinProtocol { previousSaturationLevels.remove(player); previousNaturalRegeneration.remove(player); } + + @Override + public int tickerInterval(String tickerID) { + return LeavesConfig.protocol.appleskin.syncTickInterval; + } + + @Override + public boolean isActive() { + return LeavesConfig.protocol.appleskin.enable; + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java index 6da4b4bf..6dccdb29 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java @@ -27,10 +27,8 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; -import static org.leavesmc.leaves.protocol.core.LeavesProtocolManager.EmptyPayload; - -@LeavesProtocol(namespace = "bbor") -public class BBORProtocol { +@LeavesProtocol.Register(namespace = "bbor") +public class BBORProtocol implements LeavesProtocol { public static final String PROTOCOL_ID = "bbor"; @@ -43,6 +41,8 @@ public class BBORProtocol { private static final Map> playerBoundingBoxesCache = new HashMap<>(); private static final Map>> dimensionCache = new ConcurrentHashMap<>(); + private static boolean initialized = false; + @Contract("_ -> new") public static ResourceLocation id(String path) { return ResourceLocation.tryBuild(PROTOCOL_ID, path); @@ -50,10 +50,8 @@ public class BBORProtocol { @ProtocolHandler.Ticker public static void tick() { - if (LeavesConfig.protocol.bborProtocol) { - for (var playerEntry : players.entrySet()) { - sendBoundingToPlayer(playerEntry.getKey(), playerEntry.getValue()); - } + for (var playerEntry : players.entrySet()) { + sendBoundingToPlayer(playerEntry.getKey(), playerEntry.getValue()); } } @@ -68,50 +66,41 @@ public class BBORProtocol { @ProtocolHandler.PlayerJoin public static void onPlayerLoggedIn(@NotNull ServerPlayer player) { - if (LeavesConfig.protocol.bborProtocol) { - ServerLevel overworld = MinecraftServer.getServer().overworld(); - ProtocolUtils.sendPayloadPacket(player, INITIALIZE_CLIENT, buf -> { - buf.writeLong(overworld.getSeed()); - buf.writeInt(overworld.levelData.getSpawnPos().getX()); - buf.writeInt(overworld.levelData.getSpawnPos().getZ()); - }); - sendStructureList(player); - } + ServerLevel overworld = MinecraftServer.getServer().overworld(); + ProtocolUtils.sendBytebufPacket(player, INITIALIZE_CLIENT, buf -> { + buf.writeLong(overworld.getSeed()); + buf.writeInt(overworld.levelData.getSpawnPos().getX()); + buf.writeInt(overworld.levelData.getSpawnPos().getZ()); + }); + sendStructureList(player); } @ProtocolHandler.PlayerLeave public static void onPlayerLoggedOut(@NotNull ServerPlayer player) { - if (LeavesConfig.protocol.bborProtocol) { - players.remove(player.getId()); - playerBoundingBoxesCache.remove(player.getId()); - } + players.remove(player.getId()); + playerBoundingBoxesCache.remove(player.getId()); } - @ProtocolHandler.PayloadReceiver(payload = EmptyPayload.class, payloadId = "subscribe") - public static void onPlayerSubscribed(@NotNull ServerPlayer player, EmptyPayload payload) { - if (LeavesConfig.protocol.bborProtocol) { - players.put(player.getId(), player); - sendBoundingToPlayer(player.getId(), player); - } + @ProtocolHandler.BytebufReceiver(key = "subscribe") + public static void onPlayerSubscribed(@NotNull ServerPlayer player, FriendlyByteBuf buf) { + players.put(player.getId(), player); + sendBoundingToPlayer(player.getId(), player); } + @ProtocolHandler.ReloadDataPack public static void onDataPackReload() { - if (LeavesConfig.protocol.bborProtocol) { - players.values().forEach(BBORProtocol::sendStructureList); - } + players.values().forEach(BBORProtocol::sendStructureList); } public static void onChunkLoaded(@NotNull LevelChunk chunk) { - if (LeavesConfig.protocol.bborProtocol) { - Map structures = new HashMap<>(); - final Registry structureFeatureRegistry = chunk.getLevel().registryAccess().lookupOrThrow(Registries.STRUCTURE); - for (var es : chunk.getAllStarts().entrySet()) { - final var optional = structureFeatureRegistry.getResourceKey(es.getKey()); - optional.ifPresent(key -> structures.put(key.location().toString(), es.getValue())); - } - if (!structures.isEmpty()) { - onStructuresLoaded(chunk.getLevel().dimension().location(), structures); - } + Map structures = new HashMap<>(); + final Registry structureFeatureRegistry = chunk.getLevel().registryAccess().lookupOrThrow(Registries.STRUCTURE); + for (var es : chunk.getAllStarts().entrySet()) { + final var optional = structureFeatureRegistry.getResourceKey(es.getKey()); + optional.ifPresent(key -> structures.put(key.location().toString(), es.getValue())); + } + if (!structures.isEmpty()) { + onStructuresLoaded(chunk.getLevel().dimension().location(), structures); } } @@ -148,7 +137,7 @@ public class BBORProtocol { final Registry structureRegistry = player.server.registryAccess().lookupOrThrow(Registries.STRUCTURE); final Set structureIds = structureRegistry.entrySet().stream() .map(e -> e.getKey().location().toString()).collect(Collectors.toSet()); - ProtocolUtils.sendPayloadPacket(player, STRUCTURE_LIST_SYNC, buf -> { + ProtocolUtils.sendBytebufPacket(player, STRUCTURE_LIST_SYNC, buf -> { buf.writeVarInt(structureIds.size()); structureIds.forEach(buf::writeUtf); }); @@ -168,7 +157,7 @@ public class BBORProtocol { } Set boundingBoxes = boundingBoxMap.get(key); - ProtocolUtils.sendPayloadPacket(player, ADD_BOUNDING_BOX, buf -> { + ProtocolUtils.sendBytebufPacket(player, ADD_BOUNDING_BOX, buf -> { buf.writeResourceLocation(entry.getKey()); key.serialize(buf); if (boundingBoxes != null && boundingBoxes.size() > 1) { @@ -186,6 +175,7 @@ public class BBORProtocol { for (ServerPlayer player : MinecraftServer.getServer().getPlayerList().getPlayers()) { onPlayerLoggedIn(player); } + initialized = true; } public static void loggedOutAllPlayer() { @@ -201,8 +191,27 @@ public class BBORProtocol { return dimensionCache.computeIfAbsent(dimensionId, dt -> new ConcurrentHashMap<>()); } + @Override + public boolean isActive() { + boolean active = LeavesConfig.protocol.bborProtocol; + if (!active && initialized) { + initialized = false; + loggedOutAllPlayer(); + } + return active; + } + private record BBoundingBox(String type, BlockPos min, BlockPos max) { + private static int combineHashCodes(int @NotNull ... hashCodes) { + final int prime = 31; + int result = 0; + for (int hashCode : hashCodes) { + result = prime * result + hashCode; + } + return result; + } + public void serialize(@NotNull FriendlyByteBuf buf) { buf.writeChar('S'); buf.writeInt(type.hashCode()); @@ -214,14 +223,5 @@ public class BBORProtocol { public int hashCode() { return combineHashCodes(min.hashCode(), max.hashCode()); } - - private static int combineHashCodes(int @NotNull ... hashCodes) { - final int prime = 31; - int result = 0; - for (int hashCode : hashCodes) { - result = prime * result + hashCode; - } - return result; - } } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/CarpetServerProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/CarpetServerProtocol.java index 5186d381..9f7fad36 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/CarpetServerProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/CarpetServerProtocol.java @@ -2,6 +2,8 @@ package org.leavesmc.leaves.protocol; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import org.jetbrains.annotations.Contract; @@ -17,14 +19,12 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -@LeavesProtocol(namespace = "carpet") -public class CarpetServerProtocol { +@LeavesProtocol.Register(namespace = "carpet") +public class CarpetServerProtocol implements LeavesProtocol { public static final String PROTOCOL_ID = "carpet"; public static final String VERSION = ProtocolUtils.buildProtocolVersion(PROTOCOL_ID); - private static final ResourceLocation HELLO_ID = CarpetServerProtocol.id("hello"); - private static final String HI = "69"; private static final String HELLO = "420"; @@ -42,7 +42,7 @@ public class CarpetServerProtocol { } } - @ProtocolHandler.PayloadReceiver(payload = CarpetPayload.class, payloadId = "hello") + @ProtocolHandler.PayloadReceiver(payload = CarpetPayload.class) private static void handleHello(@NotNull ServerPlayer player, @NotNull CarpetServerProtocol.CarpetPayload payload) { if (LeavesConfig.protocol.leavesCarpetSupport) { if (payload.nbt.contains(HELLO)) { @@ -54,6 +54,11 @@ public class CarpetServerProtocol { } } + @Override + public boolean isActive() { + return false; + } + public static class CarpetRules { private static final Map rules = new HashMap<>(); @@ -99,22 +104,13 @@ public class CarpetServerProtocol { } } - public record CarpetPayload(CompoundTag nbt) implements LeavesCustomPayload { + public record CarpetPayload(CompoundTag nbt) implements LeavesCustomPayload { + @ID + private static final ResourceLocation HELLO_ID = CarpetServerProtocol.id("hello"); - @New - public CarpetPayload(ResourceLocation location, FriendlyByteBuf buf) { - this(buf.readNbt()); - } - - @Override - public void write(FriendlyByteBuf buf) { - buf.writeNbt(nbt); - } - - @Override - @NotNull - public ResourceLocation id() { - return HELLO_ID; - } + @Codec + private static final StreamCodec CODEC = StreamCodec.composite( + ByteBufCodecs.COMPOUND_TAG, CarpetPayload::nbt, CarpetPayload::new + ); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/LMSPasterProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/LMSPasterProtocol.java index 03c45db2..1c535dd3 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/LMSPasterProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/LMSPasterProtocol.java @@ -3,6 +3,8 @@ package org.leavesmc.leaves.protocol; import com.google.common.collect.Sets; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; @@ -22,39 +24,33 @@ import java.util.Set; import java.util.WeakHashMap; import java.util.function.Consumer; -@LeavesProtocol(namespace = "litematica-server-paster") -public class LMSPasterProtocol { +@LeavesProtocol.Register(namespace = "litematica-server-paster") +public class LMSPasterProtocol implements LeavesProtocol { public static final String MOD_ID = "litematica-server-paster"; public static final String MOD_VERSION = "1.3.5"; - private static final ResourceLocation PACKET_ID = ResourceLocation.fromNamespaceAndPath(MOD_ID, "network_v2"); - private static final Map VERY_LONG_CHATS = new WeakHashMap<>(); - @ProtocolHandler.PayloadReceiver(payload = LmsPasterPayload.class, payloadId = "network_v2") + @ProtocolHandler.PayloadReceiver(payload = LmsPasterPayload.class) public static void handlePackets(ServerPlayer player, LmsPasterPayload payload) { - if (!LeavesConfig.protocol.lmsPasterProtocol) { - return; - } - String playerName = player.getName().getString(); - int id = payload.getPacketId(); - CompoundTag nbt = payload.getNbt(); + int id = payload.id(); + CompoundTag nbt = payload.nbt(); switch (id) { case LMSPasterProtocol.C2S.HI -> { - String clientModVersion = nbt.getString("mod_version"); + String clientModVersion = nbt.getString("mod_version").orElseThrow(); LeavesLogger.LOGGER.info(String.format("Player %s connected with %s @ %s", playerName, LMSPasterProtocol.MOD_ID, clientModVersion)); ProtocolUtils.sendPayloadPacket(player, LMSPasterProtocol.S2C.build(LMSPasterProtocol.S2C.HI, nbt2 -> nbt2.putString("mod_version", LMSPasterProtocol.MOD_VERSION))); ProtocolUtils.sendPayloadPacket(player, LMSPasterProtocol.S2C.build(LMSPasterProtocol.S2C.ACCEPT_PACKETS, nbt2 -> nbt2.putIntArray("ids", C2S.ALL_PACKET_IDS))); } case LMSPasterProtocol.C2S.CHAT -> { - String message = nbt.getString("chat"); + String message = nbt.getString("chat").orElseThrow(); triggerCommand(player, playerName, message); } case LMSPasterProtocol.C2S.VERY_LONG_CHAT_START -> VERY_LONG_CHATS.put(player.connection, new StringBuilder()); case LMSPasterProtocol.C2S.VERY_LONG_CHAT_CONTENT -> { - String segment = nbt.getString("segment"); + String segment = nbt.getString("segment").orElseThrow(); getVeryLongChatBuilder(player).ifPresent(builder -> builder.append(segment)); } case LMSPasterProtocol.C2S.VERY_LONG_CHAT_END -> { @@ -76,6 +72,11 @@ public class LMSPasterProtocol { } } + @Override + public boolean isActive() { + return LeavesConfig.protocol.lmsPasterProtocol; + } + private static class C2S { public static final int HI = 0; public static final int CHAT = 1; @@ -115,36 +116,17 @@ public class LMSPasterProtocol { } } - public static class LmsPasterPayload implements LeavesCustomPayload { - private final int id; - private final CompoundTag nbt; + public record LmsPasterPayload(int id, CompoundTag nbt) implements LeavesCustomPayload { + @ID + private static final ResourceLocation PACKET_ID = ResourceLocation.fromNamespaceAndPath(MOD_ID, "network_v2"); - public LmsPasterPayload(int id, CompoundTag nbt) { - this.id = id; - this.nbt = nbt; - } - - @New - public LmsPasterPayload(ResourceLocation location, FriendlyByteBuf buf) { - this(buf.readVarInt(), buf.readNbt()); - } - - public void write(FriendlyByteBuf buf) { - buf.writeVarInt(this.id); - buf.writeNbt(this.nbt); - } - - @Override - public ResourceLocation id() { - return PACKET_ID; - } - - public int getPacketId() { - return this.id; - } - - public CompoundTag getNbt() { - return this.nbt; - } + @Codec + private static final StreamCodec CODEC = StreamCodec.composite( + ByteBufCodecs.VAR_INT, + LmsPasterPayload::id, + ByteBufCodecs.COMPOUND_TAG, + LmsPasterPayload::nbt, + LmsPasterPayload::new + ); } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/PcaSyncProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/PcaSyncProtocol.java index fd71036f..616bed04 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/PcaSyncProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/PcaSyncProtocol.java @@ -3,6 +3,8 @@ package org.leavesmc.leaves.protocol; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; @@ -34,10 +36,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.locks.ReentrantLock; -import static org.leavesmc.leaves.protocol.core.LeavesProtocolManager.EmptyPayload; - -@LeavesProtocol(namespace = "pca") -public class PcaSyncProtocol { +@LeavesProtocol.Register(namespace = "pca") +public class PcaSyncProtocol implements LeavesProtocol { public static final String PROTOCOL_ID = "pca"; @@ -67,28 +67,18 @@ public class PcaSyncProtocol { } } - @ProtocolHandler.PayloadReceiver(payload = EmptyPayload.class, payloadId = "cancel_sync_block_entity") - private static void cancelSyncBlockEntityHandler(ServerPlayer player, EmptyPayload payload) { - if (!LeavesConfig.protocol.pca.enable) { - return; - } + @ProtocolHandler.BytebufReceiver(key = "cancel_sync_block_entity") + private static void cancelSyncBlockEntityHandler(ServerPlayer player, FriendlyByteBuf buf) { PcaSyncProtocol.clearPlayerWatchBlock(player); } - @ProtocolHandler.PayloadReceiver(payload = EmptyPayload.class, payloadId = "cancel_sync_entity") - private static void cancelSyncEntityHandler(ServerPlayer player, EmptyPayload payload) { - if (!LeavesConfig.protocol.pca.enable) { - return; - } + @ProtocolHandler.BytebufReceiver(key = "cancel_sync_entity") + private static void cancelSyncEntityHandler(ServerPlayer player, FriendlyByteBuf buf) { PcaSyncProtocol.clearPlayerWatchEntity(player); } - @ProtocolHandler.PayloadReceiver(payload = SyncBlockEntityPayload.class, payloadId = "sync_block_entity") + @ProtocolHandler.PayloadReceiver(payload = SyncBlockEntityPayload.class) private static void syncBlockEntityHandler(ServerPlayer player, SyncBlockEntityPayload payload) { - if (!LeavesConfig.protocol.pca.enable) { - return; - } - MinecraftServer server = MinecraftServer.getServer(); BlockPos pos = payload.pos; ServerLevel world = player.serverLevel(); @@ -127,12 +117,8 @@ public class PcaSyncProtocol { }); } - @ProtocolHandler.PayloadReceiver(payload = SyncEntityPayload.class, payloadId = "sync_entity") + @ProtocolHandler.PayloadReceiver(payload = SyncEntityPayload.class) private static void syncEntityHandler(ServerPlayer player, SyncEntityPayload payload) { - if (!LeavesConfig.protocol.pca.enable) { - return; - } - MinecraftServer server = MinecraftServer.getServer(); int entityId = payload.entityId; ServerLevel world = player.serverLevel(); @@ -154,12 +140,12 @@ public class PcaSyncProtocol { } } case OPS -> { - if (!(entity instanceof ServerBot) && server.getPlayerList().isOp(player.gameProfile)) { + if (!(entity instanceof ServerBot) && !server.getPlayerList().isOp(player.gameProfile)) { return; } } case OPS_AND_SELF -> { - if (!(entity instanceof ServerBot) && server.getPlayerList().isOp(player.gameProfile) && entity != player) { + if (!(entity instanceof ServerBot) && !server.getPlayerList().isOp(player.gameProfile) && entity != player) { return; } } @@ -191,13 +177,13 @@ public class PcaSyncProtocol { } public static void enablePcaSyncProtocol(@NotNull ServerPlayer player) { - ProtocolUtils.sendEmptyPayloadPacket(player, ENABLE_PCA_SYNC_PROTOCOL); + ProtocolUtils.sendEmptyPacket(player, ENABLE_PCA_SYNC_PROTOCOL); lock.lock(); lock.unlock(); } public static void disablePcaSyncProtocol(@NotNull ServerPlayer player) { - ProtocolUtils.sendEmptyPayloadPacket(player, DISABLE_PCA_SYNC_PROTOCOL); + ProtocolUtils.sendEmptyPacket(player, DISABLE_PCA_SYNC_PROTOCOL); } public static void updateEntity(@NotNull ServerPlayer player, @NotNull Entity entity) { @@ -347,87 +333,62 @@ public class PcaSyncProtocol { PcaSyncProtocol.clearPlayerWatchEntity(player); } - public record UpdateEntityPayload(ResourceLocation dimension, int entityId, CompoundTag tag) implements LeavesCustomPayload { + @Override + public boolean isActive() { + return LeavesConfig.protocol.pca.enable; + } + public record UpdateEntityPayload(ResourceLocation dimension, int entityId, CompoundTag tag) implements LeavesCustomPayload { + + @ID public static final ResourceLocation UPDATE_ENTITY = PcaSyncProtocol.id("update_entity"); - @New - public UpdateEntityPayload(ResourceLocation location, FriendlyByteBuf byteBuf) { - this(byteBuf.readResourceLocation(), byteBuf.readInt(), byteBuf.readNbt()); - } - - @Override - public void write(@NotNull FriendlyByteBuf buf) { - buf.writeResourceLocation(this.dimension); - buf.writeInt(this.entityId); - buf.writeNbt(this.tag); - } - - @Override - public ResourceLocation id() { - return UPDATE_ENTITY; - } + @Codec + public static final StreamCodec CODEC = StreamCodec.composite( + ResourceLocation.STREAM_CODEC, + UpdateEntityPayload::dimension, + ByteBufCodecs.INT, + UpdateEntityPayload::entityId, + ByteBufCodecs.COMPOUND_TAG, + UpdateEntityPayload::tag, + UpdateEntityPayload::new + ); } - public record UpdateBlockEntityPayload(ResourceLocation dimension, BlockPos blockPos, CompoundTag tag) implements LeavesCustomPayload { + public record UpdateBlockEntityPayload(ResourceLocation dimension, BlockPos blockPos, CompoundTag tag) implements LeavesCustomPayload { + @ID private static final ResourceLocation UPDATE_BLOCK_ENTITY = PcaSyncProtocol.id("update_block_entity"); - @New - public UpdateBlockEntityPayload(ResourceLocation location, @NotNull FriendlyByteBuf byteBuf) { - this(byteBuf.readResourceLocation(), byteBuf.readBlockPos(), byteBuf.readNbt()); - } - - @Override - public void write(@NotNull FriendlyByteBuf buf) { - buf.writeResourceLocation(this.dimension); - buf.writeBlockPos(this.blockPos); - buf.writeNbt(this.tag); - } - - @Override - public ResourceLocation id() { - return UPDATE_BLOCK_ENTITY; - } + @Codec + private static final StreamCodec CODEC = StreamCodec.composite( + ResourceLocation.STREAM_CODEC, + UpdateBlockEntityPayload::dimension, + BlockPos.STREAM_CODEC, + UpdateBlockEntityPayload::blockPos, + ByteBufCodecs.COMPOUND_TAG, + UpdateBlockEntityPayload::tag, + UpdateBlockEntityPayload::new + ); } - public record SyncBlockEntityPayload(BlockPos pos) implements LeavesCustomPayload { - + public record SyncBlockEntityPayload(BlockPos pos) implements LeavesCustomPayload { + @ID public static final ResourceLocation SYNC_BLOCK_ENTITY = PcaSyncProtocol.id("sync_block_entity"); - @New - public SyncBlockEntityPayload(ResourceLocation id, @NotNull FriendlyByteBuf buf) { - this(buf.readBlockPos()); - } - - @Override - public void write(@NotNull FriendlyByteBuf buf) { - buf.writeBlockPos(pos); - } - - @Override - public @NotNull ResourceLocation id() { - return SYNC_BLOCK_ENTITY; - } + @Codec + private static final StreamCodec CODEC = StreamCodec.composite( + BlockPos.STREAM_CODEC, SyncBlockEntityPayload::pos, SyncBlockEntityPayload::new + ); } - public record SyncEntityPayload(int entityId) implements LeavesCustomPayload { - + public record SyncEntityPayload(int entityId) implements LeavesCustomPayload { + @ID public static final ResourceLocation SYNC_ENTITY = PcaSyncProtocol.id("sync_entity"); - @New - public SyncEntityPayload(ResourceLocation id, @NotNull FriendlyByteBuf buf) { - this(buf.readInt()); - } - - @Override - public void write(@NotNull FriendlyByteBuf buf) { - buf.writeInt(entityId); - } - - @Override - public @NotNull ResourceLocation id() { - return SYNC_ENTITY; - } + @Codec + private static final StreamCodec CODEC = StreamCodec.composite( + ByteBufCodecs.INT, SyncEntityPayload::entityId, SyncEntityPayload::new + ); } -} +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java index 444c17df..75c8fcec 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java @@ -8,8 +8,8 @@ import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.protocol.core.LeavesProtocol; import org.leavesmc.leaves.protocol.core.ProtocolUtils; -@LeavesProtocol(namespace = {"xaerominimap", "xaeroworldmap"}) -public class XaeroMapProtocol { +@LeavesProtocol.Register(namespace = "xaerominimap_or_xaeroworldmap_i_dont_care") +public class XaeroMapProtocol implements LeavesProtocol { public static final String PROTOCOL_ID_MINI = "xaerominimap"; public static final String PROTOCOL_ID_WORLD = "xaeroworldmap"; @@ -29,14 +29,19 @@ public class XaeroMapProtocol { public static void onSendWorldInfo(@NotNull ServerPlayer player) { if (LeavesConfig.protocol.xaeroMapProtocol) { - ProtocolUtils.sendPayloadPacket(player, MINIMAP_KEY, buf -> { + ProtocolUtils.sendBytebufPacket(player, MINIMAP_KEY, buf -> { buf.writeByte(0); buf.writeInt(LeavesConfig.protocol.xaeroMapServerID); }); - ProtocolUtils.sendPayloadPacket(player, WORLDMAP_KEY, buf -> { + ProtocolUtils.sendBytebufPacket(player, WORLDMAP_KEY, buf -> { buf.writeByte(0); buf.writeInt(LeavesConfig.protocol.xaeroMapServerID); }); } } + + @Override + public boolean isActive() { + return LeavesConfig.protocol.xaeroMapProtocol; + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/bladeren/BladerenProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/bladeren/BladerenProtocol.java index 84b65fe5..2c773f2f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/bladeren/BladerenProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/bladeren/BladerenProtocol.java @@ -2,6 +2,7 @@ package org.leavesmc.leaves.protocol.bladeren; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import org.jetbrains.annotations.Contract; @@ -17,15 +18,12 @@ import java.util.HashMap; import java.util.Map; import java.util.function.BiConsumer; -@LeavesProtocol(namespace = "bladeren") -public class BladerenProtocol { +@LeavesProtocol.Register(namespace = "bladeren") +public class BladerenProtocol implements LeavesProtocol { public static final String PROTOCOL_ID = "bladeren"; public static final String PROTOCOL_VERSION = ProtocolUtils.buildProtocolVersion(PROTOCOL_ID); - private static final ResourceLocation HELLO_ID = id("hello"); - private static final ResourceLocation FEATURE_MODIFY_ID = id("feature_modify"); - private static final Map> registeredFeatures = new HashMap<>(); @Contract("_ -> new") @@ -33,50 +31,49 @@ public class BladerenProtocol { return ResourceLocation.tryBuild(PROTOCOL_ID, path); } - @ProtocolHandler.PayloadReceiver(payload = BladerenHelloPayload.class, payloadId = "hello") + @ProtocolHandler.PayloadReceiver(payload = BladerenHelloPayload.class) private static void handleHello(@NotNull ServerPlayer player, @NotNull BladerenHelloPayload payload) { - if (LeavesConfig.protocol.bladeren.enable) { - String clientVersion = payload.version; - CompoundTag tag = payload.nbt; + String clientVersion = payload.version; + CompoundTag tag = payload.nbt; - LeavesLogger.LOGGER.info("Player " + player.getScoreboardName() + " joined with bladeren " + clientVersion); + LeavesLogger.LOGGER.info("Player " + player.getScoreboardName() + " joined with bladeren " + clientVersion); - if (tag != null) { - CompoundTag featureNbt = tag.getCompound("Features"); - for (String name : featureNbt.getAllKeys()) { - if (registeredFeatures.containsKey(name)) { - registeredFeatures.get(name).accept(player, featureNbt.getCompound(name)); - } + if (tag != null) { + CompoundTag featureNbt = tag.getCompound("Features").orElseThrow(); + for (String name : featureNbt.keySet()) { + if (registeredFeatures.containsKey(name)) { + registeredFeatures.get(name).accept(player, featureNbt.getCompound(name).orElseThrow()); } } } } - @ProtocolHandler.PayloadReceiver(payload = BladerenFeatureModifyPayload.class, payloadId = "feature_modify") + @ProtocolHandler.PayloadReceiver(payload = BladerenFeatureModifyPayload.class) private static void handleModify(@NotNull ServerPlayer player, @NotNull BladerenFeatureModifyPayload payload) { - if (LeavesConfig.protocol.bladeren.enable) { - String name = payload.name; - CompoundTag tag = payload.nbt; + String name = payload.name; + CompoundTag tag = payload.nbt; - if (registeredFeatures.containsKey(name)) { - registeredFeatures.get(name).accept(player, tag); - } + if (registeredFeatures.containsKey(name)) { + registeredFeatures.get(name).accept(player, tag); } } @ProtocolHandler.PlayerJoin public static void onPlayerJoin(@NotNull ServerPlayer player) { - if (LeavesConfig.protocol.bladeren.enable) { - CompoundTag tag = new CompoundTag(); - LeavesFeatureSet.writeNBT(tag); - ProtocolUtils.sendPayloadPacket(player, new BladerenHelloPayload(PROTOCOL_VERSION, tag)); - } + CompoundTag tag = new CompoundTag(); + LeavesFeatureSet.writeNBT(tag); + ProtocolUtils.sendPayloadPacket(player, new BladerenHelloPayload(PROTOCOL_VERSION, tag)); } public static void registerFeature(String name, BiConsumer consumer) { registeredFeatures.put(name, consumer); } + @Override + public boolean isActive() { + return LeavesConfig.protocol.bladeren.enable; + } + public static class LeavesFeatureSet { private static final Map features = new HashMap<>(); @@ -108,43 +105,33 @@ public class BladerenProtocol { } } - public record BladerenFeatureModifyPayload(String name, CompoundTag nbt) implements LeavesCustomPayload { + public record BladerenFeatureModifyPayload(String name, CompoundTag nbt) implements LeavesCustomPayload { - @New - public BladerenFeatureModifyPayload(ResourceLocation location, FriendlyByteBuf buf) { - this(buf.readUtf(), buf.readNbt()); - } + @ID + private static final ResourceLocation FEATURE_MODIFY_ID = id("feature_modify"); - @Override - public void write(@NotNull FriendlyByteBuf buf) { - buf.writeUtf(name); - buf.writeNbt(nbt); - } - - @Override - @NotNull - public ResourceLocation id() { - return FEATURE_MODIFY_ID; - } + @Codec + private static final StreamCodec CODEC = StreamCodec.of( + (buf, payload) -> { + buf.writeUtf(payload.name()); + buf.writeNbt(payload.nbt()); + }, + buffer -> new BladerenFeatureModifyPayload(buffer.readUtf(), buffer.readNbt()) + ); } - public record BladerenHelloPayload(String version, CompoundTag nbt) implements LeavesCustomPayload { + public record BladerenHelloPayload(String version, CompoundTag nbt) implements LeavesCustomPayload { - @New - public BladerenHelloPayload(ResourceLocation location, @NotNull FriendlyByteBuf buf) { - this(buf.readUtf(64), buf.readNbt()); - } + @ID + private static final ResourceLocation HELLO_ID = id("hello"); - @Override - public void write(@NotNull FriendlyByteBuf buf) { - buf.writeUtf(version); - buf.writeNbt(nbt); - } - - @Override - @NotNull - public ResourceLocation id() { - return HELLO_ID; - } + @Codec + private static final StreamCodec CODEC = StreamCodec.of( + (buf, payload) -> { + buf.writeUtf(payload.version()); + buf.writeNbt(payload.nbt()); + }, + buffer -> new BladerenHelloPayload(buffer.readUtf(64), buffer.readNbt()) + ); } -} +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java index 347b7d9c..9368d188 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/bladeren/MsptSyncProtocol.java @@ -15,13 +15,11 @@ import java.util.Arrays; import java.util.List; import java.util.OptionalDouble; -@LeavesProtocol(namespace = "bladeren") -public class MsptSyncProtocol { +@LeavesProtocol.Register(namespace = "bladeren") +public class MsptSyncProtocol implements LeavesProtocol { public static final String PROTOCOL_ID = "bladeren"; - private static final ResourceLocation MSPT_SYNC = id("mspt_sync"); - private static final List players = new ArrayList<>(); @Contract("_ -> new") @@ -32,7 +30,7 @@ public class MsptSyncProtocol { @ProtocolHandler.Init public static void init() { BladerenProtocol.registerFeature("mspt_sync", (player, compoundTag) -> { - if (compoundTag.getString("Value").equals("true")) { + if (compoundTag.getStringOr("Value", "").equals("true")) { onPlayerSubmit(player); } else { onPlayerLoggedOut(player); @@ -42,36 +40,37 @@ public class MsptSyncProtocol { @ProtocolHandler.PlayerLeave public static void onPlayerLoggedOut(@NotNull ServerPlayer player) { - if (LeavesConfig.protocol.bladeren.msptSyncProtocol) { - players.remove(player); - } + players.remove(player); } @ProtocolHandler.Ticker public static void tick() { - if (LeavesConfig.protocol.bladeren.msptSyncProtocol) { - if (players.isEmpty()) { - return; - } - - MinecraftServer server = MinecraftServer.getServer(); - if (server.getTickCount() % LeavesConfig.protocol.bladeren.msptSyncTickInterval == 0) { - OptionalDouble msptArr = Arrays.stream(server.getTickTimesNanos()).average(); - if (msptArr.isPresent()) { - double mspt = msptArr.getAsDouble() * 1.0E-6D; - double tps = 1000.0D / Math.max(mspt, 50); - players.forEach(player -> ProtocolUtils.sendPayloadPacket(player, MSPT_SYNC, buf -> { - buf.writeDouble(mspt); - buf.writeDouble(tps); - })); - } - } + if (players.isEmpty()) { + return; + } + MinecraftServer server = MinecraftServer.getServer(); + OptionalDouble msptArr = Arrays.stream(server.getTickTimesNanos()).average(); + if (msptArr.isPresent()) { + double mspt = msptArr.getAsDouble() * 1.0E-6D; + double tps = 1000.0D / Math.max(mspt, 50); + players.forEach(player -> ProtocolUtils.sendBytebufPacket(player, MSPT_SYNC, buf -> { + buf.writeDouble(mspt); + buf.writeDouble(tps); + })); } } public static void onPlayerSubmit(@NotNull ServerPlayer player) { - if (LeavesConfig.protocol.bladeren.msptSyncProtocol) { - players.add(player); - } + players.add(player); + } + + @Override + public int tickerInterval(String tickerID) { + return LeavesConfig.protocol.bladeren.msptSyncTickInterval; + } + + @Override + public boolean isActive() { + return LeavesConfig.protocol.bladeren.msptSyncProtocol; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageIndex.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageIndex.java deleted file mode 100644 index 26eca28c..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageIndex.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.leavesmc.leaves.protocol.chatimage; - -public class ChatImageIndex { - - public int index; - public int total; - public String url; - public String bytes; - - public ChatImageIndex(int index, int total, String url, String bytes) { - this.index = index; - this.total = total; - this.url = url; - this.bytes = bytes; - } -} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageProtocol.java index ecbc7e1b..2985e993 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageProtocol.java @@ -16,8 +16,8 @@ import java.util.UUID; import static org.leavesmc.leaves.protocol.chatimage.ServerBlockCache.SERVER_BLOCK_CACHE; -@LeavesProtocol(namespace = "chatimage") -public class ChatImageProtocol { +@LeavesProtocol.Register(namespace = "chatimage") +public class ChatImageProtocol implements LeavesProtocol { public static final String PROTOCOL_ID = "chatimage"; public static final Gson gson = new Gson(); @@ -27,12 +27,8 @@ public class ChatImageProtocol { return ResourceLocation.tryBuild(PROTOCOL_ID, path); } - @ProtocolHandler.PayloadReceiver(payload = FileChannelPayload.class, payloadId = "get_file_channel") - public static void serverFileChannelReceived(ServerPlayer player, FileChannelPayload payload) { - if (!LeavesConfig.protocol.chatImageProtocol) { - return; - } - + @ProtocolHandler.PayloadReceiver(payload = FileChannelPayload.class) + public void serverFileChannelReceived(ServerPlayer player, FileChannelPayload payload) { MinecraftServer server = MinecraftServer.getServer(); String res = payload.message(); ChatImageIndex title = gson.fromJson(res, ChatImageIndex.class); @@ -52,12 +48,8 @@ public class ChatImageProtocol { } } - @ProtocolHandler.PayloadReceiver(payload = FileInfoChannelPayload.class, payloadId = "file_info") - public static void serverGetFileChannelReceived(ServerPlayer player, FileInfoChannelPayload packet) { - if (!LeavesConfig.protocol.chatImageProtocol) { - return; - } - + @ProtocolHandler.PayloadReceiver(payload = FileInfoChannelPayload.class) + public void serverGetFileChannelReceived(ServerPlayer player, FileInfoChannelPayload packet) { String url = packet.message(); Map list = SERVER_BLOCK_CACHE.getBlock(url); if (list == null) { @@ -69,4 +61,12 @@ public class ChatImageProtocol { ProtocolUtils.sendPayloadPacket(player, new DownloadFileChannelPayload(entry.getValue())); } } + + @Override + public boolean isActive() { + return LeavesConfig.protocol.chatImageProtocol; + } + + public record ChatImageIndex(int index, int total, String url, String bytes) { + } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/DownloadFileChannelPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/DownloadFileChannelPayload.java index 1562aadf..fe40ca62 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/DownloadFileChannelPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/DownloadFileChannelPayload.java @@ -1,32 +1,18 @@ package org.leavesmc.leaves.protocol.chatimage; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; -import org.leavesmc.leaves.protocol.core.ProtocolUtils; -public record DownloadFileChannelPayload(String message) implements LeavesCustomPayload { +public record DownloadFileChannelPayload(String message) implements LeavesCustomPayload { + @ID private static final ResourceLocation ID = ChatImageProtocol.id("download_file_channel"); - private static final StreamCodec CODEC = - StreamCodec.composite(ByteBufCodecs.STRING_UTF8, DownloadFileChannelPayload::message, DownloadFileChannelPayload::new); - - @Override - public void write(FriendlyByteBuf buf) { - CODEC.encode(ProtocolUtils.decorate(buf), this); - } - - @Override - public ResourceLocation id() { - return ID; - } - - @New - public static DownloadFileChannelPayload create(ResourceLocation location, FriendlyByteBuf buf) { - return CODEC.decode(ProtocolUtils.decorate(buf)); - } + @Codec + private static final StreamCodec CODEC = StreamCodec.composite( + ByteBufCodecs.STRING_UTF8, DownloadFileChannelPayload::message, DownloadFileChannelPayload::new + ); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/FileChannelPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/FileChannelPayload.java index 2a8e3cc9..8413f6b4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/FileChannelPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/FileChannelPayload.java @@ -1,32 +1,18 @@ package org.leavesmc.leaves.protocol.chatimage; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; -import org.leavesmc.leaves.protocol.core.ProtocolUtils; -public record FileChannelPayload(String message) implements LeavesCustomPayload { +public record FileChannelPayload(String message) implements LeavesCustomPayload { + @ID private static final ResourceLocation ID = ChatImageProtocol.id("get_file_channel"); - private static final StreamCodec CODEC = - StreamCodec.composite(ByteBufCodecs.STRING_UTF8, FileChannelPayload::message, FileChannelPayload::new); - - @Override - public void write(FriendlyByteBuf buf) { - CODEC.encode(ProtocolUtils.decorate(buf), this); - } - - @Override - public ResourceLocation id() { - return ID; - } - - @New - public static FileChannelPayload create(ResourceLocation location, FriendlyByteBuf buf) { - return CODEC.decode(ProtocolUtils.decorate(buf)); - } + @Codec + private static final StreamCodec CODEC = StreamCodec.composite( + ByteBufCodecs.STRING_UTF8, FileChannelPayload::message, FileChannelPayload::new + ); } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/FileInfoChannelPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/FileInfoChannelPayload.java index 389235fd..6c54506f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/FileInfoChannelPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/FileInfoChannelPayload.java @@ -1,32 +1,18 @@ package org.leavesmc.leaves.protocol.chatimage; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; -import org.leavesmc.leaves.protocol.core.ProtocolUtils; -public record FileInfoChannelPayload(String message) implements LeavesCustomPayload { +public record FileInfoChannelPayload(String message) implements LeavesCustomPayload { + @ID private static final ResourceLocation ID = ChatImageProtocol.id("file_info"); - private static final StreamCodec CODEC = - StreamCodec.composite(ByteBufCodecs.STRING_UTF8, FileInfoChannelPayload::message, FileInfoChannelPayload::new); - - @Override - public void write(FriendlyByteBuf buf) { - CODEC.encode(ProtocolUtils.decorate(buf), this); - } - - @Override - public ResourceLocation id() { - return ID; - } - - @New - public static FileInfoChannelPayload create(ResourceLocation location, FriendlyByteBuf buf) { - return CODEC.decode(ProtocolUtils.decorate(buf)); - } + @Codec + private static final StreamCodec CODEC = StreamCodec.composite( + ByteBufCodecs.STRING_UTF8, FileInfoChannelPayload::message, FileInfoChannelPayload::new + ); } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ServerBlockCache.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ServerBlockCache.java index 6498eb79..de169073 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ServerBlockCache.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ServerBlockCache.java @@ -19,15 +19,15 @@ public class ServerBlockCache { public Cache> blockCache = CacheBuilder.newBuilder().expireAfterAccess(60, TimeUnit.SECONDS).build(); public Cache fileCount = CacheBuilder.newBuilder().expireAfterAccess(60, TimeUnit.SECONDS).build(); - public Map createBlock(ChatImageIndex title, String imgBytes) { + public Map createBlock(ChatImageProtocol.ChatImageIndex title, String imgBytes) { try { - Map blocks = this.blockCache.get(title.url, HashMap::new); - blocks.put(title.index, imgBytes); - this.blockCache.put(title.url, blocks); - this.fileCount.put(title.url, title.total); + Map blocks = this.blockCache.get(title.url(), HashMap::new); + blocks.put(title.index(), imgBytes); + this.blockCache.put(title.url(), blocks); + this.fileCount.put(title.url(), title.total()); return blocks; } catch (Exception e) { - LeavesLogger.LOGGER.warning("Failed to create block for title " + title.url + ": " + e); + LeavesLogger.LOGGER.warning("Failed to create block for title " + title.url() + ": " + e); return null; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesCustomPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesCustomPayload.java index b09a7bfe..59e4aff4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesCustomPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesCustomPayload.java @@ -1,6 +1,5 @@ package org.leavesmc.leaves.protocol.core; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.NotNull; @@ -10,20 +9,22 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -public interface LeavesCustomPayload> extends CustomPacketPayload { +public interface LeavesCustomPayload extends CustomPacketPayload { - @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) - @Retention(RetentionPolicy.RUNTIME) - @interface New { - } - - void write(FriendlyByteBuf buf); - - ResourceLocation id(); + Type LEAVES_TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath("leaves", "custom_payload")); @Override - @NotNull - default Type type() { - return new CustomPacketPayload.Type<>(id()); + default @NotNull Type type() { + return LEAVES_TYPE; + } + + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.RUNTIME) + @interface ID { + } + + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.RUNTIME) + @interface Codec { } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocol.java index 986d2a66..8479a3fa 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocol.java @@ -5,8 +5,17 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface LeavesProtocol { - String[] namespace(); -} +public interface LeavesProtocol { + + boolean isActive(); + + default int tickerInterval(String tickerID) { + return 1; + } + + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + @interface Register { + String namespace(); + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java index fc330157..2787f546 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java @@ -1,20 +1,23 @@ package org.leavesmc.leaves.protocol.core; -import com.google.common.collect.ImmutableSet; +import io.netty.buffer.ByteBuf; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; -import org.apache.commons.lang.ArrayUtils; -import org.bukkit.event.player.PlayerKickEvent; -import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesLogger; +import org.leavesmc.leaves.protocol.core.invoker.BytebufReceiverInvokerHolder; +import org.leavesmc.leaves.protocol.core.invoker.EmptyInvokerHolder; +import org.leavesmc.leaves.protocol.core.invoker.InitInvokerHolder; +import org.leavesmc.leaves.protocol.core.invoker.MinecraftRegisterInvokerHolder; +import org.leavesmc.leaves.protocol.core.invoker.PayloadReceiverInvokerHolder; +import org.leavesmc.leaves.protocol.core.invoker.PlayerInvokerHolder; import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; -import java.lang.reflect.Executable; -import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.JarURLConnection; @@ -22,8 +25,6 @@ import java.net.URL; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -35,266 +36,288 @@ import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; -// TODO refactor public class LeavesProtocolManager { - private static final Class[] PAYLOAD_PARAMETER_TYPES = {ResourceLocation.class, FriendlyByteBuf.class}; - private static final LeavesLogger LOGGER = LeavesLogger.LOGGER; - private static final Map> KNOWN_TYPES = new HashMap<>(); - private static final Map> KNOW_RECEIVERS = new HashMap<>(); - private static Set ALL_KNOWN_ID = new HashSet<>(); + private static final Map, PayloadReceiverInvokerHolder> PAYLOAD_RECEIVERS = new HashMap<>(); + private static final Map, ResourceLocation> IDS = new HashMap<>(); + private static final Map, StreamCodec> CODECS = new HashMap<>(); + private static final Map> ID2CODEC = new HashMap<>(); - private static final List TICKERS = new ArrayList<>(); - private static final List PLAYER_JOIN = new ArrayList<>(); - private static final List PLAYER_LEAVE = new ArrayList<>(); - private static final List RELOAD_SERVER = new ArrayList<>(); - private static final Map> MINECRAFT_REGISTER = new HashMap<>(); + private static final Map STRICT_BYTEBUF_RECEIVERS = new HashMap<>(); + private static final Map NAMESPACED_BYTEBUF_RECEIVERS = new HashMap<>(); + private static final List GENERIC_BYTEBUF_RECEIVERS = new ArrayList<>(); + private static final Map STRICT_MINECRAFT_REGISTER = new HashMap<>(); + private static final Map NAMESPACED_MINECRAFT_REGISTER = new HashMap<>(); + private static final List WILD_MINECRAFT_REGISTER = new ArrayList<>(); + + private static final List> TICKERS = new ArrayList<>(); + + private static final List> PLAYER_JOIN = new ArrayList<>(); + private static final List> PLAYER_LEAVE = new ArrayList<>(); + private static final List> RELOAD_SERVER = new ArrayList<>(); + private static final List> RELOAD_DATAPACK = new ArrayList<>(); + + @SuppressWarnings("unchecked") public static void init() { for (Class clazz : getClasses("org.leavesmc.leaves.protocol")) { - final LeavesProtocol protocol = clazz.getAnnotation(LeavesProtocol.class); - if (protocol != null) { - Set methods; - try { - Method[] publicMethods = clazz.getMethods(); - Method[] privateMethods = clazz.getDeclaredMethods(); - methods = new HashSet<>(publicMethods.length + privateMethods.length, 1.0f); - Collections.addAll(methods, publicMethods); - Collections.addAll(methods, privateMethods); - } catch (NoClassDefFoundError error) { - LOGGER.severe("Failed to load class " + clazz.getName() + " due to missing dependencies, " + error.getCause() + ": " + error.getMessage()); - return; - } - - Map map = KNOWN_TYPES.getOrDefault(protocol, new HashMap<>()); - for (final Method method : methods) { - if (method.isBridge() || method.isSynthetic() || !Modifier.isStatic(method.getModifiers())) { + if (LeavesCustomPayload.class.isAssignableFrom(clazz) && !clazz.equals(LeavesCustomPayload.class)) { + for (Field field : clazz.getDeclaredFields()) { + field.setAccessible(true); + if (!Modifier.isStatic(field.getModifiers())) { continue; } - - method.setAccessible(true); - - final ProtocolHandler.Init init = method.getAnnotation(ProtocolHandler.Init.class); - if (init != null) { - try { - method.invoke(null); - } catch (InvocationTargetException | IllegalAccessException exception) { - LOGGER.severe("Failed to invoke init method " + method.getName() + " in " + clazz.getName() + ", " + exception.getCause() + ": " + exception.getMessage()); - } - continue; - } - - final ProtocolHandler.PayloadReceiver receiver = method.getAnnotation(ProtocolHandler.PayloadReceiver.class); - if (receiver != null) { - try { - boolean found = false; - for (Method payloadMethod : receiver.payload().getDeclaredMethods()) { - if (payloadMethod.isAnnotationPresent(LeavesCustomPayload.New.class)) { - if (Arrays.equals(payloadMethod.getParameterTypes(), PAYLOAD_PARAMETER_TYPES) && payloadMethod.getReturnType() == receiver.payload() && Modifier.isStatic(payloadMethod.getModifiers())) { - payloadMethod.setAccessible(true); - map.put(receiver, payloadMethod); - found = true; - break; - } - } - } - - if (!found) { - Constructor> constructor = receiver.payload().getConstructor(PAYLOAD_PARAMETER_TYPES); - if (constructor.isAnnotationPresent(LeavesCustomPayload.New.class)) { - constructor.setAccessible(true); - map.put(receiver, constructor); - } else { - throw new NoSuchMethodException(); - } - } - } catch (NoSuchMethodException exception) { - LOGGER.severe("Failed to find constructor for " + receiver.payload().getName() + ", " + exception.getCause() + ": " + exception.getMessage()); - continue; - } - - if (!KNOW_RECEIVERS.containsKey(protocol)) { - KNOW_RECEIVERS.put(protocol, new HashMap<>()); - } - - KNOW_RECEIVERS.get(protocol).put(receiver, method); - continue; - } - - final ProtocolHandler.Ticker ticker = method.getAnnotation(ProtocolHandler.Ticker.class); - if (ticker != null) { - TICKERS.add(method); - continue; - } - - final ProtocolHandler.PlayerJoin playerJoin = method.getAnnotation(ProtocolHandler.PlayerJoin.class); - if (playerJoin != null) { - PLAYER_JOIN.add(method); - continue; - } - - final ProtocolHandler.PlayerLeave playerLeave = method.getAnnotation(ProtocolHandler.PlayerLeave.class); - if (playerLeave != null) { - PLAYER_LEAVE.add(method); - continue; - } - - final ProtocolHandler.ReloadServer reloadServer = method.getAnnotation(ProtocolHandler.ReloadServer.class); - if (reloadServer != null) { - RELOAD_SERVER.add(method); - continue; - } - - final ProtocolHandler.MinecraftRegister minecraftRegister = method.getAnnotation(ProtocolHandler.MinecraftRegister.class); - if (minecraftRegister != null) { - if (!MINECRAFT_REGISTER.containsKey(protocol)) { - MINECRAFT_REGISTER.put(protocol, new HashMap<>()); - } - - MINECRAFT_REGISTER.get(protocol).put(minecraftRegister, method); - } - } - KNOWN_TYPES.put(protocol, map); - } - } - - for (LeavesProtocol protocol : KNOWN_TYPES.keySet()) { - Map map = KNOWN_TYPES.get(protocol); - for (ProtocolHandler.PayloadReceiver receiver : map.keySet()) { - if (receiver.sendFabricRegister() && !receiver.ignoreId()) { - for (String payloadId : receiver.payloadId()) { - for (String namespace : protocol.namespace()) { - ALL_KNOWN_ID.add(ResourceLocation.tryBuild(namespace, payloadId)); - } - } - } - } - } - ALL_KNOWN_ID = ImmutableSet.copyOf(ALL_KNOWN_ID); - } - - public static LeavesCustomPayload decode(ResourceLocation id, FriendlyByteBuf buf) { - for (LeavesProtocol protocol : KNOWN_TYPES.keySet()) { - if (!ArrayUtils.contains(protocol.namespace(), id.getNamespace())) { - continue; - } - - Map map = KNOWN_TYPES.get(protocol); - for (ProtocolHandler.PayloadReceiver receiver : map.keySet()) { - if (receiver.ignoreId() || ArrayUtils.contains(receiver.payloadId(), id.getPath())) { try { - if (map.get(receiver) instanceof Constructor constructor) { - return (LeavesCustomPayload) constructor.newInstance(id, buf); - } else if (map.get(receiver) instanceof Method method) { - return (LeavesCustomPayload) method.invoke(null, id, buf); + final LeavesCustomPayload.ID id = field.getAnnotation(LeavesCustomPayload.ID.class); + if (id != null && field.getType().equals(ResourceLocation.class)) { + IDS.put((Class) clazz, (ResourceLocation) field.get(null)); } - } catch (InvocationTargetException | InstantiationException | IllegalAccessException exception) { - LOGGER.warning("Failed to create payload for " + id + " in " + ArrayUtils.toString(protocol.namespace()) + ", " + exception.getCause() + ": " + exception.getMessage()); - buf.readBytes(buf.readableBytes()); - return new ErrorPayload(id, protocol.namespace(), receiver.payloadId()); + final LeavesCustomPayload.Codec codec = field.getAnnotation(LeavesCustomPayload.Codec.class); + if (codec != null && field.getType().equals(StreamCodec.class)) { + CODECS.put((Class) clazz, (StreamCodec) field.get(null)); + } + } catch (Exception e) { + throw new RuntimeException(e); } } - } - } - return null; - } - - public static void handlePayload(ServerPlayer player, LeavesCustomPayload payload) { - if (payload instanceof ErrorPayload errorPayload) { - player.connection.disconnect(Component.literal("Payload " + Arrays.toString(errorPayload.packetID) + " from " + Arrays.toString(errorPayload.protocolID) + " error"), PlayerKickEvent.Cause.INVALID_PAYLOAD); - return; - } - - for (LeavesProtocol protocol : KNOW_RECEIVERS.keySet()) { - if (!ArrayUtils.contains(protocol.namespace(), payload.type().id().getNamespace())) { continue; } - Map map = KNOW_RECEIVERS.get(protocol); - for (ProtocolHandler.PayloadReceiver receiver : map.keySet()) { - if (payload.getClass() == receiver.payload()) { - if (receiver.ignoreId() || ArrayUtils.contains(receiver.payloadId(), payload.type().id().getPath())) { - try { - map.get(receiver).invoke(null, player, payload); - } catch (InvocationTargetException | IllegalAccessException exception) { - LOGGER.warning("Failed to handle payload " + payload.type().id() + " in " + ArrayUtils.toString(protocol.namespace()) + ", " + exception.getCause() + ": " + exception.getMessage()); + final LeavesProtocol.Register register = clazz.getAnnotation(LeavesProtocol.Register.class); + if (register == null) { + continue; + } + LeavesProtocol protocol; + try { + Constructor constructor = clazz.getDeclaredConstructor(); + constructor.setAccessible(true); + protocol = (LeavesProtocol) constructor.newInstance(); + } catch (Throwable throwable) { + LOGGER.severe("Failed to load class " + clazz.getName() + ". " + throwable); + return; + } + + for (final Method method : clazz.getDeclaredMethods()) { + if (method.isBridge() || method.isSynthetic()) { + continue; + } + method.setAccessible(true); + + final ProtocolHandler.Init init = method.getAnnotation(ProtocolHandler.Init.class); + if (init != null) { + InitInvokerHolder holder = new InitInvokerHolder(protocol, method, init); + try { + holder.invoke(); + } catch (RuntimeException exception) { + LOGGER.severe("Failed to invoke init method " + method.getName() + " in " + clazz.getName() + ", " + exception.getCause() + ": " + exception.getMessage()); + } + continue; + } + + final ProtocolHandler.PayloadReceiver payloadReceiver = method.getAnnotation(ProtocolHandler.PayloadReceiver.class); + if (payloadReceiver != null) { + PAYLOAD_RECEIVERS.put(payloadReceiver.payload(), new PayloadReceiverInvokerHolder(protocol, method, payloadReceiver)); + continue; + } + + final ProtocolHandler.BytebufReceiver bytebufReceiver = method.getAnnotation(ProtocolHandler.BytebufReceiver.class); + if (bytebufReceiver != null) { + String key = bytebufReceiver.key(); + BytebufReceiverInvokerHolder holder = new BytebufReceiverInvokerHolder(protocol, method, bytebufReceiver); + if (bytebufReceiver.onlyNamespace()) { + NAMESPACED_BYTEBUF_RECEIVERS.put(key.isEmpty() ? register.namespace() : key, holder); + } else { + if (key.isEmpty()) { + GENERIC_BYTEBUF_RECEIVERS.add(holder); + } else { + if (key.contains(":")) { + STRICT_BYTEBUF_RECEIVERS.put(key, holder); + } else { + STRICT_BYTEBUF_RECEIVERS.put(register.namespace() + ":" + key, holder); + } + } + } + continue; + } + + final ProtocolHandler.Ticker ticker = method.getAnnotation(ProtocolHandler.Ticker.class); + if (ticker != null) { + TICKERS.add(new EmptyInvokerHolder<>(protocol, method, ticker)); + continue; + } + + final ProtocolHandler.PlayerJoin playerJoin = method.getAnnotation(ProtocolHandler.PlayerJoin.class); + if (playerJoin != null) { + PLAYER_JOIN.add(new PlayerInvokerHolder<>(protocol, method, playerJoin)); + continue; + } + + final ProtocolHandler.PlayerLeave playerLeave = method.getAnnotation(ProtocolHandler.PlayerLeave.class); + if (playerLeave != null) { + PLAYER_LEAVE.add(new PlayerInvokerHolder<>(protocol, method, playerLeave)); + continue; + } + + final ProtocolHandler.ReloadServer reloadServer = method.getAnnotation(ProtocolHandler.ReloadServer.class); + if (reloadServer != null) { + RELOAD_SERVER.add(new EmptyInvokerHolder<>(protocol, method, reloadServer)); + continue; + } + + final ProtocolHandler.ReloadDataPack reloadDataPack = method.getAnnotation(ProtocolHandler.ReloadDataPack.class); + if (reloadDataPack != null) { + RELOAD_DATAPACK.add(new EmptyInvokerHolder<>(protocol, method, reloadDataPack)); + continue; + } + + final ProtocolHandler.MinecraftRegister minecraftRegister = method.getAnnotation(ProtocolHandler.MinecraftRegister.class); + if (minecraftRegister != null) { + String key = minecraftRegister.key(); + MinecraftRegisterInvokerHolder holder = new MinecraftRegisterInvokerHolder(protocol, method, minecraftRegister); + if (minecraftRegister.onlyNamespace()) { + NAMESPACED_MINECRAFT_REGISTER.put(key.isEmpty() ? register.namespace() : key, holder); + } else { + if (key.isEmpty()) { + WILD_MINECRAFT_REGISTER.add(holder); + } else { + if (key.contains(":")) { + STRICT_MINECRAFT_REGISTER.put(key, holder); + } else { + STRICT_MINECRAFT_REGISTER.put(register.namespace() + ":" + key, holder); + } } } } } } + for (var idInfo : IDS.entrySet()) { + var codec = CODECS.get(idInfo.getKey()); + if (codec == null) { + throw new IllegalArgumentException("Payload " + idInfo.getKey() + " is not configured correctly"); + } + ID2CODEC.put(idInfo.getValue(), codec); + } } - public static void handleTick() { - if (!TICKERS.isEmpty()) { - try { - for (Method method : TICKERS) { - method.invoke(null); - } - } catch (InvocationTargetException | IllegalAccessException exception) { - LOGGER.warning("Failed to tick, " + exception.getCause() + ": " + exception.getMessage()); + public static LeavesCustomPayload decode(ResourceLocation location, FriendlyByteBuf buf) { + var codec = ID2CODEC.get(location); + if (codec == null) { + return null; + } + return codec.decode(ProtocolUtils.decorate(buf)); + } + + public static void encode(FriendlyByteBuf buf, LeavesCustomPayload payload) { + var location = IDS.get(payload.getClass()); + var codec = CODECS.get(payload.getClass()); + if (location == null || codec == null) { + throw new IllegalArgumentException("Payload " + payload.getClass() + " is not configured correctly " + location + " " + codec); + } + buf.writeResourceLocation(location); + codec.encode(ProtocolUtils.decorate(buf), payload); + } + + public static void handlePayload(ServerPlayer player, LeavesCustomPayload payload) { + PayloadReceiverInvokerHolder holder; + if ((holder = PAYLOAD_RECEIVERS.get(payload.getClass())) != null) { + holder.invoke(player, payload); + } + } + + public static boolean handleBytebuf(ServerPlayer player, ResourceLocation location, ByteBuf buf) { + RegistryFriendlyByteBuf buf1 = ProtocolUtils.decorate(buf); + BytebufReceiverInvokerHolder holder; + if ((holder = STRICT_BYTEBUF_RECEIVERS.get(location.toString())) != null) { + holder.invoke(player, buf1); + return true; + } + if ((holder = NAMESPACED_BYTEBUF_RECEIVERS.get(location.getNamespace())) != null) { + if (holder.invoke(player, buf1)) { + return true; + } + } + for (var holder1 : GENERIC_BYTEBUF_RECEIVERS) { + if (holder1.invoke(player, buf1)) { + return true; + } + } + return false; + } + + public static void handleTick(long tickCount) { + for (var tickerInfo : TICKERS) { + if (tickCount % tickerInfo.owner().tickerInterval(tickerInfo.handler().tickerId()) == 0) { + tickerInfo.invoke(); } } } public static void handlePlayerJoin(ServerPlayer player) { - if (!PLAYER_JOIN.isEmpty()) { - try { - for (Method method : PLAYER_JOIN) { - method.invoke(null, player); - } - } catch (InvocationTargetException | IllegalAccessException exception) { - LOGGER.warning("Failed to handle player join, " + exception.getCause() + ": " + exception.getMessage()); - } + sendKnownId(player); + for (var join : PLAYER_JOIN) { + join.invoke(player); } - - ProtocolUtils.sendPayloadPacket(player, new FabricRegisterPayload(ALL_KNOWN_ID)); } public static void handlePlayerLeave(ServerPlayer player) { - if (!PLAYER_LEAVE.isEmpty()) { - try { - for (Method method : PLAYER_LEAVE) { - method.invoke(null, player); - } - } catch (InvocationTargetException | IllegalAccessException exception) { - LOGGER.warning("Failed to handle player leave, " + exception.getCause() + ": " + exception.getMessage()); - } + for (var leave : PLAYER_LEAVE) { + leave.invoke(player); } } public static void handleServerReload() { - if (!RELOAD_SERVER.isEmpty()) { - try { - for (Method method : RELOAD_SERVER) { - method.invoke(null); - } - } catch (InvocationTargetException | IllegalAccessException exception) { - LOGGER.warning("Failed to handle server reload, " + exception.getCause() + ": " + exception.getMessage()); - } + for (var reload : RELOAD_SERVER) { + reload.invoke(); + } + } + + public static void handleDataPackReload() { + for (var reload : RELOAD_DATAPACK) { + reload.invoke(); } } public static void handleMinecraftRegister(String channelId, ServerPlayer player) { - for (LeavesProtocol protocol : MINECRAFT_REGISTER.keySet()) { - String[] channel = channelId.split(":"); - if (!ArrayUtils.contains(protocol.namespace(), channel[0])) { - continue; - } - - Map map = MINECRAFT_REGISTER.get(protocol); - for (ProtocolHandler.MinecraftRegister register : map.keySet()) { - if (register.ignoreId() || ArrayUtils.contains(register.channelId(), channel[1])) { - try { - map.get(register).invoke(null, player, channel[1]); - } catch (InvocationTargetException | IllegalAccessException exception) { - LOGGER.warning("Failed to handle minecraft register, " + exception.getCause() + ": " + exception.getMessage()); - } - } - } + ResourceLocation location = ResourceLocation.tryParse(channelId); + if (location == null) { + return; } + + for (var wildHolder : WILD_MINECRAFT_REGISTER) { + wildHolder.invoke(player, location); + } + + MinecraftRegisterInvokerHolder holder; + if ((holder = STRICT_MINECRAFT_REGISTER.get(location.toString())) != null) { + holder.invoke(player, location); + } + if ((holder = NAMESPACED_MINECRAFT_REGISTER.get(location.getNamespace())) != null) { + holder.invoke(player, location); + } + } + + private static void sendKnownId(ServerPlayer player) { + Set set = new HashSet<>(); + PAYLOAD_RECEIVERS.forEach((clazz, holder) -> { + if (holder.owner().isActive()) { + set.add(IDS.get(clazz).toString()); + } + }); + STRICT_BYTEBUF_RECEIVERS.forEach((key, holder) -> { + if (holder.owner().isActive()) { + set.add(key); + } + }); + ProtocolUtils.sendBytebufPacket(player, ResourceLocation.fromNamespaceAndPath("minecraft", "register"), buf -> { + ResourceLocation channel; + for (Iterator var3 = set.iterator(); var3.hasNext(); buf.writeBytes(channel.toString().getBytes(StandardCharsets.US_ASCII))) { + channel = ResourceLocation.parse(var3.next()); + buf.writeByte(0); + } + buf.writerIndex(Math.max(buf.writerIndex() - 1, 0)); + }); } public static Set> getClasses(String pack) { @@ -371,63 +394,4 @@ public class LeavesProtocolManager { } } } - - public record ErrorPayload(ResourceLocation id, String[] protocolID, String[] packetID) implements LeavesCustomPayload { - @Override - public void write(@NotNull FriendlyByteBuf buf) { - } - } - - public record EmptyPayload(ResourceLocation id) implements LeavesCustomPayload { - @New - public EmptyPayload(ResourceLocation location, FriendlyByteBuf buf) { - this(location); - } - - @Override - public void write(@NotNull FriendlyByteBuf buf) { - } - } - - public record LeavesPayload(FriendlyByteBuf data, ResourceLocation id) implements LeavesCustomPayload { - @New - public LeavesPayload(ResourceLocation location, FriendlyByteBuf buf) { - this(new FriendlyByteBuf(buf.readBytes(buf.readableBytes())), location); - } - - @Override - public void write(FriendlyByteBuf buf) { - buf.writeBytes(data); - } - } - - public record FabricRegisterPayload(Set channels) implements LeavesCustomPayload { - - public static final ResourceLocation CHANNEL = ResourceLocation.withDefaultNamespace("register"); - - @New - public FabricRegisterPayload(ResourceLocation location, FriendlyByteBuf buf) { - this(buf.readCollection(HashSet::new, FriendlyByteBuf::readResourceLocation)); - } - - @Override - public void write(FriendlyByteBuf buf) { - boolean first = true; - - ResourceLocation channel; - for (Iterator var3 = this.channels.iterator(); var3.hasNext(); buf.writeBytes(channel.toString().getBytes(StandardCharsets.US_ASCII))) { - channel = var3.next(); - if (first) { - first = false; - } else { - buf.writeByte(0); - } - } - } - - @Override - public ResourceLocation id() { - return CHANNEL; - } - } -} +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolHandler.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolHandler.java index 202fb071..0a36db38 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolHandler.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolHandler.java @@ -15,19 +15,21 @@ public class ProtocolHandler { @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface PayloadReceiver { - Class> payload(); + Class payload(); + } - String[] payloadId() default ""; + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface BytebufReceiver { + String key() default ""; - boolean ignoreId() default false; - - boolean sendFabricRegister() default true; + boolean onlyNamespace() default false; } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Ticker { - int delay() default 0; + String tickerId() default ""; } @Target(ElementType.METHOD) @@ -48,8 +50,13 @@ public class ProtocolHandler { @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MinecraftRegister { - String[] channelId() default ""; + String key() default ""; - boolean ignoreId() default false; + boolean onlyNamespace() default false; } -} + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + public @interface ReloadDataPack { + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolUtils.java index 72fb1e65..361660c6 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolUtils.java @@ -1,11 +1,13 @@ package org.leavesmc.leaves.protocol.core; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; import io.papermc.paper.ServerBuildInfo; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.network.protocol.common.custom.DiscardedPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -16,34 +18,24 @@ import java.util.function.Function; public class ProtocolUtils { - private static final Function bufDecorator = RegistryFriendlyByteBuf.decorator(MinecraftServer.getServer().registryAccess()); + private static final Function bufDecorator = buf -> buf instanceof RegistryFriendlyByteBuf registry ? registry : new RegistryFriendlyByteBuf(buf, MinecraftServer.getServer().registryAccess()); public static String buildProtocolVersion(String protocol) { return protocol + "-leaves-" + ServerBuildInfo.buildInfo().asString(ServerBuildInfo.StringRepresentation.VERSION_SIMPLE); } - public static void sendEmptyPayloadPacket(ServerPlayer player, ResourceLocation id) { - player.connection.send(new ClientboundCustomPayloadPacket(new LeavesProtocolManager.EmptyPayload(id))); + public static void sendEmptyPacket(ServerPlayer player, ResourceLocation id) { + player.internalConnection.send(new ClientboundCustomPayloadPacket(new DiscardedPayload(id, null))); } - @SuppressWarnings("all") - public static void sendPayloadPacket(@NotNull ServerPlayer player, ResourceLocation id, Consumer consumer) { - player.connection.send(new ClientboundCustomPayloadPacket(new LeavesCustomPayload() { - @Override - public void write(@NotNull FriendlyByteBuf buf) { - consumer.accept(buf); - } - - @Override - @NotNull - public ResourceLocation id() { - return id; - } - })); + public static void sendBytebufPacket(@NotNull ServerPlayer player, ResourceLocation id, Consumer consumer) { + RegistryFriendlyByteBuf buf = decorate(Unpooled.buffer()); + consumer.accept(buf); + player.internalConnection.send(new ClientboundCustomPayloadPacket(new DiscardedPayload(id, ByteBufUtil.getBytes(buf)))); } public static void sendPayloadPacket(ServerPlayer player, CustomPacketPayload payload) { - player.connection.send(new ClientboundCustomPayloadPacket(payload)); + player.internalConnection.send(new ClientboundCustomPayloadPacket(payload)); } public static RegistryFriendlyByteBuf decorate(ByteBuf buf) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/AbstractInvokerHolder.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/AbstractInvokerHolder.java new file mode 100644 index 00000000..1cac9120 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/AbstractInvokerHolder.java @@ -0,0 +1,70 @@ +package org.leavesmc.leaves.protocol.core.invoker; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.leavesmc.leaves.protocol.core.LeavesProtocol; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public abstract class AbstractInvokerHolder { + + protected final LeavesProtocol owner; + protected final Method invoker; + protected final T handler; + protected final Class returnType; + protected final Class[] parameterTypes; + + protected AbstractInvokerHolder(LeavesProtocol owner, Method invoker, T handler, @Nullable Class returnType, @NotNull Class... parameterTypes) { + this.owner = owner; + this.invoker = invoker; + this.handler = handler; + this.returnType = returnType; + this.parameterTypes = parameterTypes; + + validateMethodSignature(); + } + + protected void validateMethodSignature() { + if (returnType != null && !returnType.isAssignableFrom(invoker.getReturnType())) { + throw new IllegalArgumentException("Return type mismatch in " + owner.getClass().getName() + "#" + invoker.getName() + + ": expected " + returnType.getName() + " but found " + invoker.getReturnType().getName()); + } + + Class[] methodParamTypes = invoker.getParameterTypes(); + if (methodParamTypes.length != parameterTypes.length) { + throw new IllegalArgumentException("Parameter count mismatch in " + owner.getClass().getName() + "#" + invoker.getName() + + ": expected " + parameterTypes.length + " but found " + methodParamTypes.length); + } + + for (int i = 0; i < parameterTypes.length; i++) { + if (!parameterTypes[i].isAssignableFrom(methodParamTypes[i])) { + throw new IllegalArgumentException("Parameter type mismatch in " + owner.getClass().getName() + "#" + invoker.getName() + + " at index " + i + ": expected " + parameterTypes[i].getName() + " but found " + methodParamTypes[i].getName()); + } + } + } + + public LeavesProtocol owner() { + return owner; + } + + public T handler() { + return handler; + } + + protected Object invoke0(boolean force, Object... args) { + if (!force && !owner.isActive()) { + return null; + } + try { + if (Modifier.isStatic(invoker.getModifiers())) { + return invoker.invoke(null, args); + } else { + return invoker.invoke(owner, args); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/BytebufReceiverInvokerHolder.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/BytebufReceiverInvokerHolder.java new file mode 100644 index 00000000..e2c01b8e --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/BytebufReceiverInvokerHolder.java @@ -0,0 +1,18 @@ +package org.leavesmc.leaves.protocol.core.invoker; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import org.leavesmc.leaves.protocol.core.LeavesProtocol; +import org.leavesmc.leaves.protocol.core.ProtocolHandler; + +import java.lang.reflect.Method; + +public class BytebufReceiverInvokerHolder extends AbstractInvokerHolder { + public BytebufReceiverInvokerHolder(LeavesProtocol owner, Method invoker, ProtocolHandler.BytebufReceiver handler) { + super(owner, invoker, handler, null, ServerPlayer.class, FriendlyByteBuf.class); + } + + public boolean invoke(ServerPlayer player, FriendlyByteBuf buf) { + return invoke0(false, player, buf) instanceof Boolean b && b; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/EmptyInvokerHolder.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/EmptyInvokerHolder.java new file mode 100644 index 00000000..d6e18d3e --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/EmptyInvokerHolder.java @@ -0,0 +1,15 @@ +package org.leavesmc.leaves.protocol.core.invoker; + +import org.leavesmc.leaves.protocol.core.LeavesProtocol; + +import java.lang.reflect.Method; + +public class EmptyInvokerHolder extends AbstractInvokerHolder { + public EmptyInvokerHolder(LeavesProtocol owner, Method invoker, T handler) { + super(owner, invoker, handler, null); + } + + public void invoke() { + invoke0(false); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/InitInvokerHolder.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/InitInvokerHolder.java new file mode 100644 index 00000000..128aaf8e --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/InitInvokerHolder.java @@ -0,0 +1,16 @@ +package org.leavesmc.leaves.protocol.core.invoker; + +import org.leavesmc.leaves.protocol.core.LeavesProtocol; +import org.leavesmc.leaves.protocol.core.ProtocolHandler; + +import java.lang.reflect.Method; + +public class InitInvokerHolder extends AbstractInvokerHolder { + public InitInvokerHolder(LeavesProtocol owner, Method invoker, ProtocolHandler.Init handler) { + super(owner, invoker, handler, null); + } + + public void invoke() { + invoke0(true); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/MinecraftRegisterInvokerHolder.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/MinecraftRegisterInvokerHolder.java new file mode 100644 index 00000000..c6766bc7 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/MinecraftRegisterInvokerHolder.java @@ -0,0 +1,18 @@ +package org.leavesmc.leaves.protocol.core.invoker; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import org.leavesmc.leaves.protocol.core.LeavesProtocol; +import org.leavesmc.leaves.protocol.core.ProtocolHandler; + +import java.lang.reflect.Method; + +public class MinecraftRegisterInvokerHolder extends AbstractInvokerHolder { + public MinecraftRegisterInvokerHolder(LeavesProtocol owner, Method invoker, ProtocolHandler.MinecraftRegister handler) { + super(owner, invoker, handler, null, ServerPlayer.class, ResourceLocation.class); + } + + public void invoke(ServerPlayer player, ResourceLocation id) { + invoke0(false, player, id); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/PayloadReceiverInvokerHolder.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/PayloadReceiverInvokerHolder.java new file mode 100644 index 00000000..bed868b5 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/PayloadReceiverInvokerHolder.java @@ -0,0 +1,18 @@ +package org.leavesmc.leaves.protocol.core.invoker; + +import net.minecraft.server.level.ServerPlayer; +import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; +import org.leavesmc.leaves.protocol.core.LeavesProtocol; +import org.leavesmc.leaves.protocol.core.ProtocolHandler; + +import java.lang.reflect.Method; + +public class PayloadReceiverInvokerHolder extends AbstractInvokerHolder { + public PayloadReceiverInvokerHolder(LeavesProtocol owner, Method invoker, ProtocolHandler.PayloadReceiver handler) { + super(owner, invoker, handler, null, ServerPlayer.class, handler.payload()); + } + + public void invoke(ServerPlayer player, LeavesCustomPayload payload) { + invoke0(false, player, payload); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/PlayerInvokerHolder.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/PlayerInvokerHolder.java new file mode 100644 index 00000000..5ed2c2da --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/PlayerInvokerHolder.java @@ -0,0 +1,16 @@ +package org.leavesmc.leaves.protocol.core.invoker; + +import net.minecraft.server.level.ServerPlayer; +import org.leavesmc.leaves.protocol.core.LeavesProtocol; + +import java.lang.reflect.Method; + +public class PlayerInvokerHolder extends AbstractInvokerHolder { + public PlayerInvokerHolder(LeavesProtocol owner, Method invoker, T handler) { + super(owner, invoker, handler, null, ServerPlayer.class); + } + + public void invoke(ServerPlayer player) { + invoke0(false, player); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java index ed91e1c5..affaaa99 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java @@ -18,6 +18,7 @@ import net.minecraft.world.entity.animal.Chicken; import net.minecraft.world.entity.animal.allay.Allay; import net.minecraft.world.entity.animal.armadillo.Armadillo; import net.minecraft.world.entity.animal.frog.Tadpole; +import net.minecraft.world.entity.animal.sniffer.Sniffer; import net.minecraft.world.entity.monster.ZombieVillager; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -55,6 +56,7 @@ import org.leavesmc.leaves.protocol.jade.provider.IServerExtensionProvider; import org.leavesmc.leaves.protocol.jade.provider.ItemStorageExtensionProvider; import org.leavesmc.leaves.protocol.jade.provider.ItemStorageProvider; import org.leavesmc.leaves.protocol.jade.provider.block.BeehiveProvider; +import org.leavesmc.leaves.protocol.jade.provider.block.BlockNameProvider; import org.leavesmc.leaves.protocol.jade.provider.block.BrewingStandProvider; import org.leavesmc.leaves.protocol.jade.provider.block.CampfireProvider; import org.leavesmc.leaves.protocol.jade.provider.block.ChiseledBookshelfProvider; @@ -64,7 +66,6 @@ import org.leavesmc.leaves.protocol.jade.provider.block.HopperLockProvider; import org.leavesmc.leaves.protocol.jade.provider.block.JukeboxProvider; import org.leavesmc.leaves.protocol.jade.provider.block.LecternProvider; import org.leavesmc.leaves.protocol.jade.provider.block.MobSpawnerCooldownProvider; -import org.leavesmc.leaves.protocol.jade.provider.block.ObjectNameProvider; import org.leavesmc.leaves.protocol.jade.provider.block.RedstoneProvider; import org.leavesmc.leaves.protocol.jade.provider.entity.AnimalOwnerProvider; import org.leavesmc.leaves.protocol.jade.provider.entity.MobBreedingProvider; @@ -78,26 +79,26 @@ import org.leavesmc.leaves.protocol.jade.util.LootTableMineableCollector; import org.leavesmc.leaves.protocol.jade.util.PairHierarchyLookup; import org.leavesmc.leaves.protocol.jade.util.PriorityStore; import org.leavesmc.leaves.protocol.jade.util.WrappedHierarchyLookup; +import org.leavesmc.leaves.protocol.servux.litematics.utils.NbtUtils; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -@LeavesProtocol(namespace = "jade") -public class JadeProtocol { - - public static PriorityStore priorities; - private static List shearableBlocks = null; +@LeavesProtocol.Register(namespace = "jade") +public class JadeProtocol implements LeavesProtocol { public static final String PROTOCOL_ID = "jade"; public static final String PROTOCOL_VERSION = "7"; - public static final HierarchyLookup> entityDataProviders = new HierarchyLookup<>(Entity.class); public static final PairHierarchyLookup> blockDataProviders = new PairHierarchyLookup<>(new HierarchyLookup<>(Block.class), new HierarchyLookup<>(BlockEntity.class)); public static final WrappedHierarchyLookup> itemStorageProviders = WrappedHierarchyLookup.forAccessor(); private static final Set enabledPlayers = new HashSet<>(); + public static PriorityStore priorities; + private static List shearableBlocks = null; + @Contract("_ -> new") public static ResourceLocation id(String path) { return ResourceLocation.tryBuild(PROTOCOL_ID, path); @@ -113,7 +114,7 @@ public class JadeProtocol { priorities = new PriorityStore<>(IJadeProvider::getDefaultPriority, IJadeProvider::getUid); // core plugin - blockDataProviders.register(BlockEntity.class, ObjectNameProvider.ForBlock.INSTANCE); + blockDataProviders.register(BlockEntity.class, BlockNameProvider.INSTANCE); // universal plugin entityDataProviders.register(Entity.class, ItemStorageProvider.getEntity()); @@ -133,6 +134,7 @@ public class JadeProtocol { entityDataProviders.register(Chicken.class, NextEntityDropProvider.INSTANCE); entityDataProviders.register(Armadillo.class, NextEntityDropProvider.INSTANCE); + entityDataProviders.register(Sniffer.class, NextEntityDropProvider.INSTANCE); entityDataProviders.register(ZombieVillager.class, ZombieVillagerProvider.INSTANCE); @@ -150,9 +152,10 @@ public class JadeProtocol { blockDataProviders.register(ChiseledBookShelfBlockEntity.class, ChiseledBookshelfProvider.INSTANCE); blockDataProviders.register(TrialSpawnerBlockEntity.class, MobSpawnerCooldownProvider.INSTANCE); + itemStorageProviders.register(CampfireBlock.class, CampfireProvider.INSTANCE); + blockDataProviders.idMapped(); entityDataProviders.idMapped(); - itemStorageProviders.register(CampfireBlock.class, CampfireProvider.INSTANCE); blockDataProviders.loadComplete(priorities); entityDataProviders.loadComplete(priorities); @@ -161,12 +164,8 @@ public class JadeProtocol { rebuildShearableBlocks(); } - @ProtocolHandler.PayloadReceiver(payload = ClientHandshakePayload.class, payloadId = "client_handshake") + @ProtocolHandler.PayloadReceiver(payload = ClientHandshakePayload.class) public static void clientHandshake(ServerPlayer player, ClientHandshakePayload payload) { - if (!LeavesConfig.protocol.jadeProtocol) { - return; - } - if (!payload.protocolVersion().equals(PROTOCOL_VERSION)) { player.sendSystemMessage(Component.literal("You are using a different version of Jade than the server. Please update Jade or report to the server operator").withColor(0xff0000)); return; @@ -180,12 +179,8 @@ public class JadeProtocol { enabledPlayers.remove(player); } - @ProtocolHandler.PayloadReceiver(payload = RequestEntityPayload.class, payloadId = "request_entity") + @ProtocolHandler.PayloadReceiver(payload = RequestEntityPayload.class) public static void requestEntityData(ServerPlayer player, RequestEntityPayload payload) { - if (!LeavesConfig.protocol.jadeProtocol) { - return; - } - MinecraftServer.getServer().execute(() -> { EntityAccessor accessor = payload.data().unpack(player); if (accessor == null) { @@ -220,12 +215,8 @@ public class JadeProtocol { }); } - @ProtocolHandler.PayloadReceiver(payload = RequestBlockPayload.class, payloadId = "request_block") + @ProtocolHandler.PayloadReceiver(payload = RequestBlockPayload.class) public static void requestBlockData(ServerPlayer player, RequestBlockPayload payload) { - if (!LeavesConfig.protocol.jadeProtocol) { - return; - } - MinecraftServer server = MinecraftServer.getServer(); server.execute(() -> { BlockAccessor accessor = payload.data().unpack(player); @@ -263,9 +254,7 @@ public class JadeProtocol { LeavesLogger.LOGGER.warning("Error while saving data for block " + accessor.getBlockState()); } } - tag.putInt("x", pos.getX()); - tag.putInt("y", pos.getY()); - tag.putInt("z", pos.getZ()); + NbtUtils.writeBlockPosToTag(pos, tag); tag.putString("BlockId", BuiltInRegistries.BLOCK.getKey(block).toString()); ProtocolUtils.sendPayloadPacket(player, new ReceiveDataPayload(tag)); @@ -274,11 +263,9 @@ public class JadeProtocol { @ProtocolHandler.ReloadServer public static void onServerReload() { - if (LeavesConfig.protocol.jadeProtocol) { - rebuildShearableBlocks(); - for (ServerPlayer player : enabledPlayers) { - ProtocolUtils.sendPayloadPacket(player, new ServerHandshakePayload(Collections.emptyMap(), shearableBlocks, blockDataProviders.mappedIds(), entityDataProviders.mappedIds())); - } + rebuildShearableBlocks(); + for (ServerPlayer player : enabledPlayers) { + ProtocolUtils.sendPayloadPacket(player, new ServerHandshakePayload(Collections.emptyMap(), shearableBlocks, blockDataProviders.mappedIds(), entityDataProviders.mappedIds())); } } @@ -293,4 +280,9 @@ public class JadeProtocol { LeavesLogger.LOGGER.severe("Failed to collect shearable blocks"); } } + + @Override + public boolean isActive() { + return LeavesConfig.protocol.jadeProtocol; + } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java index 1a637045..6bc22532 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java @@ -9,7 +9,6 @@ import net.minecraft.world.phys.HitResult; import org.jetbrains.annotations.Nullable; public interface Accessor { - Level getLevel(); Player getPlayer(); @@ -18,15 +17,6 @@ public interface Accessor { T getHitResult(); - /** - * @return {@code true} if the dedicated server has Jade installed. - */ - boolean isServerConnected(); - - boolean showDetails(); - @Nullable Object getTarget(); - - float tickRate(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/AccessorImpl.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/AccessorImpl.java index 7e57bd40..a6d91d97 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/AccessorImpl.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/AccessorImpl.java @@ -17,17 +17,13 @@ public abstract class AccessorImpl implements Accessor { private final Level level; private final Player player; private final Supplier hit; - private final boolean serverConnected; - private final boolean showDetails; protected boolean verify; private RegistryFriendlyByteBuf buffer; - public AccessorImpl(Level level, Player player, Supplier hit, boolean serverConnected, boolean showDetails) { + public AccessorImpl(Level level, Player player, Supplier hit) { this.level = level; this.player = player; this.hit = hit; - this.serverConnected = serverConnected; - this.showDetails = showDetails; } @Override @@ -61,22 +57,4 @@ public abstract class AccessorImpl implements Accessor { public T getHitResult() { return hit.get(); } - - /** - * Returns true if dedicated server has Jade installed. - */ - @Override - public boolean isServerConnected() { - return serverConnected; - } - - @Override - public boolean showDetails() { - return showDetails; - } - - @Override - public float tickRate() { - return getLevel().tickRateManager().tickrate(); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessor.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessor.java index 12d689ca..133415a3 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessor.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessor.java @@ -1,7 +1,6 @@ package org.leavesmc.leaves.protocol.jade.accessor; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; @@ -22,16 +21,12 @@ public interface BlockAccessor extends Accessor { BlockPos getPosition(); - Direction getSide(); - @ApiStatus.NonExtendable interface Builder { Builder level(Level level); Builder player(Player player); - Builder showDetails(boolean showDetails); - Builder hit(BlockHitResult hit); Builder blockState(BlockState state); @@ -46,5 +41,4 @@ public interface BlockAccessor extends Accessor { BlockAccessor build(); } - } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessorImpl.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessorImpl.java index 8cd6c09a..a94bb9eb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessorImpl.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessorImpl.java @@ -2,7 +2,6 @@ package org.leavesmc.leaves.protocol.jade.accessor; import com.google.common.base.Suppliers; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; @@ -30,7 +29,7 @@ public class BlockAccessorImpl extends AccessorImpl implements B private final Supplier blockEntity; private BlockAccessorImpl(Builder builder) { - super(builder.level, builder.player, Suppliers.ofInstance(builder.hit), builder.connected, builder.showDetails); + super(builder.level, builder.player, Suppliers.ofInstance(builder.hit)); blockState = builder.blockState; blockEntity = builder.blockEntity; } @@ -55,11 +54,6 @@ public class BlockAccessorImpl extends AccessorImpl implements B return getHitResult().getBlockPos(); } - @Override - public Direction getSide() { - return getHitResult().getDirection(); - } - @Nullable @Override public Object getTarget() { @@ -67,11 +61,8 @@ public class BlockAccessorImpl extends AccessorImpl implements B } public static class Builder implements BlockAccessor.Builder { - private Level level; private Player player; - private boolean connected; - private boolean showDetails; private BlockHitResult hit; private BlockState blockState = Blocks.AIR.defaultBlockState(); private Supplier blockEntity; @@ -88,12 +79,6 @@ public class BlockAccessorImpl extends AccessorImpl implements B return this; } - @Override - public Builder showDetails(boolean showDetails) { - this.showDetails = showDetails; - return this; - } - @Override public Builder hit(BlockHitResult hit) { this.hit = hit; @@ -116,8 +101,6 @@ public class BlockAccessorImpl extends AccessorImpl implements B public Builder from(BlockAccessor accessor) { level = accessor.getLevel(); player = accessor.getPlayer(); - connected = accessor.isServerConnected(); - showDetails = accessor.showDetails(); hit = accessor.getHitResult(); blockEntity = accessor::getBlockEntity; blockState = accessor.getBlockState(); @@ -132,15 +115,15 @@ public class BlockAccessorImpl extends AccessorImpl implements B public record SyncData(boolean showDetails, BlockHitResult hit, BlockState blockState, ItemStack fakeBlock) { public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.BOOL, - SyncData::showDetails, - StreamCodec.of(FriendlyByteBuf::writeBlockHitResult, FriendlyByteBuf::readBlockHitResult), - SyncData::hit, - ByteBufCodecs.idMapper(Block.BLOCK_STATE_REGISTRY), - SyncData::blockState, - ItemStack.OPTIONAL_STREAM_CODEC, - SyncData::fakeBlock, - SyncData::new + ByteBufCodecs.BOOL, + SyncData::showDetails, + StreamCodec.of(FriendlyByteBuf::writeBlockHitResult, FriendlyByteBuf::readBlockHitResult), + SyncData::hit, + ByteBufCodecs.idMapper(Block.BLOCK_STATE_REGISTRY), + SyncData::blockState, + ItemStack.OPTIONAL_STREAM_CODEC, + SyncData::fakeBlock, + SyncData::new ); public BlockAccessor unpack(ServerPlayer player) { @@ -149,13 +132,12 @@ public class BlockAccessorImpl extends AccessorImpl implements B blockEntity = Suppliers.memoize(() -> player.level().getBlockEntity(hit.getBlockPos())); } return new Builder() - .level(player.level()) - .player(player) - .showDetails(showDetails) - .hit(hit) - .blockState(blockState) - .blockEntity(blockEntity) - .build(); + .level(player.level()) + .player(player) + .hit(hit) + .blockState(blockState) + .blockEntity(blockEntity) + .build(); } } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessor.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessor.java index 454360d5..00fd87b7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessor.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessor.java @@ -23,8 +23,6 @@ public interface EntityAccessor extends Accessor { Builder player(Player player); - Builder showDetails(boolean showDetails); - default Builder hit(EntityHitResult hit) { return hit(() -> hit); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessorImpl.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessorImpl.java index 65d16c00..56166c62 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessorImpl.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessorImpl.java @@ -20,7 +20,7 @@ public class EntityAccessorImpl extends AccessorImpl implements private final Supplier entity; public EntityAccessorImpl(Builder builder) { - super(builder.level, builder.player, builder.hit, builder.connected, builder.showDetails); + super(builder.level, builder.player, builder.hit); entity = builder.entity; } @@ -41,11 +41,8 @@ public class EntityAccessorImpl extends AccessorImpl implements } public static class Builder implements EntityAccessor.Builder { - - public boolean showDetails; private Level level; private Player player; - private boolean connected; private Supplier hit; private Supplier entity; @@ -61,11 +58,6 @@ public class EntityAccessorImpl extends AccessorImpl implements return this; } - @Override - public Builder showDetails(boolean showDetails) { - this.showDetails = showDetails; - return this; - } @Override public Builder hit(Supplier hit) { @@ -83,8 +75,6 @@ public class EntityAccessorImpl extends AccessorImpl implements public Builder from(EntityAccessor accessor) { level = accessor.getLevel(); player = accessor.getPlayer(); - connected = accessor.isServerConnected(); - showDetails = accessor.showDetails(); hit = accessor::getHitResult; entity = accessor::getEntity; return this; @@ -98,26 +88,25 @@ public class EntityAccessorImpl extends AccessorImpl implements public record SyncData(boolean showDetails, int id, int partIndex, Vec3 hitVec) { public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.BOOL, - SyncData::showDetails, - ByteBufCodecs.VAR_INT, - SyncData::id, - ByteBufCodecs.VAR_INT, - SyncData::partIndex, - ByteBufCodecs.VECTOR3F.map(Vec3::new, Vec3::toVector3f), - SyncData::hitVec, - SyncData::new + ByteBufCodecs.BOOL, + SyncData::showDetails, + ByteBufCodecs.VAR_INT, + SyncData::id, + ByteBufCodecs.VAR_INT, + SyncData::partIndex, + ByteBufCodecs.VECTOR3F.map(Vec3::new, Vec3::toVector3f), + SyncData::hitVec, + SyncData::new ); public EntityAccessor unpack(ServerPlayer player) { Supplier entity = Suppliers.memoize(() -> CommonUtil.getPartEntity(player.level().getEntity(id), partIndex)); return new EntityAccessorImpl.Builder() - .level(player.level()) - .player(player) - .showDetails(showDetails) - .entity(entity) - .hit(Suppliers.memoize(() -> new EntityHitResult(entity.get(), hitVec))) - .build(); + .level(player.level()) + .player(player) + .entity(entity) + .hit(Suppliers.memoize(() -> new EntityHitResult(entity.get(), hitVec))) + .build(); } } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ClientHandshakePayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ClientHandshakePayload.java index 3d40670d..1620d68f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ClientHandshakePayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ClientHandshakePayload.java @@ -1,35 +1,19 @@ package org.leavesmc.leaves.protocol.jade.payload; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; -import org.leavesmc.leaves.protocol.core.ProtocolUtils; import org.leavesmc.leaves.protocol.jade.JadeProtocol; -public record ClientHandshakePayload(String protocolVersion) implements LeavesCustomPayload { +public record ClientHandshakePayload(String protocolVersion) implements LeavesCustomPayload { + @ID private static final ResourceLocation PACKET_CLIENT_HANDSHAKE = JadeProtocol.id("client_handshake"); + @Codec private static final StreamCodec CODEC = StreamCodec.composite( - ByteBufCodecs.STRING_UTF8, - ClientHandshakePayload::protocolVersion, - ClientHandshakePayload::new); - - @Override - public void write(FriendlyByteBuf buf) { - CODEC.encode(ProtocolUtils.decorate(buf), this); - } - - @Override - public ResourceLocation id() { - return PACKET_CLIENT_HANDSHAKE; - } - - @New - public static ClientHandshakePayload create(ResourceLocation location, FriendlyByteBuf buf) { - return CODEC.decode(ProtocolUtils.decorate(buf)); - } -} + ByteBufCodecs.STRING_UTF8, ClientHandshakePayload::protocolVersion, ClientHandshakePayload::new + ); +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ReceiveDataPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ReceiveDataPayload.java index 1b474ea8..b2630fca 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ReceiveDataPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ReceiveDataPayload.java @@ -2,27 +2,19 @@ package org.leavesmc.leaves.protocol.jade.payload; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; import org.leavesmc.leaves.protocol.jade.JadeProtocol; -public record ReceiveDataPayload(CompoundTag tag) implements LeavesCustomPayload { +public record ReceiveDataPayload(CompoundTag tag) implements LeavesCustomPayload { + @ID private static final ResourceLocation PACKET_RECEIVE_DATA = JadeProtocol.id("receive_data"); - @New - public ReceiveDataPayload(ResourceLocation id, FriendlyByteBuf buf) { - this(buf.readNbt()); - } - - @Override - public void write(@NotNull FriendlyByteBuf buf) { - buf.writeNbt(tag); - } - - @Override - public ResourceLocation id() { - return PACKET_RECEIVE_DATA; - } + @Codec + private static final StreamCodec CODEC = StreamCodec.composite( + ByteBufCodecs.COMPOUND_TAG, ReceiveDataPayload::tag, ReceiveDataPayload::new + ); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestBlockPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestBlockPayload.java index a152da5a..9d32bf29 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestBlockPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestBlockPayload.java @@ -1,15 +1,12 @@ package org.leavesmc.leaves.protocol.jade.payload; import io.netty.buffer.ByteBuf; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; -import org.leavesmc.leaves.protocol.core.ProtocolUtils; import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessorImpl; @@ -20,9 +17,12 @@ import java.util.Objects; import static org.leavesmc.leaves.protocol.jade.JadeProtocol.blockDataProviders; -public record RequestBlockPayload(BlockAccessorImpl.SyncData data, List<@Nullable IServerDataProvider> dataProviders) implements LeavesCustomPayload { +public record RequestBlockPayload(BlockAccessorImpl.SyncData data, List<@Nullable IServerDataProvider> dataProviders) implements LeavesCustomPayload { + @ID private static final ResourceLocation PACKET_REQUEST_BLOCK = JadeProtocol.id("request_block"); + + @Codec private static final StreamCodec CODEC = StreamCodec.composite( BlockAccessorImpl.SyncData.STREAM_CODEC, RequestBlockPayload::data, @@ -32,20 +32,4 @@ public record RequestBlockPayload(BlockAccessorImpl.SyncData data, List<@Nullabl $ -> Objects.requireNonNull(blockDataProviders.idMapper()).getIdOrThrow($))), RequestBlockPayload::dataProviders, RequestBlockPayload::new); - - @Override - public void write(FriendlyByteBuf buf) { - CODEC.encode(ProtocolUtils.decorate(buf), this); - } - - @Override - @NotNull - public ResourceLocation id() { - return PACKET_REQUEST_BLOCK; - } - - @New - public static RequestBlockPayload create(ResourceLocation location, FriendlyByteBuf buf) { - return CODEC.decode(ProtocolUtils.decorate(buf)); - } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestEntityPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestEntityPayload.java index e55bcda8..70dd289a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestEntityPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestEntityPayload.java @@ -1,15 +1,12 @@ package org.leavesmc.leaves.protocol.jade.payload; import io.netty.buffer.ByteBuf; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; -import org.leavesmc.leaves.protocol.core.ProtocolUtils; import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessor; import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessorImpl; @@ -20,9 +17,12 @@ import java.util.Objects; import static org.leavesmc.leaves.protocol.jade.JadeProtocol.entityDataProviders; -public record RequestEntityPayload(EntityAccessorImpl.SyncData data, List<@Nullable IServerDataProvider> dataProviders) implements LeavesCustomPayload { +public record RequestEntityPayload(EntityAccessorImpl.SyncData data, List<@Nullable IServerDataProvider> dataProviders) implements LeavesCustomPayload { + @ID private static final ResourceLocation PACKET_REQUEST_ENTITY = JadeProtocol.id("request_entity"); + + @Codec private static final StreamCodec CODEC = StreamCodec.composite( EntityAccessorImpl.SyncData.STREAM_CODEC, RequestEntityPayload::data, @@ -33,21 +33,4 @@ public record RequestEntityPayload(EntityAccessorImpl.SyncData data, List<@Nulla )), RequestEntityPayload::dataProviders, RequestEntityPayload::new); - - - @Override - public void write(FriendlyByteBuf buf) { - CODEC.encode(ProtocolUtils.decorate(buf), this); - } - - @Override - @NotNull - public ResourceLocation id() { - return PACKET_REQUEST_ENTITY; - } - - @New - public static RequestEntityPayload create(ResourceLocation location, FriendlyByteBuf buf) { - return CODEC.decode(ProtocolUtils.decorate(buf)); - } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ServerHandshakePayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ServerHandshakePayload.java index 9608dc99..4955e0e1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ServerHandshakePayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/ServerHandshakePayload.java @@ -4,14 +4,12 @@ package org.leavesmc.leaves.protocol.jade.payload; import com.google.common.collect.Maps; import io.netty.buffer.ByteBuf; import net.minecraft.core.registries.Registries; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; -import org.leavesmc.leaves.protocol.core.ProtocolUtils; import org.leavesmc.leaves.protocol.jade.JadeProtocol; import java.util.List; @@ -19,9 +17,12 @@ import java.util.Map; import static org.leavesmc.leaves.protocol.jade.util.JadeCodec.PRIMITIVE_STREAM_CODEC; -public record ServerHandshakePayload(Map serverConfig, List shearableBlocks, List blockProviderIds, List entityProviderIds) implements LeavesCustomPayload { +public record ServerHandshakePayload(Map serverConfig, List shearableBlocks, List blockProviderIds, List entityProviderIds) implements LeavesCustomPayload { + @ID private static final ResourceLocation PACKET_SERVER_HANDSHAKE = JadeProtocol.id("server_handshake"); + + @Codec private static final StreamCodec CODEC = StreamCodec.composite( ByteBufCodecs.map(Maps::newHashMapWithExpectedSize, ResourceLocation.STREAM_CODEC, PRIMITIVE_STREAM_CODEC), ServerHandshakePayload::serverConfig, @@ -31,21 +32,6 @@ public record ServerHandshakePayload(Map serverConfig, ServerHandshakePayload::blockProviderIds, ByteBufCodecs.list().apply(ResourceLocation.STREAM_CODEC), ServerHandshakePayload::entityProviderIds, - ServerHandshakePayload::new); - - @Override - public void write(FriendlyByteBuf buf) { - CODEC.encode(ProtocolUtils.decorate(buf), this); - } - - @Override - public ResourceLocation id() { - return PACKET_SERVER_HANDSHAKE; - } - - @New - public static ServerHandshakePayload create(ResourceLocation location, FriendlyByteBuf buf) { - return CODEC.decode(ProtocolUtils.decorate(buf)); - } -} - + ServerHandshakePayload::new + ); +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java index c9e00e50..a0916567 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java @@ -37,52 +37,6 @@ public enum ItemStorageExtensionProvider implements IServerExtensionProvider> getGroups(Accessor request) { - Object target = request.getTarget(); - - switch (target) { - case null -> { - return createItemCollector(request).update(request); - } - case RandomizableContainer te when te.getLootTable() != null -> { - return List.of(); - } - case ContainerEntity containerEntity when containerEntity.getContainerLootTable() != null -> { - return List.of(); - } - default -> { - } - } - - Player player = request.getPlayer(); - if (!player.isCreative() && !player.isSpectator() && target instanceof BaseContainerBlockEntity te) { - if (te.lockKey != LockCode.NO_LOCK) { - return List.of(); - } - } - - if (target instanceof EnderChestBlockEntity) { - PlayerEnderChestContainer inventory = player.getEnderChestInventory(); - return new ItemCollector<>(new ItemIterator.ContainerItemIterator(x -> inventory, 0)).update(request); - } - - ItemCollector itemCollector; - try { - itemCollector = targetCache.get(target, () -> createItemCollector(request)); - } catch (ExecutionException e) { - LeavesLogger.LOGGER.severe("Failed to get item collector for " + target); - return null; - } - - return itemCollector.update(request); - } - - @Override - public ResourceLocation getUid() { - return UNIVERSAL_ITEM_STORAGE; - } - public static ItemCollector createItemCollector(Accessor request) { if (request.getTarget() instanceof AbstractHorse) { return new ItemCollector<>(new ItemIterator.ContainerItemIterator(o -> { @@ -131,8 +85,54 @@ public enum ItemStorageExtensionProvider implements IServerExtensionProvider> getGroups(Accessor request) { + Object target = request.getTarget(); + + switch (target) { + case null -> { + return createItemCollector(request).update(request); + } + case RandomizableContainer te when te.getLootTable() != null -> { + return List.of(); + } + case ContainerEntity containerEntity when containerEntity.getContainerLootTable() != null -> { + return List.of(); + } + default -> { + } + } + + Player player = request.getPlayer(); + if (!player.isCreative() && !player.isSpectator() && target instanceof BaseContainerBlockEntity te) { + if (te.lockKey != LockCode.NO_LOCK) { + return List.of(); + } + } + + if (target instanceof EnderChestBlockEntity) { + PlayerEnderChestContainer inventory = player.getEnderChestInventory(); + return new ItemCollector<>(new ItemIterator.ContainerItemIterator(x -> inventory, 0)).update(request); + } + + ItemCollector itemCollector; + try { + itemCollector = targetCache.get(target, () -> createItemCollector(request)); + } catch (ExecutionException e) { + LeavesLogger.LOGGER.severe("Failed to get item collector for " + target); + return null; + } + + return itemCollector.update(request); + } + + @Override + public ResourceLocation getUid() { + return UNIVERSAL_ITEM_STORAGE; + } + @Override public int getDefaultPriority() { - return IServerExtensionProvider.super.getDefaultPriority() + 1000; + return 9999; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java index 8289b5c4..7d6cd6dd 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java @@ -24,8 +24,7 @@ import java.util.Map; public abstract class ItemStorageProvider> implements IServerDataProvider { - private static final StreamCodec>>> STREAM_CODEC = ViewGroup.listCodec( - ItemStack.OPTIONAL_STREAM_CODEC); + private static final StreamCodec>>> STREAM_CODEC = ViewGroup.listCodec(ItemStack.OPTIONAL_STREAM_CODEC); private static final ResourceLocation UNIVERSAL_ITEM_STORAGE = JadeProtocol.mc_id("item_storage"); @@ -37,14 +36,6 @@ public abstract class ItemStorageProvider> implements ISer return ForEntity.INSTANCE; } - public static class ForBlock extends ItemStorageProvider { - private static final ForBlock INSTANCE = new ForBlock(); - } - - public static class ForEntity extends ItemStorageProvider { - private static final ForEntity INSTANCE = new ForEntity(); - } - public static void putData(CompoundTag tag, @NotNull Accessor accessor) { Object target = accessor.getTarget(); Player player = accessor.getPlayer(); @@ -83,6 +74,14 @@ public abstract class ItemStorageProvider> implements ISer @Override public int getDefaultPriority() { - return 9999; + return 1000; + } + + public static class ForBlock extends ItemStorageProvider { + private static final ForBlock INSTANCE = new ForBlock(); + } + + public static class ForEntity extends ItemStorageProvider { + private static final ForEntity INSTANCE = new ForEntity(); } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/BlockNameProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/BlockNameProvider.java new file mode 100644 index 00000000..4904ef09 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/BlockNameProvider.java @@ -0,0 +1,60 @@ +package org.leavesmc.leaves.protocol.jade.provider.block; + +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentSerialization; +import net.minecraft.network.chat.contents.TranslatableContents; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.Nameable; +import net.minecraft.world.level.block.ChestBlock; +import net.minecraft.world.level.block.entity.ChestBlockEntity; +import net.minecraft.world.level.block.state.properties.ChestType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.leavesmc.leaves.protocol.jade.JadeProtocol; +import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; +import org.leavesmc.leaves.protocol.jade.provider.StreamServerDataProvider; + +public enum BlockNameProvider implements StreamServerDataProvider { + INSTANCE; + + private static final ResourceLocation CORE_OBJECT_NAME = JadeProtocol.id("object_name"); + + @Override + @Nullable + public Component streamData(@NotNull BlockAccessor accessor) { + if (!(accessor.getBlockEntity() instanceof Nameable nameable)) { + return null; + } + if (nameable instanceof ChestBlockEntity && accessor.getBlock() instanceof ChestBlock && accessor.getBlockState().getValue(ChestBlock.TYPE) != ChestType.SINGLE) { + MenuProvider menuProvider = accessor.getBlockState().getMenuProvider(accessor.getLevel(), accessor.getPosition()); + if (menuProvider != null) { + Component name = menuProvider.getDisplayName(); + if (!(name.getContents() instanceof TranslatableContents contents) || !"container.chestDouble".equals(contents.getKey())) { + return name; + } + } + } else if (nameable.hasCustomName()) { + return nameable.getDisplayName(); + } + return accessor.getBlockEntity().components().get(DataComponents.ITEM_NAME); + } + + @Override + public StreamCodec streamCodec() { + return ComponentSerialization.STREAM_CODEC; + } + + @Override + public ResourceLocation getUid() { + return CORE_OBJECT_NAME; + } + + @Override + public int getDefaultPriority() { + return -10100; + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/BrewingStandProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/BrewingStandProvider.java index e6f15f87..4266550e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/BrewingStandProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/BrewingStandProvider.java @@ -34,10 +34,10 @@ public enum BrewingStandProvider implements StreamServerDataProvider STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.VAR_INT, - Data::fuel, - ByteBufCodecs.VAR_INT, - Data::time, - Data::new); + ByteBufCodecs.VAR_INT, + Data::fuel, + ByteBufCodecs.VAR_INT, + Data::time, + Data::new); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ChiseledBookshelfProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ChiseledBookshelfProvider.java index bde872cc..12fdbc3c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ChiseledBookshelfProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ChiseledBookshelfProvider.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; +import org.leavesmc.leaves.protocol.jade.provider.ItemStorageProvider; import org.leavesmc.leaves.protocol.jade.provider.StreamServerDataProvider; public enum ChiseledBookshelfProvider implements StreamServerDataProvider { @@ -31,9 +32,13 @@ public enum ChiseledBookshelfProvider implements StreamServerDataProvider inventory) { public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.VAR_INT, - Data::progress, - ByteBufCodecs.VAR_INT, - Data::total, - ItemStack.OPTIONAL_LIST_STREAM_CODEC, - Data::inventory, - Data::new); + ByteBufCodecs.VAR_INT, + Data::progress, + ByteBufCodecs.VAR_INT, + Data::total, + ItemStack.OPTIONAL_LIST_STREAM_CODEC, + Data::inventory, + Data::new); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/HopperLockProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/HopperLockProvider.java index a3937081..2459acd4 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/HopperLockProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/HopperLockProvider.java @@ -29,4 +29,9 @@ public enum HopperLockProvider implements StreamServerDataProvider { - - private static final ResourceLocation CORE_OBJECT_NAME = JadeProtocol.id("object_name"); - - public static class ForBlock extends ObjectNameProvider implements StreamServerDataProvider { - public static final ForBlock INSTANCE = new ForBlock(); - - @Override - @Nullable - public Component streamData(@NotNull BlockAccessor accessor) { - if (!(accessor.getBlockEntity() instanceof Nameable nameable)) { - return null; - } - if (nameable instanceof ChestBlockEntity && accessor.getBlock() instanceof ChestBlock && accessor.getBlockState().getValue(ChestBlock.TYPE) != ChestType.SINGLE) { - MenuProvider menuProvider = accessor.getBlockState().getMenuProvider(accessor.getLevel(), accessor.getPosition()); - if (menuProvider != null) { - Component name = menuProvider.getDisplayName(); - if (!(name.getContents() instanceof TranslatableContents contents) || !"container.chestDouble".equals(contents.getKey())) { - return name; - } - } - } else if (nameable.hasCustomName()) { - return nameable.getDisplayName(); - } - return accessor.getBlockEntity().components().get(DataComponents.ITEM_NAME); - } - - @Override - public StreamCodec streamCodec() { - return ComponentSerialization.STREAM_CODEC; - } - } - - @Override - public ResourceLocation getUid() { - return CORE_OBJECT_NAME; - } - - @Override - public int getDefaultPriority() { - return -10100; - } -} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/AnimalOwnerProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/AnimalOwnerProvider.java index ff50ef60..495815a2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/AnimalOwnerProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/AnimalOwnerProvider.java @@ -5,6 +5,8 @@ import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityReference; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.OwnableEntity; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.protocol.jade.JadeProtocol; @@ -19,6 +21,16 @@ public enum AnimalOwnerProvider implements StreamServerDataProvider reference = ownableEntity.getOwnerReference(); + if (reference != null) { + return reference.getUUID(); + } + } + return null; + } + @Override public String streamData(@NotNull EntityAccessor accessor) { return CommonUtil.getLastKnownUsername(getOwnerUUID(accessor.getEntity())); @@ -29,13 +41,6 @@ public enum AnimalOwnerProvider implements StreamServerDataProvider 0 && time < max) { + tag.putInt("NextSniffIn", (int) time); + } } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/ShearsToolHandler.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/ShearsToolHandler.java index 6a9cd9f0..9bbe5168 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/ShearsToolHandler.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/ShearsToolHandler.java @@ -1,32 +1,37 @@ package org.leavesmc.leaves.protocol.jade.tool; -import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.item.component.Tool; import net.minecraft.world.level.block.state.BlockState; -import org.leavesmc.leaves.protocol.jade.JadeProtocol; import java.util.List; -public class ShearsToolHandler extends SimpleToolHandler { +public class ShearsToolHandler { private static final ShearsToolHandler INSTANCE = new ShearsToolHandler(); + private final List tools; + + public ShearsToolHandler() { + this.tools = List.of(Items.SHEARS.getDefaultInstance()); + } + public static ShearsToolHandler getInstance() { return INSTANCE; } - public ShearsToolHandler() { - super(JadeProtocol.id("shears"), List.of(Items.SHEARS.getDefaultInstance()), true); - } - - @Override - public ItemStack test(BlockState state, Level world, BlockPos pos) { - if (state.is(Blocks.TRIPWIRE)) { - return tools.getFirst(); + public ItemStack test(BlockState state) { + for (ItemStack toolItem : tools) { + if (toolItem.isCorrectToolForDrops(state)) { + return toolItem; + } + Tool tool = toolItem.get(DataComponents.TOOL); + if (tool != null && tool.getMiningSpeed(state) > tool.defaultMiningSpeed()) { + return toolItem; + } } - return super.test(state, world, pos); + return ItemStack.EMPTY; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/SimpleToolHandler.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/SimpleToolHandler.java deleted file mode 100644 index d45ecdb1..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/SimpleToolHandler.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.leavesmc.leaves.protocol.jade.tool; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import net.minecraft.core.BlockPos; -import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.component.Tool; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -public class SimpleToolHandler implements ToolHandler { - - protected final List tools = Lists.newArrayList(); - private final ResourceLocation uid; - private final boolean skipInstaBreakingBlock; - - protected SimpleToolHandler(ResourceLocation uid, @NotNull List tools, boolean skipInstaBreakingBlock) { - this.uid = uid; - Preconditions.checkArgument(!tools.isEmpty(), "tools cannot be empty"); - this.tools.addAll(tools); - this.skipInstaBreakingBlock = skipInstaBreakingBlock; - } - - @Contract("_, _ -> new") - public static @NotNull SimpleToolHandler create(ResourceLocation uid, List tools) { - return create(uid, tools, true); - } - - @Contract("_, _, _ -> new") - public static @NotNull SimpleToolHandler create(ResourceLocation uid, List tools, boolean skipInstaBreakingBlock) { - return new SimpleToolHandler(uid, Lists.transform(tools, Item::getDefaultInstance), skipInstaBreakingBlock); - } - - @Override - public ItemStack test(BlockState state, Level world, BlockPos pos) { - if (skipInstaBreakingBlock && !state.requiresCorrectToolForDrops() && state.getDestroySpeed(world, pos) == 0) { - return ItemStack.EMPTY; - } - return test(state); - } - - public ItemStack test(BlockState state) { - for (ItemStack toolItem : tools) { - if (toolItem.isCorrectToolForDrops(state)) { - return toolItem; - } - Tool tool = toolItem.get(DataComponents.TOOL); - if (tool != null && tool.getMiningSpeed(state) > tool.defaultMiningSpeed()) { - return toolItem; - } - } - return ItemStack.EMPTY; - } - - @Override - public List getTools() { - return tools; - } - - @Override - public ResourceLocation getUid() { - return uid; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/ToolHandler.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/ToolHandler.java deleted file mode 100644 index 18f11e70..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/tool/ToolHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.leavesmc.leaves.protocol.jade.tool; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import org.leavesmc.leaves.protocol.jade.provider.IJadeProvider; - -import java.util.List; - -public interface ToolHandler extends IJadeProvider { - - ItemStack test(BlockState state, Level world, BlockPos pos); - - List getTools(); - -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/CommonUtil.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/CommonUtil.java index 47701b17..4e48a268 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/CommonUtil.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/CommonUtil.java @@ -1,14 +1,11 @@ package org.leavesmc.leaves.protocol.jade.util; import com.mojang.authlib.GameProfile; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.boss.EnderDragonPart; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.SkullBlockEntity; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.protocol.jade.accessor.Accessor; @@ -21,10 +18,6 @@ import java.util.UUID; public class CommonUtil { - public static @NotNull ResourceLocation getId(Block block) { - return BuiltInRegistries.BLOCK.getKey(block); - } - public static Entity wrapPartEntityParent(Entity target) { if (target instanceof EnderDragonPart part) { return part.parentMob; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/HierarchyLookup.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/HierarchyLookup.java index 0b1a99db..b2736d7d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/HierarchyLookup.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/HierarchyLookup.java @@ -73,7 +73,7 @@ public class HierarchyLookup implements IHierarchyLooku return resultCache.get(clazz, () -> { List list = Lists.newArrayList(); getInternal(clazz, list); - list = ImmutableList.sortedCopyOf(Comparator.comparingInt(JadeProtocol.priorities::byValue), list); + list = ImmutableList.sortedCopyOf(COMPARATOR, list); if (singleton && !list.isEmpty()) { return ImmutableList.of(list.getFirst()); } @@ -135,5 +135,4 @@ public class HierarchyLookup implements IHierarchyLooku idMapper = createIdMapper(); } } - } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/IHierarchyLookup.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/IHierarchyLookup.java index 2e5ccafc..c160eaa7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/IHierarchyLookup.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/IHierarchyLookup.java @@ -4,15 +4,20 @@ import com.google.common.collect.Streams; import net.minecraft.core.IdMapper; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; +import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.provider.IJadeProvider; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Stream; public interface IHierarchyLookup { + + Comparator COMPARATOR = Comparator.comparingInt(provider -> JadeProtocol.priorities.byValue(provider)); + default IHierarchyLookup cast() { return this; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java index 68f93978..c23cb197 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java @@ -7,6 +7,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.item.component.TooltipDisplay; import org.leavesmc.leaves.protocol.jade.accessor.Accessor; import java.util.List; @@ -17,15 +18,17 @@ import java.util.function.Predicate; public class ItemCollector { public static final int MAX_SIZE = 54; public static final ItemCollector EMPTY = new ItemCollector<>(null); - private static final Predicate NON_EMPTY = stack -> { + private static final Predicate SHOWN = stack -> { if (stack.isEmpty()) { return false; } - CustomData customData = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY); - if (customData.contains("CustomModelData")) { - CompoundTag tag = customData.copyTag(); - for (String key : tag.getAllKeys()) { - if (key.toLowerCase(Locale.ENGLISH).endsWith("clear") && tag.getBoolean(key)) { + if (stack.getOrDefault(DataComponents.TOOLTIP_DISPLAY, TooltipDisplay.DEFAULT).hideTooltip()) { + return false; + } + if (stack.hasNonDefault(DataComponents.CUSTOM_MODEL_DATA) || stack.hasNonDefault(DataComponents.ITEM_MODEL)) { + CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); + for (String key : tag.keySet()) { + if (key.toLowerCase(Locale.ENGLISH).endsWith("clear") && tag.getBooleanOr(key, true)) { return false; } } @@ -65,7 +68,7 @@ public class ItemCollector { AtomicInteger count = new AtomicInteger(); iterator.populate(container).forEach(stack -> { count.incrementAndGet(); - if (NON_EMPTY.test(stack)) { + if (SHOWN.test(stack)) { ItemDefinition def = new ItemDefinition(stack); items.addTo(def, stack.getCount()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/LootTableMineableCollector.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/LootTableMineableCollector.java index 81575cfa..9c580ab3 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/LootTableMineableCollector.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/LootTableMineableCollector.java @@ -50,6 +50,25 @@ public class LootTableMineableCollector { return list; } + public static boolean isCorrectConditions(@NotNull List conditions, ItemStack toolItem) { + if (conditions.size() != 1) { + return false; + } + + LootItemCondition condition = conditions.getFirst(); + if (condition instanceof MatchTool(Optional predicate)) { + ItemPredicate itemPredicate = predicate.orElse(null); + return itemPredicate != null && itemPredicate.test(toolItem); + } else if (condition instanceof AnyOfCondition anyOfCondition) { + for (LootItemCondition child : anyOfCondition.terms) { + if (isCorrectConditions(List.of(child), toolItem)) { + return true; + } + } + } + return false; + } + private boolean doLootTable(LootTable lootTable) { if (lootTable == null || lootTable == LootTable.EMPTY) { return false; @@ -87,23 +106,4 @@ public class LootTableMineableCollector { } return false; } - - public static boolean isCorrectConditions(@NotNull List conditions, ItemStack toolItem) { - if (conditions.size() != 1) { - return false; - } - - LootItemCondition condition = conditions.getFirst(); - if (condition instanceof MatchTool(Optional predicate)) { - ItemPredicate itemPredicate = predicate.orElse(null); - return itemPredicate != null && itemPredicate.test(toolItem); - } else if (condition instanceof AnyOfCondition anyOfCondition) { - for (LootItemCondition child : anyOfCondition.terms) { - if (isCorrectConditions(List.of(child), toolItem)) { - return true; - } - } - } - return false; - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/PairHierarchyLookup.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/PairHierarchyLookup.java index 8069ee8e..9e0dd9cc 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/PairHierarchyLookup.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/PairHierarchyLookup.java @@ -9,11 +9,9 @@ import net.minecraft.resources.ResourceLocation; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesLogger; -import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.provider.IJadeProvider; import java.util.Collection; -import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -46,10 +44,7 @@ public class PairHierarchyLookup implements IHierarchyL } else if (secondList.isEmpty()) { return firstList; } - return ImmutableList.sortedCopyOf( - Comparator.comparingInt(JadeProtocol.priorities::byValue), - Iterables.concat(firstList, secondList) - ); + return ImmutableList.sortedCopyOf(COMPARATOR, Iterables.concat(firstList, secondList)); }); } catch (ExecutionException e) { LeavesLogger.LOGGER.severe(e.toString()); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ViewGroup.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ViewGroup.java index ef22f89d..56f3e4e2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ViewGroup.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ViewGroup.java @@ -12,6 +12,23 @@ import java.util.Map; import java.util.Optional; public class ViewGroup { + public List views; + @Nullable + public String id; + @Nullable + protected CompoundTag extraData; + + public ViewGroup(List views) { + this(views, Optional.empty(), Optional.empty()); + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + public ViewGroup(List views, Optional id, Optional extraData) { + this.views = views; + this.id = id.orElse(null); + this.extraData = extraData.orElse(null); + } + public static StreamCodec> codec(StreamCodec viewCodec) { return StreamCodec.composite( ByteBufCodecs.list().apply(viewCodec), @@ -32,31 +49,10 @@ public class ViewGroup { Map::entry); } - public List views; - @Nullable - public String id; - @Nullable - protected CompoundTag extraData; - - public ViewGroup(List views) { - this(views, Optional.empty(), Optional.empty()); - } - - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - public ViewGroup(List views, Optional id, Optional extraData) { - this.views = views; - this.id = id.orElse(null); - this.extraData = extraData.orElse(null); - } - public CompoundTag getExtraData() { if (extraData == null) { extraData = new CompoundTag(); } return extraData; } - - public void setProgress(float progress) { - getExtraData().putFloat("Progress", progress); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/WrappedHierarchyLookup.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/WrappedHierarchyLookup.java index 91bf986b..be8abe21 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/WrappedHierarchyLookup.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/WrappedHierarchyLookup.java @@ -1,6 +1,8 @@ package org.leavesmc.leaves.protocol.jade.util; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; import org.apache.commons.lang3.tuple.Pair; @@ -13,6 +15,7 @@ import org.leavesmc.leaves.protocol.jade.provider.IJadeProvider; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Function; import java.util.stream.Stream; @@ -38,15 +41,15 @@ public class WrappedHierarchyLookup extends HierarchyLo } public List wrappedGet(Accessor accessor) { - List list = Lists.newArrayList(); + Set set = Sets.newLinkedHashSet(); for (var override : overrides) { Object o = override.getRight().apply(accessor); if (o != null) { - list.addAll(override.getLeft().get(o)); + set.addAll(override.getLeft().get(o)); } } - list.addAll(get(accessor.getTarget())); - return list; + set.addAll(get(accessor.getTarget())); + return ImmutableList.sortedCopyOf(COMPARATOR, set); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/PacketTransformer.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/PacketTransformer.java index 242a84cd..fabd1f9e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/PacketTransformer.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/PacketTransformer.java @@ -1,8 +1,11 @@ package org.leavesmc.leaves.protocol.rei; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; +import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.protocol.common.custom.DiscardedPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import org.leavesmc.leaves.LeavesLogger; @@ -25,16 +28,10 @@ public class PacketTransformer { private final Map cache = Collections.synchronizedMap(new HashMap<>()); - private static class PartData { - private final ResourceLocation id; - private final int partsNum; - private final List parts; - - public PartData(ResourceLocation id, int partsNum) { - this.id = id; - this.partsNum = partsNum; - this.parts = new ArrayList<>(); - } + public static DiscardedPayload wrapRei(ResourceLocation location, FriendlyByteBuf buf) { + FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer()); + newBuf.writeByteArray(ByteBufUtil.getBytes(buf)); + return new DiscardedPayload(location, ByteBufUtil.getBytes(newBuf)); } public void inbound(ResourceLocation id, RegistryFriendlyByteBuf buf, ServerPlayer player, BiConsumer consumer) { @@ -135,4 +132,16 @@ public class PacketTransformer { buf.release(); } } + + private static class PartData { + private final ResourceLocation id; + private final int partsNum; + private final List parts; + + public PartData(ResourceLocation id, int partsNum) { + this.id = id; + this.partsNum = partsNum; + this.parts = new ArrayList<>(); + } + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/REIServerProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/REIServerProtocol.java index 1333d638..c6fb6241 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/REIServerProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/REIServerProtocol.java @@ -2,7 +2,6 @@ package org.leavesmc.leaves.protocol.rei; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import net.minecraft.ChatFormatting; import net.minecraft.Util; @@ -16,7 +15,6 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.SmithingTemplateItem; import net.minecraft.world.item.crafting.FireworkRocketRecipe; import net.minecraft.world.item.crafting.MapCloningRecipe; import net.minecraft.world.item.crafting.RecipeHolder; @@ -24,6 +22,7 @@ import net.minecraft.world.item.crafting.RecipeMap; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.crafting.ShapelessRecipe; +import net.minecraft.world.item.crafting.SmithingTransformRecipe; import net.minecraft.world.item.crafting.SmithingTrimRecipe; import net.minecraft.world.item.crafting.TippedArrowRecipe; import net.minecraft.world.item.crafting.TransmuteRecipe; @@ -45,7 +44,6 @@ import org.leavesmc.leaves.protocol.rei.display.ShapelessDisplay; import org.leavesmc.leaves.protocol.rei.display.SmeltingDisplay; import org.leavesmc.leaves.protocol.rei.display.SmokingDisplay; import org.leavesmc.leaves.protocol.rei.display.StoneCuttingDisplay; -import org.leavesmc.leaves.protocol.rei.payload.BufCustomPacketPayload; import org.leavesmc.leaves.protocol.rei.payload.DisplaySyncPayload; import java.util.HashSet; @@ -57,8 +55,8 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; -@LeavesProtocol(namespace = REIServerProtocol.PROTOCOL_ID) -public class REIServerProtocol { +@LeavesProtocol.Register(namespace = REIServerProtocol.PROTOCOL_ID) +public class REIServerProtocol implements LeavesProtocol { public static final String PROTOCOL_ID = "roughlyenoughitems"; public static final String CHEAT_PERMISSION = "leaves.protocol.rei.cheat"; @@ -79,15 +77,16 @@ public class REIServerProtocol { return builder.build(); }); private static final Set enabledPlayers = new HashSet<>(); - private static int minecraftRecipeVer = 0; - private static int nextReiRecipeVer = -1; - private static ImmutableList cachedPayloads; private static final Executor executor = new ThreadPoolExecutor( 1, 1, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.DiscardOldestPolicy() ); + private static int minecraftRecipeVer = 0; + private static int nextReiRecipeVer = -1; + private static ImmutableList cachedPayloads; + @ProtocolHandler.ReloadDataPack public static void onRecipeReload() { minecraftRecipeVer = MinecraftServer.getServer().getTickCount(); } @@ -111,17 +110,12 @@ public class REIServerProtocol { @ProtocolHandler.PlayerLeave public static void onPlayerLoggedOut(@NotNull ServerPlayer player) { - if (LeavesConfig.protocol.reiServerProtocol) { - enabledPlayers.remove(player); - } + enabledPlayers.remove(player); } @ProtocolHandler.Ticker public static void tick() { - if (!LeavesConfig.protocol.reiServerProtocol) { - return; - } - if (MinecraftServer.getServer().getTickCount() % 200 == 1 && minecraftRecipeVer != nextReiRecipeVer) { + if (minecraftRecipeVer != nextReiRecipeVer) { nextReiRecipeVer = minecraftRecipeVer; executor.execute(() -> reloadRecipe(nextReiRecipeVer)); } @@ -153,7 +147,7 @@ public class REIServerProtocol { recipeMap.byType(RecipeType.SMITHING).forEach(holder -> { switch (holder.value()) { case SmithingTrimRecipe ignored -> builder.addAll(Display.ofSmithingTrimRecipe((RecipeHolder) holder)); - case SmithingTemplateItem ignored -> builder.add(Display.ofTransforming((RecipeHolder) holder)); + case SmithingTransformRecipe ignored -> builder.add(Display.ofTransforming((RecipeHolder) holder)); default -> { } } @@ -168,8 +162,8 @@ public class REIServerProtocol { RegistryFriendlyByteBuf s2cBuf = ProtocolUtils.decorate(Unpooled.buffer()); DisplaySyncPayload.STREAM_CODEC.encode(s2cBuf, displaySyncPayload); ImmutableList.Builder listBuilder = ImmutableList.builder(); - outboundTransform(SYNC_DISPLAYS_PACKET, s2cBuf, (id, splitBuf) -> - listBuilder.add(new BufCustomPacketPayload(new CustomPacketPayload.Type<>(id), ByteBufUtil.getBytes(splitBuf))) + outboundTransform(s2cBuf, (id, splitBuf) -> + listBuilder.add(PacketTransformer.wrapRei(id, splitBuf)) ); cachedPayloads = listBuilder.build(); @@ -182,33 +176,29 @@ public class REIServerProtocol { }); } - @ProtocolHandler.MinecraftRegister(ignoreId = true) - public static void onPlayerSubscribed(@NotNull ServerPlayer player, String channel) { - if (!LeavesConfig.protocol.reiServerProtocol) { - return; - } + @ProtocolHandler.MinecraftRegister(onlyNamespace = true) + public static void onPlayerSubscribed(@NotNull ServerPlayer player, ResourceLocation location) { enabledPlayers.add(player); + String channel = location.getPath(); if (channel.equals("sync_displays")) { if (cachedPayloads != null) { cachedPayloads.forEach(payload -> ProtocolUtils.sendPayloadPacket(player, payload)); } } else if (channel.equals("ci_msg")) { // cheat rei-client into using "delete_item" packet - if (player.getServer().getProfilePermissions(player.getGameProfile()) < 1) { + if (MinecraftServer.getServer().getProfilePermissions(player.getGameProfile()) < 1) { player.getBukkitEntity().sendOpLevel((byte) 1); } } } - @ProtocolHandler.PayloadReceiver(payload = BufCustomPacketPayload.class, payloadId = "delete_item") - public static void handleDeleteItem(ServerPlayer player, BufCustomPacketPayload payload) { - if (!LeavesConfig.protocol.reiServerProtocol || !hasCheatPermission(player)) { + @ProtocolHandler.BytebufReceiver(key = "delete_item") + public static void handleDeleteItem(ServerPlayer player, RegistryFriendlyByteBuf buf) { + if (!hasCheatPermission(player)) { return; } - RegistryFriendlyByteBuf c2sBuf = ProtocolUtils.decorate(Unpooled.buffer()); - c2sBuf.writeBytes(payload.payload()); - inboundTransform(player, payload.id(), c2sBuf, (id, wholeBuf) -> { + inboundTransform(player, DELETE_ITEMS_PACKET, buf, (id, wholeBuf) -> { AbstractContainerMenu menu = player.containerMenu; if (!menu.getCarried().isEmpty()) { menu.setCarried(ItemStack.EMPTY); @@ -217,13 +207,11 @@ public class REIServerProtocol { }); } - @ProtocolHandler.PayloadReceiver(payload = BufCustomPacketPayload.class, payloadId = "create_item") - public static void handleCreateItem(ServerPlayer player, BufCustomPacketPayload payload) { - if (!LeavesConfig.protocol.reiServerProtocol || !hasCheatPermission(player)) { + @ProtocolHandler.BytebufReceiver(key = "create_item") + public static void handleCreateItem(ServerPlayer player, RegistryFriendlyByteBuf buf) { + if (!hasCheatPermission(player)) { return; } - RegistryFriendlyByteBuf c2sBuf = ProtocolUtils.decorate(Unpooled.buffer()); - c2sBuf.writeBytes(payload.payload()); BiConsumer consumer = (ignored, c2sWholeBuf) -> { FriendlyByteBuf tmpBuf = new FriendlyByteBuf(Unpooled.buffer()).writeBytes(c2sWholeBuf.readByteArray()); ItemStack itemStack = tmpBuf.readJsonWithCodec(ItemStack.OPTIONAL_CODEC); @@ -241,17 +229,14 @@ public class REIServerProtocol { player.displayClientMessage(Component.translatable("text.rei.failed_cheat_items"), false); } }; - inboundTransform(player, payload.id(), c2sBuf, consumer); + inboundTransform(player, CREATE_ITEMS_PACKET, buf, consumer); } - @ProtocolHandler.PayloadReceiver(payload = BufCustomPacketPayload.class, payloadId = "create_item_grab") - public static void handleCreateItemGrab(ServerPlayer player, BufCustomPacketPayload payload) { - if (!LeavesConfig.protocol.reiServerProtocol || !hasCheatPermission(player)) { + @ProtocolHandler.BytebufReceiver(key = "create_item_grab") + public static void handleCreateItemGrab(ServerPlayer player, RegistryFriendlyByteBuf buf) { + if (!hasCheatPermission(player)) { return; } - RegistryFriendlyByteBuf c2sBuf = ProtocolUtils.decorate(Unpooled.buffer()); - c2sBuf.writeBytes(payload.payload()); - BiConsumer consumer = (ignored, c2sWholeBuf) -> { FriendlyByteBuf tmpBuf = new FriendlyByteBuf(Unpooled.buffer()).writeBytes(c2sWholeBuf.readByteArray()); ItemStack itemStack = tmpBuf.readJsonWithCodec(ItemStack.OPTIONAL_CODEC); @@ -274,23 +259,21 @@ public class REIServerProtocol { }); */ }; - inboundTransform(player, payload.id(), c2sBuf, consumer); + inboundTransform(player, CREATE_ITEMS_GRAB_PACKET, buf, consumer); } - @ProtocolHandler.PayloadReceiver(payload = BufCustomPacketPayload.class, payloadId = "create_item_hotbar") - public static void handleCreateItemHotbar(ServerPlayer player, BufCustomPacketPayload payload) { - if (!LeavesConfig.protocol.reiServerProtocol || !hasCheatPermission(player)) { + @ProtocolHandler.BytebufReceiver(key = "create_item_hotbar") + public static void handleCreateItemHotbar(ServerPlayer player, RegistryFriendlyByteBuf buf) { + if (!hasCheatPermission(player)) { return; } - RegistryFriendlyByteBuf c2sBuf = ProtocolUtils.decorate(Unpooled.buffer()); - c2sBuf.writeBytes(payload.payload()); BiConsumer consumer = (ignored, c2sWholeBuf) -> { FriendlyByteBuf tmpBuf = new FriendlyByteBuf(Unpooled.buffer()).writeBytes(c2sWholeBuf.readByteArray()); ItemStack stack = tmpBuf.readJsonWithCodec(ItemStack.OPTIONAL_CODEC); int hotbarSlotId = tmpBuf.readVarInt(); if (hotbarSlotId >= 0 && hotbarSlotId < 9) { AbstractContainerMenu menu = player.containerMenu; - player.getInventory().items.set(hotbarSlotId, stack.copy()); + player.getInventory().getNonEquipmentItems().set(hotbarSlotId, stack.copy()); menu.broadcastChanges(); RegistryFriendlyByteBuf s2cWholeBuf = ProtocolUtils.decorate(Unpooled.buffer()); s2cWholeBuf.writeJsonWithCodec(ItemStack.OPTIONAL_CODEC, stack.copy()); @@ -305,13 +288,15 @@ public class REIServerProtocol { player.displayClientMessage(Component.translatable("text.rei.failed_cheat_items"), false); } }; - inboundTransform(player, payload.id(), c2sBuf, consumer); + inboundTransform(player, CREATE_ITEMS_HOTBAR_PACKET, buf, consumer); } - private static void inboundTransform(ServerPlayer player, - ResourceLocation id, - RegistryFriendlyByteBuf buf, - BiConsumer consumer) { + @ProtocolHandler.BytebufReceiver(key = "move_items_new") + public static void handleMoveItem(ServerPlayer player, RegistryFriendlyByteBuf buf) { + // TODO handle to disable REI client warning + } + + private static void inboundTransform(ServerPlayer player, ResourceLocation id, RegistryFriendlyByteBuf buf, BiConsumer consumer) { PacketTransformer transformer = TRANSFORMERS.get(id); if (transformer != null) { transformer.inbound(id, buf, player, consumer); @@ -320,14 +305,12 @@ public class REIServerProtocol { } } - private static void outboundTransform(ResourceLocation id, - RegistryFriendlyByteBuf buf, - BiConsumer consumer) { - PacketTransformer transformer = TRANSFORMERS.get(id); + private static void outboundTransform(RegistryFriendlyByteBuf buf, BiConsumer consumer) { + PacketTransformer transformer = TRANSFORMERS.get(SYNC_DISPLAYS_PACKET); if (transformer != null) { - transformer.outbound(id, buf, consumer); + transformer.outbound(SYNC_DISPLAYS_PACKET, buf, consumer); } else { - consumer.accept(id, buf); + consumer.accept(SYNC_DISPLAYS_PACKET, buf); } } @@ -338,4 +321,14 @@ public class REIServerProtocol { player.displayClientMessage(Component.translatable("text.rei.no_permission_cheat").withStyle(ChatFormatting.RED), false); return false; } + + @Override + public boolean isActive() { + return LeavesConfig.protocol.reiServerProtocol; + } + + @Override + public int tickerInterval(String tickerID) { + return 200; + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/BlastingDisplay.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/BlastingDisplay.java index 47f6e133..8a7d00af 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/BlastingDisplay.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/BlastingDisplay.java @@ -5,12 +5,12 @@ import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; public class BlastingDisplay extends CookingDisplay { + private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/blasting"); + public BlastingDisplay(RecipeHolder recipe) { super(recipe); } - private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/blasting"); - @Override public ResourceLocation getSerializerId() { return SERIALIZER_ID; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CampfireDisplay.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CampfireDisplay.java index b9234cc9..a097770b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CampfireDisplay.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CampfireDisplay.java @@ -5,12 +5,12 @@ import net.minecraft.world.item.crafting.CampfireCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; public class CampfireDisplay extends CookingDisplay { + private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/campfire"); + public CampfireDisplay(RecipeHolder recipe) { super(recipe); } - private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/campfire"); - @Override public ResourceLocation getSerializerId() { return SERIALIZER_ID; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CookingDisplay.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CookingDisplay.java index e530e980..0aba2c03 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CookingDisplay.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CookingDisplay.java @@ -16,9 +16,6 @@ import java.util.List; import java.util.Optional; public abstract class CookingDisplay extends Display { - protected float xp; - protected double cookTime; - private static final StreamCodec CODEC = StreamCodec.composite( EntryIngredient.CODEC.apply(ByteBufCodecs.list()), CookingDisplay::getInputEntries, @@ -32,6 +29,8 @@ public abstract class CookingDisplay extends Display { CookingDisplay::getCookTime, CookingDisplay::of ); + protected float xp; + protected double cookTime; private CookingDisplay(@NotNull List inputs, @NotNull List outputs, @NotNull ResourceLocation id, float xp, double cookTime) { super(inputs, outputs, id); @@ -49,6 +48,11 @@ public abstract class CookingDisplay extends Display { ); } + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static CookingDisplay of(@NotNull List inputs, @NotNull List outputs, @NotNull Optional id, float xp, double cookTime) { + throw new UnsupportedOperationException(); + } + public float getXp() { return xp; } @@ -60,9 +64,4 @@ public abstract class CookingDisplay extends Display { public StreamCodec streamCodec() { return CODEC; } - - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private static CookingDisplay of(@NotNull List inputs, @NotNull List outputs, @NotNull Optional id, float xp, double cookTime) { - throw new UnsupportedOperationException(); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CustomDisplay.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CustomDisplay.java index 3c2d892f..c98be664 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CustomDisplay.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/CustomDisplay.java @@ -12,9 +12,6 @@ import java.util.List; import java.util.Optional; public class CustomDisplay extends CraftingDisplay { - private final int width; - private final int height; - private static final StreamCodec CODEC = StreamCodec.composite( EntryIngredient.CODEC.apply(ByteBufCodecs.list()), CustomDisplay::getInputEntries, @@ -24,8 +21,9 @@ public class CustomDisplay extends CraftingDisplay { CustomDisplay::getOptionalLocation, CustomDisplay::of ); - private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/crafting/custom"); + private final int width; + private final int height; /** * see me.shedaniel.rei.plugin.common.displays.crafting.DefaultCustomDisplay#DefaultCustomDisplay @@ -46,6 +44,11 @@ public class CustomDisplay extends CraftingDisplay { this.height = row.cardinality(); } + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static CustomDisplay of(@NotNull List inputs, @NotNull List outputs, @NotNull Optional id) { + throw new UnsupportedOperationException(); + } + @Override public int getWidth() { return width; @@ -64,9 +67,4 @@ public class CustomDisplay extends CraftingDisplay { public StreamCodec streamCodec() { return CODEC; } - - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private static CustomDisplay of(@NotNull List inputs, @NotNull List outputs, @NotNull Optional id) { - throw new UnsupportedOperationException(); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/Display.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/Display.java index 81f64a63..3e7b9197 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/Display.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/Display.java @@ -21,6 +21,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.item.component.Fireworks; +import net.minecraft.world.item.component.ProvidesTrimMaterial; import net.minecraft.world.item.crafting.FireworkRocketRecipe; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.MapCloningRecipe; @@ -34,11 +35,7 @@ import net.minecraft.world.item.crafting.display.ShapedCraftingRecipeDisplay; import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay; import net.minecraft.world.item.crafting.display.SlotDisplay; import net.minecraft.world.item.crafting.display.SlotDisplayContext; -import net.minecraft.world.item.equipment.trim.ArmorTrim; import net.minecraft.world.item.equipment.trim.TrimMaterial; -import net.minecraft.world.item.equipment.trim.TrimMaterials; -import net.minecraft.world.item.equipment.trim.TrimPattern; -import net.minecraft.world.item.equipment.trim.TrimPatterns; import net.minecraft.world.level.ItemLike; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.protocol.rei.ingredient.EntryIngredient; @@ -73,22 +70,6 @@ public abstract class Display { this.id = id; } - public List getInputEntries() { - return inputs; - } - - public List getOutputEntries() { - return outputs; - } - - public ResourceLocation getDisplayLocation() { - return id; - } - - public Optional getOptionalLocation() { - return Optional.ofNullable(id); - } - @SuppressWarnings("unchecked") public static StreamCodec dispatchCodec() { return new StreamCodec<>() { @@ -106,10 +87,6 @@ public abstract class Display { }; } - public abstract ResourceLocation getSerializerId(); - - public abstract StreamCodec streamCodec(); - public static Collection ofTransmuteRecipe(@NotNull RecipeHolder recipeHolder) { TransmuteRecipe recipe = recipeHolder.value(); List displays = recipe.display(); @@ -192,15 +169,13 @@ public abstract class Display { */ @NotNull public static SmithingDisplay ofTransforming(RecipeHolder recipeHolder) { - - return new SmithingDisplay( List.of( recipeHolder.value().templateIngredient().map(EntryIngredient::ofIngredient).orElse(EntryIngredient.empty()), - recipeHolder.value().baseIngredient().map(EntryIngredient::ofIngredient).orElse(EntryIngredient.empty()), + EntryIngredient.ofIngredient(recipeHolder.value().baseIngredient()), recipeHolder.value().additionIngredient().map(EntryIngredient::ofIngredient).orElse(EntryIngredient.empty()) ), - List.of(EntryIngredient.of(recipeHolder.value().getResult())), + List.of(ofSlotDisplay(recipeHolder.value().getResult())), SmithingDisplay.SmithingRecipeType.TRANSFORM, recipeHolder.id().location() ); @@ -209,62 +184,30 @@ public abstract class Display { /** * see me.shedaniel.rei.plugin.common.displays.DefaultSmithingDisplay#fromTrimming */ + @SuppressWarnings("deprecation") @NotNull public static Collection ofSmithingTrimRecipe(@NotNull RecipeHolder recipeHolder) { RegistryAccess registryAccess = MinecraftServer.getServer().registryAccess(); SmithingTrimRecipe recipe = recipeHolder.value(); List displays = new ArrayList<>(); - for (Holder templateItem : (Iterable>) recipe.templateIngredient().map(Ingredient::items).orElse(Stream.of())::iterator) { - Holder.Reference trimPattern = getPatternFromTemplate(registryAccess, templateItem) - .orElse(null); - if (trimPattern == null) continue; + for (Holder additionStack : (Iterable>) recipe.additionIngredient().map(Ingredient::items).orElse(Stream.of())::iterator) { + Holder trimMaterial = getMaterialFromIngredient(registryAccess, additionStack).orElse(null); + if (trimMaterial == null) continue; - for (Holder additionStack : (Iterable>) recipe.additionIngredient().map(Ingredient::items).orElse(Stream.of())::iterator) { - Holder.Reference trimMaterial = getMaterialFromIngredient(registryAccess, additionStack) - .orElse(null); - if (trimMaterial == null) continue; + EntryIngredient baseIngredient = EntryIngredient.ofIngredient(recipe.baseIngredient()); + displays.add(new SmithingDisplay.Trimming(List.of( + recipe.templateIngredient().map(EntryIngredient::ofIngredient).orElse(EntryIngredient.empty()), + baseIngredient, + EntryIngredient.ofItemHolder(additionStack) + ), List.of(baseIngredient), SmithingDisplay.SmithingRecipeType.TRIM, recipeHolder.id().location(), recipe.pattern())); - EntryIngredient baseIngredient = recipe.baseIngredient().map(EntryIngredient::ofIngredient).orElse(EntryIngredient.empty()); - EntryIngredient templateOutput = baseIngredient.isEmpty() ? EntryIngredient.empty() - : getTrimmingOutput(registryAccess, templateItem.value().getDefaultInstance(), baseIngredient.get(0), additionStack.value().getDefaultInstance()); - - displays.add(new SmithingDisplay(List.of( - EntryIngredient.ofItemHolder(templateItem), - baseIngredient, - EntryIngredient.ofItemHolder(additionStack) - ), List.of(templateOutput), SmithingDisplay.SmithingRecipeType.TRIM, recipeHolder.id().location())); - } } return displays; } - public static EntryIngredient getTrimmingOutput(RegistryAccess registryAccess, ItemStack templateItem, ItemStack baseItem, ItemStack additionItem) { - Holder.Reference trimPattern = TrimPatterns.getFromTemplate(registryAccess, templateItem) - .orElse(null); - if (trimPattern == null) return EntryIngredient.empty(); - Holder.Reference trimMaterial = TrimMaterials.getFromIngredient(registryAccess, additionItem) - .orElse(null); - if (trimMaterial == null) return EntryIngredient.empty(); - ArmorTrim armorTrim = new ArmorTrim(trimMaterial, trimPattern); - ArmorTrim trim = baseItem.get(DataComponents.TRIM); - if (trim != null && trim.hasPatternAndMaterial(trimPattern, trimMaterial)) return EntryIngredient.empty(); - ItemStack newItem = baseItem.copyWithCount(1); - newItem.set(DataComponents.TRIM, armorTrim); - return EntryIngredient.of(newItem); - } - - private static Optional> getPatternFromTemplate(HolderLookup.Provider provider, Holder item) { - return provider.lookupOrThrow(Registries.TRIM_PATTERN) - .listElements() - .filter(reference -> item == reference.value().templateItem()) - .findFirst(); - } - - private static Optional> getMaterialFromIngredient(HolderLookup.Provider provider, Holder item) { - return provider.lookupOrThrow(Registries.TRIM_MATERIAL) - .listElements() - .filter(reference -> item == reference.value().ingredient()) - .findFirst(); + private static Optional> getMaterialFromIngredient(HolderLookup.Provider provider, Holder item) { + ProvidesTrimMaterial providesTrimMaterial = new ItemStack(item).get(DataComponents.PROVIDES_TRIM_MATERIAL); + return providesTrimMaterial != null ? providesTrimMaterial.unwrap(provider) : Optional.empty(); } public static EntryIngredient ofSlotDisplay(SlotDisplay slot) { @@ -324,4 +267,24 @@ public abstract class Display { } return EntryIngredient.of(stackList.toArray(new ItemStack[0])); } + + public List getInputEntries() { + return inputs; + } + + public List getOutputEntries() { + return outputs; + } + + public ResourceLocation getDisplayLocation() { + return id; + } + + public Optional getOptionalLocation() { + return Optional.ofNullable(id); + } + + public abstract ResourceLocation getSerializerId(); + + public abstract StreamCodec streamCodec(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/ShapedDisplay.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/ShapedDisplay.java index cf09b72c..8f38955c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/ShapedDisplay.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/ShapedDisplay.java @@ -20,10 +20,6 @@ import java.util.Optional; * see me.shedaniel.rei.plugin.common.displays.crafting.DefaultShapedDisplay#DefaultShapedDisplay(RecipeHolder) */ public class ShapedDisplay extends CraftingDisplay { - private final int width; - - private final int height; - private static final StreamCodec CODEC = StreamCodec.composite( EntryIngredient.CODEC.apply(ByteBufCodecs.list()), CraftingDisplay::getInputEntries, @@ -37,8 +33,9 @@ public class ShapedDisplay extends CraftingDisplay { CraftingDisplay::getHeight, ShapedDisplay::of ); - private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/crafting/shaped"); + private final int width; + private final int height; public ShapedDisplay(@NotNull RecipeHolder recipeHolder) { super( @@ -60,6 +57,23 @@ public class ShapedDisplay extends CraftingDisplay { this.height = recipeDisplay.height(); } + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static CraftingDisplay of(List inputs, List outputs, Optional location, int width, int height) { + throw new UnsupportedOperationException(); + } + + private static List ofIngredient(ShapedRecipe recipe) { + return recipe.getIngredients().stream().map(ingredient -> { + if (ingredient.isEmpty()) { + return EntryIngredient.empty(); + } + ItemStack[] itemStacks = ingredient.get().items() + .map(itemHolder -> new ItemStack(itemHolder, 1)) + .toArray(ItemStack[]::new); + return EntryIngredient.of(itemStacks); + }).toList(); + } + @Override public int getWidth() { return width; @@ -78,21 +92,4 @@ public class ShapedDisplay extends CraftingDisplay { public StreamCodec streamCodec() { return CODEC; } - - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private static CraftingDisplay of(List inputs, List outputs, Optional location, int width, int height) { - throw new UnsupportedOperationException(); - } - - private static List ofIngredient(ShapedRecipe recipe) { - return recipe.getIngredients().stream().map(ingredient -> { - if (ingredient.isEmpty()) { - return EntryIngredient.empty(); - } - ItemStack[] itemStacks = ingredient.get().items() - .map(itemHolder -> new ItemStack(itemHolder, 1)) - .toArray(ItemStack[]::new); - return EntryIngredient.of(itemStacks); - }).toList(); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/ShapelessDisplay.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/ShapelessDisplay.java index b8e42d1e..f458901a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/ShapelessDisplay.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/ShapelessDisplay.java @@ -51,6 +51,11 @@ public class ShapelessDisplay extends CraftingDisplay { ); } + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static CraftingDisplay of(List inputs, List outputs, Optional location) { + throw new NotImplementedException(); + } + @Override public int getWidth() { return getInputEntries().size() > 4 ? 3 : 2; @@ -69,9 +74,4 @@ public class ShapelessDisplay extends CraftingDisplay { public StreamCodec streamCodec() { return CODEC; } - - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private static CraftingDisplay of(List inputs, List outputs, Optional location) { - throw new NotImplementedException(); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmeltingDisplay.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmeltingDisplay.java index 7d9923ee..e22a93b0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmeltingDisplay.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmeltingDisplay.java @@ -5,12 +5,12 @@ import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.SmeltingRecipe; public class SmeltingDisplay extends CookingDisplay { + private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/smelting"); + public SmeltingDisplay(RecipeHolder recipe) { super(recipe); } - private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/smelting"); - @Override public ResourceLocation getSerializerId() { return SERIALIZER_ID; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmithingDisplay.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmithingDisplay.java index cda51825..59f5ab5c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmithingDisplay.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmithingDisplay.java @@ -2,11 +2,13 @@ package org.leavesmc.leaves.protocol.rei.display; import com.mojang.serialization.Codec; import io.netty.buffer.ByteBuf; +import net.minecraft.core.Holder; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ByIdMap; +import net.minecraft.world.item.equipment.trim.TrimPattern; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.protocol.rei.ingredient.EntryIngredient; @@ -31,20 +33,6 @@ public class SmithingDisplay extends Display { private final SmithingRecipeType type; - public Optional getOptionalType() { - return Optional.of(type); - } - - @Override - public ResourceLocation getSerializerId() { - return SERIALIZER_ID; - } - - @Override - public StreamCodec streamCodec() { - return CODEC; - } - public SmithingDisplay( @NotNull List inputs, @NotNull List outputs, @@ -60,6 +48,20 @@ public class SmithingDisplay extends Display { throw new UnsupportedOperationException(); } + public Optional getOptionalType() { + return Optional.of(type); + } + + @Override + public ResourceLocation getSerializerId() { + return SERIALIZER_ID; + } + + @Override + public StreamCodec streamCodec() { + return CODEC; + } + public enum SmithingRecipeType { TRIM, TRANSFORM, @@ -69,4 +71,54 @@ public class SmithingDisplay extends Display { public static final IntFunction BY_ID = ByIdMap.continuous(Enum::ordinal, values(), ByIdMap.OutOfBoundsStrategy.ZERO); public static final StreamCodec STREAM_CODEC = ByteBufCodecs.idMapper(BY_ID, Enum::ordinal); } + + public static class Trimming extends SmithingDisplay { + private static final StreamCodec CODEC = StreamCodec.composite( + EntryIngredient.CODEC.apply(ByteBufCodecs.list()), + SmithingDisplay.Trimming::getInputEntries, + EntryIngredient.CODEC.apply(ByteBufCodecs.list()), + SmithingDisplay.Trimming::getOutputEntries, + ByteBufCodecs.optional(SmithingRecipeType.STREAM_CODEC), + SmithingDisplay.Trimming::getOptionalType, + ByteBufCodecs.optional(ResourceLocation.STREAM_CODEC), + SmithingDisplay.Trimming::getOptionalLocation, + TrimPattern.STREAM_CODEC, + SmithingDisplay.Trimming::pattern, + SmithingDisplay.Trimming::of + ); + + private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/smithing/trimming"); + + private final Holder pattern; + + public Trimming( + @NotNull List inputs, + @NotNull List outputs, + @NotNull SmithingRecipeType type, + @NotNull ResourceLocation location, + @NotNull Holder pattern + ) { + super(inputs, outputs, type, location); + this.pattern = pattern; + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + public static Trimming of(List inputs, List outputs, Optional type, Optional location, Holder pattern) { + throw new UnsupportedOperationException(); + } + + @Override + public ResourceLocation getSerializerId() { + return SERIALIZER_ID; + } + + @Override + public StreamCodec streamCodec() { + return CODEC; + } + + public Holder pattern() { + return pattern; + } + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmokingDisplay.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmokingDisplay.java index f858a65e..b4504d39 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmokingDisplay.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/SmokingDisplay.java @@ -5,12 +5,12 @@ import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; public class SmokingDisplay extends CookingDisplay { + private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/smoking"); + public SmokingDisplay(RecipeHolder recipe) { super(recipe); } - private static final ResourceLocation SERIALIZER_ID = ResourceLocation.tryBuild("minecraft", "default/smoking"); - @Override public ResourceLocation getSerializerId() { return SERIALIZER_ID; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/StoneCuttingDisplay.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/StoneCuttingDisplay.java index dcea6a34..83d34f14 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/StoneCuttingDisplay.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/display/StoneCuttingDisplay.java @@ -43,6 +43,11 @@ public class StoneCuttingDisplay extends Display { ); } + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private static StoneCuttingDisplay of(@NotNull List inputs, @NotNull List outputs, @NotNull Optional id) { + throw new UnsupportedOperationException(); + } + @Override public ResourceLocation getSerializerId() { return SERIALIZER_ID; @@ -52,9 +57,4 @@ public class StoneCuttingDisplay extends Display { public StreamCodec streamCodec() { return CODEC; } - - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private static StoneCuttingDisplay of(@NotNull List inputs, @NotNull List outputs, @NotNull Optional id) { - throw new UnsupportedOperationException(); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/ingredient/EntryIngredient.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/ingredient/EntryIngredient.java index 6be33031..80d3cdd1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/ingredient/EntryIngredient.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/ingredient/EntryIngredient.java @@ -19,6 +19,7 @@ import java.util.stream.Stream; public class EntryIngredient { private static final StreamCodec> ITEM_STREAM_CODEC = ByteBufCodecs.holderRegistry(Registries.ITEM); + private static final ResourceLocation ITEM_ID = ResourceLocation.withDefaultNamespace("item"); public static final StreamCodec CODEC = new StreamCodec<>() { @NotNull @Override @@ -41,38 +42,18 @@ public class EntryIngredient { }); } }; - - private static final ResourceLocation ITEM_ID = ResourceLocation.withDefaultNamespace("item"); - + private static final EntryIngredient EMPTY = new EntryIngredient(new ItemStack[0]); @NotNull private final ItemStack[] array; - private static final EntryIngredient EMPTY = new EntryIngredient(new ItemStack[0]); - private EntryIngredient(@NotNull ItemStack[] array) { this.array = Objects.requireNonNull(array); } - public Stream stream() { - return Arrays.stream(array); - } - public static EntryIngredient empty() { return EMPTY; } - public boolean isEmpty() { - return array.length == 0; - } - - public ItemStack get(int index) { - return array[index].copy(); - } - - public int size() { - return array.length; - } - public static EntryIngredient ofItemHolder(@NotNull Holder item) { return EntryIngredient.of(item.value()); } @@ -89,13 +70,30 @@ public class EntryIngredient { return new EntryIngredient(Arrays.copyOf(itemStacks, itemStacks.length)); } + @SuppressWarnings("deprecation") public static EntryIngredient ofIngredient(Ingredient ingredient) { if (ingredient.isEmpty()) { return EntryIngredient.empty(); } ItemStack[] itemStacks = ingredient.items() - .map(itemHolder -> new ItemStack(itemHolder, 1)) + .map(itemHolder -> itemHolder.value().getDefaultInstance()) .toArray(ItemStack[]::new); return EntryIngredient.of(itemStacks); } + + public Stream stream() { + return Arrays.stream(array); + } + + public boolean isEmpty() { + return array.length == 0; + } + + public ItemStack get(int index) { + return array[index].copy(); + } + + public int size() { + return array.length; + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/payload/BufCustomPacketPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/payload/BufCustomPacketPayload.java deleted file mode 100644 index 08092a37..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/payload/BufCustomPacketPayload.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.leavesmc.leaves.protocol.rei.payload; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; - -public record BufCustomPacketPayload( - Type type, - byte[] payload -) implements LeavesCustomPayload { - @New - public static BufCustomPacketPayload create(ResourceLocation location, @NotNull FriendlyByteBuf buf) { - return new BufCustomPacketPayload(new Type<>(location), buf.readByteArray()); - } - - @Override - public void write(FriendlyByteBuf buf) { - FriendlyByteBuf.writeByteArray(buf, this.payload); - } - - @Override - public ResourceLocation id() { - return type.id(); - } - - @NotNull - @Override - public Type type() { - return type; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/payload/DisplaySyncPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/payload/DisplaySyncPayload.java index f779c3c2..0a1f4179 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/payload/DisplaySyncPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/payload/DisplaySyncPayload.java @@ -6,11 +6,10 @@ import io.netty.buffer.Unpooled; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; -import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.util.ByIdMap; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesLogger; -import org.leavesmc.leaves.protocol.rei.REIServerProtocol; +import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; import org.leavesmc.leaves.protocol.rei.display.Display; import java.util.ArrayList; @@ -19,12 +18,13 @@ import java.util.Objects; import java.util.function.IntFunction; import java.util.function.UnaryOperator; +// This payload will never be sent to the client. We use PacketTransformer to send split payload. public record DisplaySyncPayload( SyncType syncType, Collection displays, long version -) implements CustomPacketPayload { - public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>(REIServerProtocol.SYNC_DISPLAYS_PACKET); +) implements LeavesCustomPayload { + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( SyncType.STREAM_CODEC, DisplaySyncPayload::syncType, @@ -62,11 +62,6 @@ public record DisplaySyncPayload( DisplaySyncPayload::new ); - @Override - @NotNull - public Type type() { - return TYPE; - } public enum SyncType { APPEND, diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/PacketSplitter.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/PacketSplitter.java index 3a0e790f..b0a568ee 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/PacketSplitter.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/PacketSplitter.java @@ -67,6 +67,10 @@ public class PacketSplitter { return READING_SESSIONS.computeIfAbsent(key, ReadingSession::new).receive(buf, maxLength); } + public interface IPacketSplitterHandler { + void encode(ServerPlayer player, FriendlyByteBuf buf); + } + /** * I had to fix the `Pair.of` key mappings, because they were removed from MC; * So I made it into a pre-shared random session 'key' between client and server. @@ -110,8 +114,4 @@ public class PacketSplitter { return null; } } - - public interface IPacketSplitterHandler { - void encode(ServerPlayer player, FriendlyByteBuf buf); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxEntityDataProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxEntityDataProtocol.java index 36cc207c..89f454e2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxEntityDataProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxEntityDataProtocol.java @@ -5,6 +5,7 @@ import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -24,29 +25,20 @@ import java.util.UUID; // Powered by Servux(https://github.com/sakura-ryoko/servux) -@LeavesProtocol(namespace = "servux") -public class ServuxEntityDataProtocol { +@LeavesProtocol.Register(namespace = "servux") +public class ServuxEntityDataProtocol implements LeavesProtocol { - public static final ResourceLocation CHANNEL = ServuxProtocol.id("entity_data"); public static final int PROTOCOL_VERSION = 1; private static final Map readingSessionKeys = new HashMap<>(); @ProtocolHandler.PlayerJoin - public static void onPlayerLoggedIn(ServerPlayer player) { - if (!LeavesConfig.protocol.servux.entityProtocol) { - return; - } - + public static void onPlayerJoin(ServerPlayer player) { sendMetadata(player); } - @ProtocolHandler.PayloadReceiver(payload = EntityDataPayload.class, payloadId = "entity_data") + @ProtocolHandler.PayloadReceiver(payload = EntityDataPayload.class) public static void onPacketReceive(ServerPlayer player, EntityDataPayload payload) { - if (!LeavesConfig.protocol.servux.entityProtocol) { - return; - } - switch (payload.packetType) { case PACKET_C2S_METADATA_REQUEST -> sendMetadata(player); case PACKET_C2S_BLOCK_ENTITY_REQUEST -> onBlockEntityRequest(player, payload.pos); @@ -75,7 +67,7 @@ public class ServuxEntityDataProtocol { public static void sendMetadata(ServerPlayer player) { CompoundTag metadata = new CompoundTag(); metadata.putString("name", "entity_data"); - metadata.putString("id", CHANNEL.toString()); + metadata.putString("id", EntityDataPayload.CHANNEL.toString()); metadata.putInt("version", PROTOCOL_VERSION); metadata.putString("servux", ServuxProtocol.SERVUX_STRING); @@ -109,10 +101,6 @@ public class ServuxEntityDataProtocol { } public static void sendPacket(ServerPlayer player, EntityDataPayload payload) { - if (!LeavesConfig.protocol.servux.entityProtocol) { - return; - } - if (payload.packetType == EntityDataPayloadType.PACKET_S2C_NBT_RESPONSE_START) { FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); buffer.writeNbt(payload.nbt); @@ -129,6 +117,11 @@ public class ServuxEntityDataProtocol { sendPacket(player, payload); } + @Override + public boolean isActive() { + return LeavesConfig.protocol.servux.entityProtocol; + } + public enum EntityDataPayloadType { PACKET_S2C_METADATA(1), PACKET_C2S_METADATA_REQUEST(2), @@ -143,10 +136,6 @@ public class ServuxEntityDataProtocol { PACKET_C2S_NBT_RESPONSE_START(12), PACKET_C2S_NBT_RESPONSE_DATA(13); - private static final class Helper { - static Map ID_TO_TYPE = new HashMap<>(); - } - public final int type; EntityDataPayloadType(int type) { @@ -157,9 +146,85 @@ public class ServuxEntityDataProtocol { public static EntityDataPayloadType fromId(int id) { return EntityDataPayloadType.Helper.ID_TO_TYPE.get(id); } + + private static final class Helper { + static Map ID_TO_TYPE = new HashMap<>(); + } } - public static class EntityDataPayload implements LeavesCustomPayload { + public static class EntityDataPayload implements LeavesCustomPayload { + + @ID + public static final ResourceLocation CHANNEL = ServuxProtocol.id("entity_data"); + + @Codec + public static final StreamCodec CODEC = StreamCodec.of( + (buf, payload) -> { + buf.writeVarInt(payload.packetType.type); + switch (payload.packetType) { + case PACKET_C2S_BLOCK_ENTITY_REQUEST -> { + buf.writeVarInt(payload.transactionId); + buf.writeBlockPos(payload.pos); + } + case PACKET_C2S_ENTITY_REQUEST -> { + buf.writeVarInt(payload.transactionId); + buf.writeVarInt(payload.entityId); + } + case PACKET_S2C_BLOCK_NBT_RESPONSE_SIMPLE -> { + buf.writeBlockPos(payload.pos); + buf.writeNbt(payload.nbt); + } + case PACKET_S2C_ENTITY_NBT_RESPONSE_SIMPLE -> { + buf.writeVarInt(payload.entityId); + buf.writeNbt(payload.nbt); + } + case PACKET_S2C_NBT_RESPONSE_DATA, PACKET_C2S_NBT_RESPONSE_DATA -> buf.writeBytes(payload.buffer.readBytes(payload.buffer.readableBytes())); + case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA -> buf.writeNbt(payload.nbt); + } + }, + buf -> { + EntityDataPayloadType type = EntityDataPayloadType.fromId(buf.readVarInt()); + if (type == null) { + throw new IllegalStateException("invalid packet type received"); + } + EntityDataPayload payload = new EntityDataPayload(type); + switch (type) { + case PACKET_C2S_BLOCK_ENTITY_REQUEST -> { + buf.readVarInt(); + payload.pos = buf.readBlockPos().immutable(); + } + case PACKET_C2S_ENTITY_REQUEST -> { + buf.readVarInt(); + payload.entityId = buf.readVarInt(); + } + case PACKET_S2C_BLOCK_NBT_RESPONSE_SIMPLE -> { + payload.pos = buf.readBlockPos().immutable(); + CompoundTag nbt = buf.readNbt(); + if (nbt != null) { + payload.nbt.merge(nbt); + } + } + case PACKET_S2C_ENTITY_NBT_RESPONSE_SIMPLE -> { + payload.entityId = buf.readVarInt(); + CompoundTag nbt = buf.readNbt(); + if (nbt != null) { + payload.nbt.merge(nbt); + } + } + case PACKET_S2C_NBT_RESPONSE_DATA, PACKET_C2S_NBT_RESPONSE_DATA -> { + payload.buffer = new FriendlyByteBuf(buf.readBytes(buf.readableBytes())); + payload.nbt = new CompoundTag(); + } + case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA -> { + CompoundTag nbt = buf.readNbt(); + if (nbt != null) { + payload.nbt.merge(nbt); + } + } + } + return payload; + } + ); private final EntityDataPayloadType packetType; private final int transactionId; @@ -183,96 +248,5 @@ public class ServuxEntityDataProtocol { this.buffer = new FriendlyByteBuf(Unpooled.buffer()); } } - - @New - public static EntityDataPayload decode(ResourceLocation location, FriendlyByteBuf buffer) { - EntityDataPayloadType type = EntityDataPayloadType.fromId(buffer.readVarInt()); - if (type == null) { - throw new IllegalStateException("invalid packet type received"); - } - - EntityDataPayload payload = new EntityDataPayload(type); - switch (type) { - case PACKET_C2S_BLOCK_ENTITY_REQUEST -> { - buffer.readVarInt(); - payload.pos = buffer.readBlockPos().immutable(); - } - - case PACKET_C2S_ENTITY_REQUEST -> { - buffer.readVarInt(); - payload.entityId = buffer.readVarInt(); - } - - case PACKET_S2C_BLOCK_NBT_RESPONSE_SIMPLE -> { - payload.pos = buffer.readBlockPos().immutable(); - CompoundTag nbt = buffer.readNbt(); - if (nbt != null) { - payload.nbt.merge(nbt); - } - } - - case PACKET_S2C_ENTITY_NBT_RESPONSE_SIMPLE -> { - payload.entityId = buffer.readVarInt(); - CompoundTag nbt = buffer.readNbt(); - if (nbt != null) { - payload.nbt.merge(nbt); - } - } - - case PACKET_S2C_NBT_RESPONSE_DATA, PACKET_C2S_NBT_RESPONSE_DATA -> { - payload.buffer = new FriendlyByteBuf(buffer.readBytes(buffer.readableBytes())); - payload.nbt = new CompoundTag(); - } - - case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA -> { - CompoundTag nbt = buffer.readNbt(); - if (nbt != null) { - payload.nbt.merge(nbt); - } - } - } - - return payload; - } - - @Override - public void write(FriendlyByteBuf buf) { - buf.writeVarInt(this.packetType.type); - - switch (this.packetType) { - case PACKET_C2S_BLOCK_ENTITY_REQUEST -> { - buf.writeVarInt(this.transactionId); - buf.writeBlockPos(this.pos); - } - - case PACKET_C2S_ENTITY_REQUEST -> { - buf.writeVarInt(this.transactionId); - buf.writeVarInt(this.entityId); - } - - case PACKET_S2C_BLOCK_NBT_RESPONSE_SIMPLE -> { - buf.writeBlockPos(this.pos); - buf.writeNbt(this.nbt); - } - - case PACKET_S2C_ENTITY_NBT_RESPONSE_SIMPLE -> { - buf.writeVarInt(this.entityId); - buf.writeNbt(this.nbt); - } - - case PACKET_S2C_NBT_RESPONSE_DATA, PACKET_C2S_NBT_RESPONSE_DATA -> { - buf.writeBytes(this.buffer.readBytes(this.buffer.readableBytes())); - } - - case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA -> { - buf.writeNbt(this.nbt); - } - } - } - - @Override - public ResourceLocation id() { - return CHANNEL; - } } -} +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxHudDataProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxHudDataProtocol.java index 78b45989..f0091b49 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxHudDataProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxHudDataProtocol.java @@ -8,6 +8,7 @@ import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.Tag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; @@ -28,10 +29,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -@LeavesProtocol(namespace = "servux") -public class ServuxHudDataProtocol { +@LeavesProtocol.Register(namespace = "servux") +public class ServuxHudDataProtocol implements LeavesProtocol { - public static final ResourceLocation CHANNEL = ServuxProtocol.id("hud_metadata"); public static final int PROTOCOL_VERSION = 1; private static final List players = new ArrayList<>(); @@ -39,19 +39,15 @@ public class ServuxHudDataProtocol { public static boolean refreshSpawnMetadata = false; - @ProtocolHandler.PayloadReceiver(payload = HudDataPayload.class, payloadId = "hud_metadata") + @ProtocolHandler.PayloadReceiver(payload = HudDataPayload.class) public static void onPacketReceive(ServerPlayer player, HudDataPayload payload) { - if (!LeavesConfig.protocol.servux.hudMetadataProtocol) { - return; - } - switch (payload.packetType) { case PACKET_C2S_METADATA_REQUEST -> { players.add(player); CompoundTag metadata = new CompoundTag(); metadata.putString("name", "hud_metadata"); - metadata.putString("id", CHANNEL.toString()); + metadata.putString("id", HudDataPayload.CHANNEL.toString()); metadata.putInt("version", PROTOCOL_VERSION); metadata.putString("servux", ServuxProtocol.SERVUX_STRING); putWorldData(metadata); @@ -64,32 +60,9 @@ public class ServuxHudDataProtocol { } } - @ProtocolHandler.Ticker - public void onTick() { - if (!LeavesConfig.protocol.servux.hudMetadataProtocol) { - return; - } - - MinecraftServer server = MinecraftServer.getServer(); - int tickCounter = server.getTickCount(); - if ((tickCounter % updateInterval) == 0) { - for (ServerPlayer player : players) { - if (refreshSpawnMetadata) { - refreshSpawnMetadata(player); - } - refreshWeatherData(player); - } - refreshSpawnMetadata = false; - } - } - public static void refreshSpawnMetadata(ServerPlayer player) { - if (!LeavesConfig.protocol.servux.hudMetadataProtocol) { - return; - } - CompoundTag metadata = new CompoundTag(); - metadata.putString("id", CHANNEL.toString()); + metadata.putString("id", HudDataPayload.CHANNEL.toString()); metadata.putString("servux", ServuxProtocol.SERVUX_STRING); putWorldData(metadata); @@ -97,10 +70,6 @@ public class ServuxHudDataProtocol { } public static void refreshRecipeManager(ServerPlayer player) { - if (!LeavesConfig.protocol.servux.hudMetadataProtocol) { - return; - } - Collection> recipes = player.server.getRecipeManager().getRecipes(); CompoundTag nbt = new CompoundTag(); ListTag list = new ListTag(); @@ -122,17 +91,13 @@ public class ServuxHudDataProtocol { } public static void refreshWeatherData(ServerPlayer player) { - if (!LeavesConfig.protocol.servux.hudMetadataProtocol) { - return; - } - ServerLevel level = MinecraftServer.getServer().overworld(); if (level.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE)) { return; } CompoundTag nbt = new CompoundTag(); - nbt.putString("id", CHANNEL.toString()); + nbt.putString("id", HudDataPayload.CHANNEL.toString()); nbt.putString("servux", ServuxProtocol.SERVUX_STRING); if (level.serverLevelData.isRaining() && level.serverLevelData.getRainTime() > -1) { @@ -170,10 +135,6 @@ public class ServuxHudDataProtocol { } public static void sendPacket(ServerPlayer player, HudDataPayload payload) { - if (!LeavesConfig.protocol.servux.hudMetadataProtocol) { - return; - } - if (payload.packetType == HudDataPayloadType.PACKET_S2C_NBT_RESPONSE_START) { FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); buffer.writeNbt(payload.nbt); @@ -187,6 +148,27 @@ public class ServuxHudDataProtocol { sendPacket(player, new HudDataPayload(HudDataPayloadType.PACKET_S2C_NBT_RESPONSE_DATA, buf)); } + @ProtocolHandler.Ticker + public void onTick() { + for (ServerPlayer player : players) { + if (refreshSpawnMetadata) { + refreshSpawnMetadata(player); + } + refreshWeatherData(player); + } + refreshSpawnMetadata = false; + } + + @Override + public boolean isActive() { + return LeavesConfig.protocol.servux.hudMetadataProtocol; + } + + @Override + public int tickerInterval(String tickerID) { + return updateInterval; + } + public enum HudDataPayloadType { PACKET_S2C_METADATA(1), PACKET_C2S_METADATA_REQUEST(2), @@ -198,10 +180,6 @@ public class ServuxHudDataProtocol { PACKET_S2C_NBT_RESPONSE_START(10), PACKET_S2C_NBT_RESPONSE_DATA(11); - private static final class Helper { - static Map ID_TO_TYPE = new HashMap<>(); - } - public final int type; HudDataPayloadType(int type) { @@ -212,9 +190,44 @@ public class ServuxHudDataProtocol { public static HudDataPayloadType fromId(int id) { return HudDataPayloadType.Helper.ID_TO_TYPE.get(id); } + + private static final class Helper { + static Map ID_TO_TYPE = new HashMap<>(); + } } - public record HudDataPayload(HudDataPayloadType packetType, CompoundTag nbt, FriendlyByteBuf buffer) implements LeavesCustomPayload { + public record HudDataPayload(HudDataPayloadType packetType, CompoundTag nbt, FriendlyByteBuf buffer) implements LeavesCustomPayload { + + @ID + public static final ResourceLocation CHANNEL = ServuxProtocol.id("hud_metadata"); + + @Codec + public static final StreamCodec CODEC = StreamCodec.of( + (buf, payload) -> { + buf.writeVarInt(payload.packetType().type); + switch (payload.packetType()) { + case PACKET_S2C_NBT_RESPONSE_DATA -> buf.writeBytes(payload.buffer().copy()); + case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA, PACKET_C2S_SPAWN_DATA_REQUEST, + PACKET_S2C_SPAWN_DATA, PACKET_S2C_WEATHER_TICK, PACKET_C2S_RECIPE_MANAGER_REQUEST -> buf.writeNbt(payload.nbt()); + } + }, + buf -> { + HudDataPayloadType type = HudDataPayloadType.fromId(buf.readVarInt()); + if (type == null) { + throw new IllegalStateException("invalid packet type received"); + } + switch (type) { + case PACKET_S2C_NBT_RESPONSE_DATA -> { + return new HudDataPayload(type, new FriendlyByteBuf(buf.readBytes(buf.readableBytes()))); + } + case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA, PACKET_C2S_SPAWN_DATA_REQUEST, PACKET_S2C_SPAWN_DATA, PACKET_S2C_WEATHER_TICK, + PACKET_C2S_RECIPE_MANAGER_REQUEST -> { + return new HudDataPayload(type, buf.readNbt()); + } + } + throw new IllegalStateException("invalid packet type received"); + } + ); public HudDataPayload(HudDataPayloadType type, CompoundTag nbt) { this(type, nbt, null); @@ -224,42 +237,5 @@ public class ServuxHudDataProtocol { this(type, new CompoundTag(), buffer); } - @New - @NotNull - public static HudDataPayload decode(ResourceLocation location, @NotNull FriendlyByteBuf buf) { - HudDataPayloadType type = HudDataPayloadType.fromId(buf.readVarInt()); - if (type == null) { - throw new IllegalStateException("invalid packet type received"); - } - - switch (type) { - case PACKET_S2C_NBT_RESPONSE_DATA -> { - return new HudDataPayload(type, new FriendlyByteBuf(buf.readBytes(buf.readableBytes()))); - } - - case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA, PACKET_C2S_SPAWN_DATA_REQUEST, PACKET_S2C_SPAWN_DATA, PACKET_S2C_WEATHER_TICK, - PACKET_C2S_RECIPE_MANAGER_REQUEST -> { - return new HudDataPayload(type, buf.readNbt()); - } - } - - throw new IllegalStateException("invalid packet type received"); - } - - @Override - public void write(@NotNull FriendlyByteBuf buf) { - buf.writeVarInt(this.packetType.type); - - switch (this.packetType) { - case PACKET_S2C_NBT_RESPONSE_DATA -> buf.writeBytes(this.buffer.copy()); - case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA, PACKET_C2S_SPAWN_DATA_REQUEST, - PACKET_S2C_SPAWN_DATA, PACKET_S2C_WEATHER_TICK, PACKET_C2S_RECIPE_MANAGER_REQUEST -> buf.writeNbt(this.nbt); - } - } - - @Override - public ResourceLocation id() { - return CHANNEL; - } } -} +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxStructuresProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxStructuresProtocol.java index 9902dc66..7eae9cc7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxStructuresProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxStructuresProtocol.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; @@ -36,22 +37,17 @@ import java.util.concurrent.ConcurrentHashMap; // Powered by Servux(https://github.com/sakura-ryoko/servux) -@LeavesProtocol(namespace = "servux") -public class ServuxStructuresProtocol { +@LeavesProtocol.Register(namespace = "servux") +public class ServuxStructuresProtocol implements LeavesProtocol { public static final int PROTOCOL_VERSION = 2; - private static final int updateInterval = 40; private static final int timeout = 30 * 20; - - private static int retainDistance; - - public static final ResourceLocation CHANNEL = ServuxProtocol.id("structures"); - private static final Map players = new ConcurrentHashMap<>(); private static final Map> timeouts = new HashMap<>(); + private static int retainDistance; - @ProtocolHandler.PayloadReceiver(payload = StructuresPayload.class, payloadId = "structures") + @ProtocolHandler.PayloadReceiver(payload = StructuresPayload.class) public static void onPacketReceive(ServerPlayer player, StructuresPayload payload) { if (!LeavesConfig.protocol.servux.structureProtocol) { return; @@ -139,7 +135,7 @@ public class ServuxStructuresProtocol { MinecraftServer server = MinecraftServer.getServer(); CompoundTag tag = new CompoundTag(); tag.putString("name", "structure_bounding_boxes"); - tag.putString("id", CHANNEL.toString()); + tag.putString("id", StructuresPayload.CHANNEL.toString()); tag.putInt("version", PROTOCOL_VERSION); tag.putString("servux", ServuxProtocol.SERVUX_STRING); tag.putInt("timeout", timeout); @@ -313,6 +309,29 @@ public class ServuxStructuresProtocol { } } + public static void sendPacket(ServerPlayer player, StructuresPayload payload) { + if (!LeavesConfig.protocol.servux.structureProtocol) { + return; + } + + if (payload.packetType() == StructuresPayloadType.PACKET_S2C_STRUCTURE_DATA_START) { + FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); + buffer.writeNbt(payload.nbt()); + PacketSplitter.send(ServuxStructuresProtocol::sendWithSplitter, buffer, player); + } else { + ProtocolUtils.sendPayloadPacket(player, payload); + } + } + + private static void sendWithSplitter(ServerPlayer player, FriendlyByteBuf buf) { + sendPacket(player, new StructuresPayload(StructuresPayloadType.PACKET_S2C_STRUCTURE_DATA, buf)); + } + + @Override + public boolean isActive() { + return LeavesConfig.protocol.servux.structureProtocol; + } + public enum StructuresPayloadType { PACKET_S2C_METADATA(1), PACKET_S2C_STRUCTURE_DATA(2), @@ -322,10 +341,6 @@ public class ServuxStructuresProtocol { PACKET_S2C_SPAWN_METADATA(10), PACKET_C2S_REQUEST_SPAWN_METADATA(11); - private static final class Helper { - static Map ID_TO_TYPE = new HashMap<>(); - } - public final int type; StructuresPayloadType(int type) { @@ -336,9 +351,39 @@ public class ServuxStructuresProtocol { public static StructuresPayloadType fromId(int id) { return Helper.ID_TO_TYPE.get(id); } + + private static final class Helper { + static Map ID_TO_TYPE = new HashMap<>(); + } } - public record StructuresPayload(StructuresPayloadType packetType, CompoundTag nbt, FriendlyByteBuf buffer) implements LeavesCustomPayload { + public record StructuresPayload(StructuresPayloadType packetType, CompoundTag nbt, FriendlyByteBuf buffer) implements LeavesCustomPayload { + + @ID + public static final ResourceLocation CHANNEL = ServuxProtocol.id("structures"); + + @Codec + public static final StreamCodec CODEC = StreamCodec.of( + (buf, payload) -> { + buf.writeVarInt(payload.packetType().type); + if (payload.packetType().equals(StructuresPayloadType.PACKET_S2C_STRUCTURE_DATA)) { + buf.writeBytes(payload.buffer().readBytes(payload.buffer().readableBytes())); + } else { + buf.writeNbt(payload.nbt()); + } + }, + buf -> { + int i = buf.readVarInt(); + StructuresPayloadType type = StructuresPayloadType.fromId(i); + if (type == null) { + throw new IllegalStateException("invalid packet type received"); + } else if (type.equals(StructuresPayloadType.PACKET_S2C_STRUCTURE_DATA)) { + return new StructuresPayload(type, new FriendlyByteBuf(buf.readBytes(buf.readableBytes()))); + } else { + return new StructuresPayload(type, buf.readNbt()); + } + } + ); public StructuresPayload(StructuresPayloadType packetType, CompoundTag nbt) { this(packetType, nbt, null); @@ -347,35 +392,6 @@ public class ServuxStructuresProtocol { public StructuresPayload(StructuresPayloadType packetType, FriendlyByteBuf buffer) { this(packetType, new CompoundTag(), buffer); } - - @New - private static StructuresPayload decode(ResourceLocation id, FriendlyByteBuf buf) { - int i = buf.readVarInt(); - StructuresPayloadType type = StructuresPayloadType.fromId(i); - - if (type == null) { - throw new IllegalStateException("invalid packet type received"); - } else if (type.equals(StructuresPayloadType.PACKET_S2C_STRUCTURE_DATA)) { - return new StructuresPayload(type, new FriendlyByteBuf(buf.readBytes(buf.readableBytes()))); - } else { - return new StructuresPayload(type, buf.readNbt()); - } - } - - @Override - public void write(FriendlyByteBuf buf) { - buf.writeVarInt(this.packetType.type); - if (this.packetType.equals(StructuresPayloadType.PACKET_S2C_STRUCTURE_DATA)) { - buf.writeBytes(this.buffer.readBytes(this.buffer.readableBytes())); - } else { - buf.writeNbt(this.nbt); - } - } - - @Override - public ResourceLocation id() { - return CHANNEL; - } } public static class Timeout { @@ -393,22 +409,4 @@ public class ServuxStructuresProtocol { this.lastSync = tickCounter; } } - - public static void sendPacket(ServerPlayer player, StructuresPayload payload) { - if (!LeavesConfig.protocol.servux.structureProtocol) { - return; - } - - if (payload.packetType() == StructuresPayloadType.PACKET_S2C_STRUCTURE_DATA_START) { - FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); - buffer.writeNbt(payload.nbt()); - PacketSplitter.send(ServuxStructuresProtocol::sendWithSplitter, buffer, player); - } else { - ProtocolUtils.sendPayloadPacket(player, payload); - } - } - - private static void sendWithSplitter(ServerPlayer player, FriendlyByteBuf buf) { - sendPacket(player, new StructuresPayload(StructuresPayloadType.PACKET_S2C_STRUCTURE_DATA, buf)); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/LitematicaSchematic.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/LitematicaSchematic.java index 4a799efa..88b2aebe 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/LitematicaSchematic.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/LitematicaSchematic.java @@ -8,6 +8,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.LongArrayTag; import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; @@ -39,6 +40,38 @@ public record LitematicaSchematic(Map subRegions, SchematicMe public static final int MINECRAFT_DATA_VERSION = SharedConstants.getProtocolVersion(); public static final int SCHEMATIC_VERSION = 7; + @NotNull + @Contract("_ -> new") + public static LitematicaSchematic readFromNBT(@NotNull CompoundTag nbt) { + if (nbt.contains("Version")) { + final int version = nbt.getIntOr("Version", -1); + final int minecraftDataVersion = nbt.contains("MinecraftDataVersion") ? nbt.getInt("MinecraftDataVersion").orElseThrow() : SharedConstants.getProtocolVersion(); + + if (version >= 1 && version <= SCHEMATIC_VERSION) { + SchematicMetadata metadata = SchematicMetadata.readFromNBT(nbt.getCompoundOrEmpty("Metadata"), version, minecraftDataVersion, FileType.LITEMATICA_SCHEMATIC); + Map subRegions = readSubRegionsFromNBT(nbt.getCompoundOrEmpty("Regions"), version, minecraftDataVersion); + return new LitematicaSchematic(subRegions, metadata); + } else { + throw new RuntimeException("Unsupported or future schematic version"); + } + } else { + throw new RuntimeException("The schematic doesn't have version information, and can't be safely loaded!"); + } + } + + @NotNull + private static Map readSubRegionsFromNBT(@NotNull CompoundTag tag, int version, int minecraftDataVersion) { + Map subRegions = new HashMap<>(); + for (String regionName : tag.keySet()) { + Tag region = tag.get(regionName); + if (region == null || region.getId() != Tag.TAG_COMPOUND) { + throw new RuntimeException("Unknown region: " + regionName); + } + subRegions.put(regionName, SubRegion.readFromNBT(tag.getCompoundOrEmpty(regionName), version, minecraftDataVersion)); + } + return subRegions; + } + @NotNull @Unmodifiable public Map getAreaSizes() { @@ -54,38 +87,6 @@ public record LitematicaSchematic(Map subRegions, SchematicMe return Objects.requireNonNull(subRegions.get(name)); } - @NotNull - @Contract("_ -> new") - public static LitematicaSchematic readFromNBT(@NotNull CompoundTag nbt) { - if (nbt.contains("Version", Tag.TAG_INT)) { - final int version = nbt.getInt("Version"); - final int minecraftDataVersion = nbt.contains("MinecraftDataVersion") ? nbt.getInt("MinecraftDataVersion") : SharedConstants.getProtocolVersion(); - - if (version >= 1 && version <= SCHEMATIC_VERSION) { - SchematicMetadata metadata = SchematicMetadata.readFromNBT(nbt.getCompound("Metadata"), version, minecraftDataVersion, FileType.LITEMATICA_SCHEMATIC); - Map subRegions = readSubRegionsFromNBT(nbt.getCompound("Regions"), version, minecraftDataVersion); - return new LitematicaSchematic(subRegions, metadata); - } else { - throw new RuntimeException("Unsupported or future schematic version"); - } - } else { - throw new RuntimeException("The schematic doesn't have version information, and can't be safely loaded!"); - } - } - - @NotNull - private static Map readSubRegionsFromNBT(@NotNull CompoundTag tag, int version, int minecraftDataVersion) { - Map subRegions = new HashMap<>(); - for (String regionName : tag.getAllKeys()) { - Tag region = tag.get(regionName); - if (region == null || region.getId() != Tag.TAG_COMPOUND) { - throw new RuntimeException("Unknown region: " + regionName); - } - subRegions.put(regionName, SubRegion.readFromNBT(tag.getCompound(regionName), version, minecraftDataVersion)); - } - return subRegions; - } - public record SubRegion( LitematicaBlockStateContainer blockContainers, Map tileEntities, @@ -98,8 +99,8 @@ public record LitematicaSchematic(Map subRegions, SchematicMe @NotNull @Contract("_, _, _ -> new") public static SubRegion readFromNBT(@NotNull CompoundTag regionTag, int version, int minecraftDataVersion) { - BlockPos position = NbtUtils.readBlockPos(regionTag.getCompound("Position")); - BlockPos size = NbtUtils.readBlockPos(regionTag.getCompound("Size")); + BlockPos position = NbtUtils.readBlockPos(regionTag.getCompoundOrEmpty("Position")); + BlockPos size = NbtUtils.readBlockPos(regionTag.getCompoundOrEmpty("Size")); if (position == null || size == null) { throw new IllegalArgumentException("Invalid region"); } @@ -107,27 +108,28 @@ public record LitematicaSchematic(Map subRegions, SchematicMe Map tileEntities; List entities; if (version >= 2) { - tileEntities = readTileEntitiesFromNBT(regionTag.getList("TileEntities", Tag.TAG_COMPOUND)); - entities = readEntitiesFromNBT(regionTag.getList("Entities", Tag.TAG_COMPOUND)); + tileEntities = readTileEntitiesFromNBT(regionTag.getListOrEmpty("TileEntities")); + entities = readEntitiesFromNBT(regionTag.getListOrEmpty("Entities")); } else { - tileEntities = readTileEntitiesFromNBT_v1(regionTag.getList("TileEntities", Tag.TAG_COMPOUND)); - entities = readEntitiesFromNBT_v1(regionTag.getList("Entities", Tag.TAG_COMPOUND)); + tileEntities = readTileEntitiesFromNBT_v1(regionTag.getListOrEmpty("TileEntities")); + entities = readEntitiesFromNBT_v1(regionTag.getListOrEmpty("Entities")); } Map> pendingBlockTicks = null; if (version >= 3) { - pendingBlockTicks = readPendingTicksFromNBT(regionTag.getList("PendingBlockTicks", Tag.TAG_COMPOUND), BuiltInRegistries.BLOCK, "Block", Blocks.AIR); + pendingBlockTicks = readPendingTicksFromNBT(regionTag.getListOrEmpty("PendingBlockTicks"), BuiltInRegistries.BLOCK, "Block", Blocks.AIR); } Map> pendingFluidTicks = null; if (version >= 5) { - pendingFluidTicks = readPendingTicksFromNBT(regionTag.getList("PendingFluidTicks", Tag.TAG_COMPOUND), BuiltInRegistries.FLUID, "Fluid", Fluids.EMPTY); + pendingFluidTicks = readPendingTicksFromNBT(regionTag.getListOrEmpty("PendingFluidTicks"), BuiltInRegistries.FLUID, "Fluid", Fluids.EMPTY); } LitematicaBlockStateContainer blockContainers = null; - if (regionTag.contains("BlockStates", Tag.TAG_LONG_ARRAY)) { - ListTag palette = regionTag.getList("BlockStatePalette", Tag.TAG_COMPOUND); - long[] blockStateArr = regionTag.getLongArray("BlockStates"); + Tag blockState = regionTag.get("BlockStates"); + if (blockState != null && blockState.getId() == Tag.TAG_LONG_ARRAY) { + ListTag palette = regionTag.getListOrEmpty("BlockStatePalette"); + long[] blockStateArr = ((LongArrayTag) blockState).getAsLongArray(); BlockPos posEndRel = PositionUtils.getRelativeEndPositionFromAreaSize(size).offset(position); BlockPos posMin = PositionUtils.getMinCorner(position, posEndRel); BlockPos posMax = PositionUtils.getMaxCorner(position, posEndRel); @@ -146,7 +148,7 @@ public record LitematicaSchematic(Map subRegions, SchematicMe final int size = tagList.size(); for (int i = 0; i < size; ++i) { - CompoundTag entityData = tagList.getCompound(i); + CompoundTag entityData = tagList.getCompoundOrEmpty(i); Vec3 posVec = NbtUtils.readEntityPositionFromTag(entityData); if (posVec != null && !entityData.isEmpty()) { @@ -162,7 +164,7 @@ public record LitematicaSchematic(Map subRegions, SchematicMe final int size = tagList.size(); for (int i = 0; i < size; ++i) { - CompoundTag tag = tagList.getCompound(i); + CompoundTag tag = tagList.getCompoundOrEmpty(i); BlockPos pos = NbtUtils.readBlockPos(tag); if (pos != null && !tag.isEmpty()) { @@ -177,14 +179,14 @@ public record LitematicaSchematic(Map subRegions, SchematicMe Map> tickMap = new HashMap<>(); final int size = tagList.size(); for (int i = 0; i < size; ++i) { - CompoundTag tag = tagList.getCompound(i); + CompoundTag tag = tagList.getCompoundOrEmpty(i); // XXX these were accidentally saved as longs in version 3 - if (!tag.contains("Time", Tag.TAG_ANY_NUMERIC)) { + if (!tag.contains("Time")) { continue; } T target; - ResourceLocation resourceLocation = ResourceLocation.tryParse(tag.getString(tagName)); + ResourceLocation resourceLocation = ResourceLocation.tryParse(tag.getStringOr(tagName, "")); if (resourceLocation == null) { continue; } @@ -196,10 +198,10 @@ public record LitematicaSchematic(Map subRegions, SchematicMe if (target == emptyValue) { continue; } - BlockPos pos = new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); - TickPriority priority = TickPriority.byValue(tag.getInt("Priority")); - int scheduledTime = tag.getInt("Time"); - long subTick = tag.getLong("SubTick"); + BlockPos pos = new BlockPos(tag.getIntOr("x", 0), tag.getIntOr("y", 0), tag.getIntOr("z", 0)); + TickPriority priority = TickPriority.byValue(tag.getIntOr("Priority", 0)); + int scheduledTime = tag.getIntOr("Time", 0); + long subTick = tag.getLongOr("SubTick", 0L); tickMap.put(pos, new ScheduledTick<>(target, pos, scheduledTime, priority, subTick)); } @@ -211,9 +213,9 @@ public record LitematicaSchematic(Map subRegions, SchematicMe final int size = tagList.size(); for (int i = 0; i < size; ++i) { - CompoundTag tag = tagList.getCompound(i); + CompoundTag tag = tagList.getCompoundOrEmpty(i); Vec3 posVec = NbtUtils.readVec3(tag); - CompoundTag entityData = tag.getCompound("EntityData"); + CompoundTag entityData = tag.getCompoundOrEmpty("EntityData"); if (posVec != null && !entityData.isEmpty()) { // Update the correct position to the TileEntity NBT, where it is stored in version 2 @@ -230,8 +232,8 @@ public record LitematicaSchematic(Map subRegions, SchematicMe final int size = tagList.size(); for (int i = 0; i < size; ++i) { - CompoundTag tag = tagList.getCompound(i); - CompoundTag tileNbt = tag.getCompound("TileNBT"); + CompoundTag tag = tagList.getCompoundOrEmpty(i); + CompoundTag tileNbt = tag.getCompoundOrEmpty("TileNBT"); // Note: This within-schematic relative position is not inside the tile tag! BlockPos pos = NbtUtils.readBlockPos(tag); @@ -251,13 +253,13 @@ public record LitematicaSchematic(Map subRegions, SchematicMe public EntityInfo(Vec3 posVec, CompoundTag nbt) { this.posVec = posVec; - if (nbt.contains("SleepingX", Tag.TAG_INT)) { + if (nbt.contains("SleepingX")) { nbt.putInt("SleepingX", Mth.floor(posVec.x)); } - if (nbt.contains("SleepingY", Tag.TAG_INT)) { + if (nbt.contains("SleepingY")) { nbt.putInt("SleepingY", Mth.floor(posVec.y)); } - if (nbt.contains("SleepingZ", Tag.TAG_INT)) { + if (nbt.contains("SleepingZ")) { nbt.putInt("SleepingZ", Mth.floor(posVec.z)); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/SchematicMetadata.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/SchematicMetadata.java index 5206b10b..147ace9d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/SchematicMetadata.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/SchematicMetadata.java @@ -2,7 +2,6 @@ package org.leavesmc.leaves.protocol.servux.litematics; import net.minecraft.core.Vec3i; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.protocol.servux.litematics.utils.FileType; @@ -31,33 +30,16 @@ public record SchematicMetadata( @NotNull @Contract("_, _, _, _ -> new") public static SchematicMetadata readFromNBT(@NotNull CompoundTag nbt, int version, int minecraftDataVersion, FileType fileType) { - String name = nbt.getString("Name"); - String author = nbt.getString("Author"); - String description = nbt.getString("Description"); - int regionCount = nbt.getInt("RegionCount"); - long timeCreated = nbt.getLong("TimeCreated"); - long timeModified = nbt.getLong("TimeModified"); - - long totalVolume = -1; - if (nbt.contains("TotalVolume", Tag.TAG_ANY_NUMERIC)) { - totalVolume = nbt.getInt("TotalVolume"); - } - - long totalBlocks = -1; - if (nbt.contains("TotalBlocks", Tag.TAG_ANY_NUMERIC)) { - totalBlocks = nbt.getInt("TotalBlocks"); - } - - Vec3i enclosingSize = Vec3i.ZERO; - if (nbt.contains("EnclosingSize", Tag.TAG_COMPOUND)) { - enclosingSize = Objects.requireNonNullElse(NbtUtils.readVec3iFromTag(nbt.getCompound("EnclosingSize")), Vec3i.ZERO); - } - - int[] thumbnailPixelData = null; - if (nbt.contains("PreviewImageData", Tag.TAG_INT_ARRAY)) { - thumbnailPixelData = nbt.getIntArray("PreviewImageData"); - } - + String name = nbt.getStringOr("Name", "?"); + String author = nbt.getStringOr("Author", "?"); + String description = nbt.getStringOr("Description", ""); + int regionCount = nbt.getIntOr("RegionCount", -1); + long timeCreated = nbt.getLongOr("TimeCreated", -1L); + long timeModified = nbt.getLongOr("TimeModified", -1L); + long totalVolume = nbt.getIntOr("TotalVolume", -1); + long totalBlocks = nbt.getIntOr("TotalBlocks", -1); + Vec3i enclosingSize = Objects.requireNonNullElse(NbtUtils.readVec3iFromTag(nbt.getCompoundOrEmpty("EnclosingSize")), Vec3i.ZERO); + int[] thumbnailPixelData = nbt.getIntArray("PreviewImageData").orElse(null); return new SchematicMetadata(name, author, description, enclosingSize, timeCreated, timeModified, minecraftDataVersion, version, Schema.getSchemaByDataVersion(minecraftDataVersion), fileType, regionCount, totalVolume, totalBlocks, thumbnailPixelData); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java index 1a928f7f..f7f60f48 100755 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java @@ -7,18 +7,19 @@ import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; -import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; @@ -39,10 +40,9 @@ import java.util.Random; import java.util.Set; import java.util.UUID; -@LeavesProtocol(namespace = "servux") -public class ServuxLitematicsProtocol { +@LeavesProtocol.Register(namespace = "servux") +public class ServuxLitematicsProtocol implements LeavesProtocol { - public static final ResourceLocation CHANNEL = ServuxProtocol.id("litematics"); public static final int PROTOCOL_VERSION = 1; private static final CompoundTag metadata = new CompoundTag(); @@ -51,18 +51,19 @@ public class ServuxLitematicsProtocol { @ProtocolHandler.Init public static void init() { metadata.putString("name", "litematic_data"); - metadata.putString("id", CHANNEL.toString()); + metadata.putString("id", ServuxLitematicaPayload.CHANNEL.toString()); metadata.putInt("version", PROTOCOL_VERSION); metadata.putString("servux", ServuxProtocol.SERVUX_STRING); } public static boolean hasPermission(ServerPlayer player) { - CraftPlayer bukkitEntity = player.getBukkitEntity(); - return bukkitEntity.hasPermission("leaves.protocol.litematics"); + return player.getBukkitEntity().hasPermission("leaves.protocol.litematics"); } - public static boolean isEnabled() { - return LeavesConfig.protocol.servux.litematicsProtocol; + public static void sendMetaData(ServerPlayer player) { + ServuxLitematicaPayload send = new ServuxLitematicaPayload(ServuxLitematicaPayloadType.PACKET_S2C_METADATA); + send.nbt.merge(metadata); + encodeServerData(player, send); } public static void encodeServerData(ServerPlayer player, @NotNull ServuxLitematicaPayload packet) { @@ -83,18 +84,24 @@ public class ServuxLitematicsProtocol { encodeServerData(player, payload); } - @ProtocolHandler.PayloadReceiver(payload = ServuxLitematicaPayload.class, payloadId = "litematics") + @ProtocolHandler.PlayerJoin + public static void onPlayerJoin(ServerPlayer player) { + sendMetaData(player); + } + + @ProtocolHandler.PayloadReceiver(payload = ServuxLitematicaPayload.class) public static void onPacketReceive(ServerPlayer player, ServuxLitematicaPayload payload) { - if (!isEnabled() || !hasPermission(player)) { + if (!hasPermission(player)) { return; } switch (payload.packetType) { - case PACKET_C2S_METADATA_REQUEST -> { - ServuxLitematicaPayload send = new ServuxLitematicaPayload(ServuxLitematicaPayloadType.PACKET_S2C_METADATA); - send.nbt.merge(metadata); - encodeServerData(player, send); - } + case PACKET_C2S_METADATA_REQUEST -> sendMetaData(player); + + case PACKET_C2S_BLOCK_ENTITY_REQUEST -> onBlockEntityRequest(player, payload.getPos()); + + case PACKET_C2S_ENTITY_REQUEST -> onEntityRequest(player, payload.getEntityId()); + case PACKET_C2S_BULK_ENTITY_NBT_REQUEST -> onBulkEntityRequest(player, payload.getChunkPos(), payload.getCompound()); @@ -120,6 +127,41 @@ public class ServuxLitematicsProtocol { } } + public static void onBlockEntityRequest(ServerPlayer player, BlockPos pos) { + if (!hasPermission(player)) { + return; + } + BlockEntity be = player.serverLevel().getBlockEntity(pos); + CompoundTag tag = be != null ? be.saveWithFullMetadata(MinecraftServer.getServer().registryAccess()) : new CompoundTag(); + ServuxLitematicaPayload payload = new ServuxLitematicaPayload(ServuxLitematicaPayloadType.PACKET_S2C_BLOCK_NBT_RESPONSE_SIMPLE); + payload.pos = pos; + payload.nbt = tag; + encodeServerData(player, payload); + } + + public static void onEntityRequest(ServerPlayer player, int entityId) { + if (!hasPermission(player)) { + return; + } + Entity entity = player.serverLevel().getEntity(entityId); + if (entity == null) { + return; + } + CompoundTag tag = new CompoundTag(); + ServuxLitematicaPayload payload = new ServuxLitematicaPayload(ServuxLitematicaPayloadType.PACKET_S2C_ENTITY_NBT_RESPONSE_SIMPLE); + payload.entityId = entityId; + if (entity instanceof net.minecraft.world.entity.player.Player) { + ResourceLocation loc = EntityType.getKey(entity.getType()); + tag = entity.saveWithoutId(tag); + tag.putString("id", loc.toString()); + payload.nbt = tag; + encodeServerData(player, payload); + } else if (entity.saveAsPassenger(tag)) { + payload.nbt = tag; + encodeServerData(player, payload); + } + } + public static void onBulkEntityRequest(ServerPlayer player, ChunkPos chunkPos, CompoundTag req) { if (req == null || req.isEmpty()) { return; @@ -131,15 +173,14 @@ public class ServuxLitematicsProtocol { if (chunk == null) { return; } - if ((req.contains("Task") && req.getString("Task").equals("BulkEntityRequest")) || - !req.contains("Task")) { + if (!req.contains("Task") || req.getStringOr("Task", "").equals("BulkEntityRequest")) { ServuxProtocol.LOGGER.debug("litematic_data: Sending Bulk NBT Data for ChunkPos [{}] to player {}", chunkPos, player.getName().getString()); long timeStart = System.currentTimeMillis(); ListTag tileList = new ListTag(); ListTag entityList = new ListTag(); - int minY = req.getInt("minY"); - int maxY = req.getInt("maxY"); + int minY = req.getIntOr("minY", -64); + int maxY = req.getIntOr("maxY", 319); BlockPos pos1 = new BlockPos(chunkPos.getMinBlockX(), minY, chunkPos.getMinBlockZ()); BlockPos pos2 = new BlockPos(chunkPos.getMaxBlockX(), maxY, chunkPos.getMaxBlockZ()); AABB bb = AABB.encapsulatingFullBlocks(pos1, pos2); @@ -183,29 +224,42 @@ public class ServuxLitematicsProtocol { } public static void handleClientPasteRequest(ServerPlayer player, @NotNull CompoundTag tags) { - if (tags.getString("Task").equals("LitematicaPaste")) { + if (!hasPermission(player)) { + player.getBukkitEntity().sendActionBar(Component.text("Insufficient Permissions for the Litematic paste operation", NamedTextColor.RED)); + return; + } + if (!player.isCreative()) { + player.getBukkitEntity().sendActionBar(Component.text("Creative Mode is required for the Litematic paste operation", NamedTextColor.RED)); + return; + } + + if (tags.getStringOr("Task", "").equals("LitematicaPaste")) { ServuxProtocol.LOGGER.debug("litematic_data: Servux Paste request from player {}", player.getName().getString()); ServerLevel serverLevel = player.serverLevel(); long timeStart = System.currentTimeMillis(); SchematicPlacement placement = SchematicPlacement.createFromNbt(tags); - ReplaceBehavior replaceMode = ReplaceBehavior.fromStringStatic(tags.getString("ReplaceMode")); - MinecraftServer server = MinecraftServer.getServer(); - server.scheduleOnMain(() -> { + ReplaceBehavior replaceMode = ReplaceBehavior.fromStringStatic(tags.getStringOr("ReplaceMode", ReplaceBehavior.NONE.name())); + MinecraftServer.getServer().scheduleOnMain(() -> { placement.pasteTo(serverLevel, replaceMode); long timeElapsed = System.currentTimeMillis() - timeStart; player.getBukkitEntity().sendActionBar( Component.text("Pasted ") - .append(Component.text(placement.getName()).color(NamedTextColor.AQUA)) + .append(Component.text(placement.getName(), NamedTextColor.AQUA)) .append(Component.text(" to world ")) - .append(Component.text(serverLevel.serverLevelData.getLevelName()).color(NamedTextColor.LIGHT_PURPLE)) + .append(Component.text(serverLevel.serverLevelData.getLevelName(), NamedTextColor.LIGHT_PURPLE)) .append(Component.text(" in ")) - .append(Component.text(timeElapsed).color(NamedTextColor.GREEN)) + .append(Component.text(timeElapsed, NamedTextColor.GREEN)) .append(Component.text("ms")) ); }); } } + @Override + public boolean isActive() { + return LeavesConfig.protocol.servux.litematicsProtocol; + } + public enum ServuxLitematicaPayloadType { PACKET_S2C_METADATA(1), PACKET_C2S_METADATA_REQUEST(2), @@ -221,10 +275,6 @@ public class ServuxLitematicsProtocol { PACKET_C2S_NBT_RESPONSE_START(12), PACKET_C2S_NBT_RESPONSE_DATA(13); - private static final class Helper { - static Map ID_TO_TYPE = new HashMap<>(); - } - public final int type; ServuxLitematicaPayloadType(int type) { @@ -235,10 +285,82 @@ public class ServuxLitematicsProtocol { public static ServuxLitematicaPayloadType fromId(int id) { return ServuxLitematicaPayloadType.Helper.ID_TO_TYPE.get(id); } + + private static final class Helper { + static Map ID_TO_TYPE = new HashMap<>(); + } } - public static class ServuxLitematicaPayload implements LeavesCustomPayload { + public static class ServuxLitematicaPayload implements LeavesCustomPayload { + @ID + public static final ResourceLocation CHANNEL = ServuxProtocol.id("litematics"); + + @Codec + public static final StreamCodec CODEC = StreamCodec.of( + (buf, payload) -> { + buf.writeVarInt(payload.packetType.type); + switch (payload.packetType) { + case PACKET_C2S_BLOCK_ENTITY_REQUEST -> { + buf.writeVarInt(payload.transactionId); + buf.writeBlockPos(payload.pos); + } + case PACKET_C2S_ENTITY_REQUEST -> { + buf.writeVarInt(payload.transactionId); + buf.writeVarInt(payload.entityId); + } + case PACKET_S2C_BLOCK_NBT_RESPONSE_SIMPLE -> { + buf.writeBlockPos(payload.pos); + buf.writeNbt(payload.nbt); + } + case PACKET_S2C_ENTITY_NBT_RESPONSE_SIMPLE -> { + buf.writeVarInt(payload.entityId); + buf.writeNbt(payload.nbt); + } + case PACKET_C2S_BULK_ENTITY_NBT_REQUEST -> { + buf.writeChunkPos(payload.chunkPos); + buf.writeNbt(payload.nbt); + } + case PACKET_S2C_NBT_RESPONSE_DATA, PACKET_C2S_NBT_RESPONSE_DATA -> buf.writeBytes(payload.buffer.readBytes(payload.buffer.readableBytes())); + case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA -> buf.writeNbt(payload.nbt); + default -> ServuxProtocol.LOGGER.error("ServuxLitematicaPacket#toPacket: Unknown packet type!"); + } + }, + buf -> { + ServuxLitematicaPayloadType type = ServuxLitematicaPayloadType.fromId(buf.readVarInt()); + if (type == null) { + throw new IllegalStateException("invalid packet type received"); + } + ServuxLitematicaPayload payload = new ServuxLitematicaPayload(type); + switch (type) { + case PACKET_C2S_BLOCK_ENTITY_REQUEST -> { + buf.readVarInt(); + payload.pos = buf.readBlockPos().immutable(); + } + case PACKET_C2S_ENTITY_REQUEST -> { + buf.readVarInt(); + payload.entityId = buf.readVarInt(); + } + case PACKET_S2C_BLOCK_NBT_RESPONSE_SIMPLE -> { + payload.pos = buf.readBlockPos().immutable(); + payload.nbt = buf.readNbt(); + } + case PACKET_S2C_ENTITY_NBT_RESPONSE_SIMPLE -> { + payload.entityId = buf.readVarInt(); + payload.nbt = buf.readNbt(); + } + case PACKET_C2S_BULK_ENTITY_NBT_REQUEST -> { + payload.chunkPos = buf.readChunkPos(); + payload.nbt = buf.readNbt(); + } + case PACKET_C2S_NBT_RESPONSE_DATA, PACKET_S2C_NBT_RESPONSE_DATA -> payload.buffer = new FriendlyByteBuf(buf.readBytes(buf.readableBytes())); + case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA -> payload.nbt = buf.readNbt(); + } + return payload; + } + ); + + public static final int PROTOCOL_VERSION = 1; private final ServuxLitematicaPayloadType packetType; private final int transactionId; private int entityId; @@ -246,7 +368,6 @@ public class ServuxLitematicsProtocol { private CompoundTag nbt; private ChunkPos chunkPos; private FriendlyByteBuf buffer; - public static final int PROTOCOL_VERSION = 1; private ServuxLitematicaPayload(ServuxLitematicaPayloadType type) { this.packetType = type; @@ -296,90 +417,5 @@ public class ServuxLitematicsProtocol { public boolean isEmpty() { return !this.hasBuffer() && !this.hasNbt(); } - - @New - public static ServuxLitematicaPayload decode(ResourceLocation location, FriendlyByteBuf input) { - ServuxLitematicaPayloadType type = ServuxLitematicaPayloadType.fromId(input.readVarInt()); - if (type == null) { - throw new IllegalStateException("invalid packet type received"); - } - - ServuxLitematicaPayload payload = new ServuxLitematicaPayload(type); - switch (type) { - case PACKET_C2S_BLOCK_ENTITY_REQUEST -> { - input.readVarInt(); - payload.pos = input.readBlockPos().immutable(); - } - - case PACKET_C2S_ENTITY_REQUEST -> { - input.readVarInt(); - payload.entityId = input.readVarInt(); - } - - case PACKET_S2C_BLOCK_NBT_RESPONSE_SIMPLE -> { - payload.pos = input.readBlockPos().immutable(); - payload.nbt = input.readNbt(); - } - - case PACKET_S2C_ENTITY_NBT_RESPONSE_SIMPLE -> { - payload.entityId = input.readVarInt(); - payload.nbt = input.readNbt(); - } - - case PACKET_C2S_BULK_ENTITY_NBT_REQUEST -> { - payload.chunkPos = input.readChunkPos(); - payload.nbt = input.readNbt(); - } - - case PACKET_C2S_NBT_RESPONSE_DATA, PACKET_S2C_NBT_RESPONSE_DATA -> payload.buffer = new FriendlyByteBuf(input.readBytes(input.readableBytes())); - - case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA -> payload.nbt = input.readNbt(); - } - - return payload; - } - - @Override - public void write(FriendlyByteBuf output) { - output.writeVarInt(this.packetType.type); - - switch (this.packetType) { - case PACKET_C2S_BLOCK_ENTITY_REQUEST -> { - output.writeVarInt(this.transactionId); - output.writeBlockPos(this.pos); - } - - case PACKET_C2S_ENTITY_REQUEST -> { - output.writeVarInt(this.transactionId); - output.writeVarInt(this.entityId); - } - - case PACKET_S2C_BLOCK_NBT_RESPONSE_SIMPLE -> { - output.writeBlockPos(this.pos); - output.writeNbt(this.nbt); - } - - case PACKET_S2C_ENTITY_NBT_RESPONSE_SIMPLE -> { - output.writeVarInt(this.entityId); - output.writeNbt(this.nbt); - } - - case PACKET_C2S_BULK_ENTITY_NBT_REQUEST -> { - output.writeChunkPos(this.chunkPos); - output.writeNbt(this.nbt); - } - - case PACKET_S2C_NBT_RESPONSE_DATA, PACKET_C2S_NBT_RESPONSE_DATA -> output.writeBytes(this.buffer.readBytes(this.buffer.readableBytes())); - - case PACKET_C2S_METADATA_REQUEST, PACKET_S2C_METADATA -> output.writeNbt(this.nbt); - - default -> ServuxProtocol.LOGGER.error("ServuxLitematicaPacket#toPacket: Unknown packet type!"); - } - } - - @Override - public ResourceLocation id() { - return CHANNEL; - } } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBitArray.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBitArray.java index c4dc4bff..edf530b2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBitArray.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBitArray.java @@ -37,6 +37,22 @@ public class LitematicaBitArray { this.longArray = Objects.requireNonNullElseGet(longArrayIn, () -> new long[(int) (roundUp(arraySizeIn * bitsPerEntryIn, 64L) / 64L)]); } + public static long roundUp(long value, long interval) { + if (interval == 0L) { + return 0L; + } else if (value == 0L) { + return interval; + } else { + if (value < 0L) { + interval *= -1L; + } + + long remainder = value % interval; + + return remainder == 0L ? value : value + interval - remainder; + } + } + public void setAt(long index, int value) { long startOffset = index * (long) this.bitsPerEntry; int startArrIndex = (int) (startOffset >> 6); // startOffset / 64 @@ -68,20 +84,4 @@ public class LitematicaBitArray { public long size() { return this.arraySize; } - - public static long roundUp(long value, long interval) { - if (interval == 0L) { - return 0L; - } else if (value == 0L) { - return interval; - } else { - if (value < 0L) { - interval *= -1L; - } - - long remainder = value % interval; - - return remainder == 0L ? value : value + interval - remainder; - } - } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStateContainer.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStateContainer.java index 94f2a54e..1bcc7362 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStateContainer.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStateContainer.java @@ -11,14 +11,14 @@ import javax.annotation.Nullable; public class LitematicaBlockStateContainer { public static final BlockState AIR_BLOCK_STATE = Blocks.AIR.defaultBlockState(); - protected LitematicaBitArray storage; - protected LitematicaBlockStatePalette palette; protected final Vec3i size; protected final int sizeX; protected final int sizeY; protected final int sizeZ; protected final int sizeLayer; protected final long totalVolume; + protected LitematicaBitArray storage; + protected LitematicaBlockStatePalette palette; protected int bits; public LitematicaBlockStateContainer(int sizeX, int sizeY, int sizeZ, int bits, @Nullable long[] backingLongArray) { @@ -32,6 +32,13 @@ public class LitematicaBlockStateContainer { this.setBits(bits, backingLongArray); } + public static LitematicaBlockStateContainer createFrom(ListTag palette, long[] blockStates, BlockPos size) { + int bits = Math.max(2, Integer.SIZE - Integer.numberOfLeadingZeros(palette.size() - 1)); + LitematicaBlockStateContainer container = new LitematicaBlockStateContainer(size.getX(), size.getY(), size.getZ(), bits, blockStates); + container.palette.readFromNBT(palette); + return container; + } + public Vec3i getSize() { return this.size; } @@ -91,11 +98,4 @@ public class LitematicaBlockStateContainer { public LitematicaBlockStatePalette getPalette() { return this.palette; } - - public static LitematicaBlockStateContainer createFrom(ListTag palette, long[] blockStates, BlockPos size) { - int bits = Math.max(2, Integer.SIZE - Integer.numberOfLeadingZeros(palette.size() - 1)); - LitematicaBlockStateContainer container = new LitematicaBlockStateContainer(size.getX(), size.getY(), size.getZ(), bits, blockStates); - container.palette.readFromNBT(palette); - return container; - } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePalette.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePalette.java index c69f628d..329495e7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePalette.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePalette.java @@ -1,6 +1,12 @@ package org.leavesmc.leaves.protocol.servux.litematics.container; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nullable; @@ -18,7 +24,22 @@ public interface LitematicaBlockStatePalette { @Nullable BlockState getBlockState(int indexKey); - void readFromNBT(ListTag tagList); + void requestNewId(BlockState state); + + default void readFromNBT(ListTag tagList) { + Registry lookup = MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BLOCK); + + final int size = tagList.size(); + + for (int i = 0; i < size; ++i) { + CompoundTag tag = tagList.getCompound(i).orElseThrow(); + BlockState state = NbtUtils.readBlockState(lookup, tag); + + if (i > 0 || state != LitematicaBlockStateContainer.AIR_BLOCK_STATE) { + this.requestNewId(state); + } + } + } ListTag writeToNBT(); } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePaletteHashMap.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePaletteHashMap.java index 1ad11431..e15cc1a2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePaletteHashMap.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePaletteHashMap.java @@ -1,12 +1,8 @@ package org.leavesmc.leaves.protocol.servux.litematics.container; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtUtils; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import org.leavesmc.leaves.protocol.servux.litematics.utils.Int2ObjectBiMap; @@ -45,7 +41,7 @@ public class LitematicaBlockStatePaletteHashMap implements LitematicaBlockStateP return this.statePaletteMap.get(indexKey); } - private void requestNewId(BlockState state) { + public void requestNewId(BlockState state) { final int origId = this.statePaletteMap.add(state); if (origId >= (1 << this.bits)) { @@ -57,22 +53,6 @@ public class LitematicaBlockStatePaletteHashMap implements LitematicaBlockStateP } } - @Override - public void readFromNBT(ListTag tagList) { - Registry lookup = MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BLOCK); - - final int size = tagList.size(); - - for (int i = 0; i < size; ++i) { - CompoundTag tag = tagList.getCompound(i); - BlockState state = NbtUtils.readBlockState(lookup, tag); - - if (i > 0 || state != LitematicaBlockStateContainer.AIR_BLOCK_STATE) { - this.requestNewId(state); - } - } - } - @Override public ListTag writeToNBT() { ListTag tagList = new ListTag(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePaletteLinear.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePaletteLinear.java index 6f6ea248..e5a19808 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePaletteLinear.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/container/LitematicaBlockStatePaletteLinear.java @@ -1,12 +1,8 @@ package org.leavesmc.leaves.protocol.servux.litematics.container; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtUtils; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nullable; @@ -49,7 +45,7 @@ public class LitematicaBlockStatePaletteLinear implements LitematicaBlockStatePa return indexKey >= 0 && indexKey < this.currentSize ? this.states[indexKey] : null; } - private void requestNewId(BlockState state) { + public void requestNewId(BlockState state) { final int size = this.currentSize; if (size < this.states.length) { @@ -58,22 +54,6 @@ public class LitematicaBlockStatePaletteLinear implements LitematicaBlockStatePa } } - @Override - public void readFromNBT(ListTag tagList) { - Registry lookup = MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BLOCK); - - final int size = tagList.size(); - - for (int i = 0; i < size; ++i) { - CompoundTag tag = tagList.getCompound(i); - BlockState state = NbtUtils.readBlockState(lookup, tag); - - if (i > 0 || state != LitematicaBlockStateContainer.AIR_BLOCK_STATE) { - this.requestNewId(state); - } - } - } - @Override public ListTag writeToNBT() { ListTag tagList = new ListTag(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/placement/SchematicPlacement.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/placement/SchematicPlacement.java index 180b3b06..31835231 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/placement/SchematicPlacement.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/placement/SchematicPlacement.java @@ -5,7 +5,6 @@ import net.minecraft.core.BlockBox; import net.minecraft.core.BlockPos; import net.minecraft.core.SectionPos; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.block.Mirror; @@ -16,6 +15,7 @@ import org.leavesmc.leaves.protocol.servux.ServuxProtocol; import org.leavesmc.leaves.protocol.servux.litematics.LitematicaSchematic; import org.leavesmc.leaves.protocol.servux.litematics.selection.Box; import org.leavesmc.leaves.protocol.servux.litematics.utils.IntBoundingBox; +import org.leavesmc.leaves.protocol.servux.litematics.utils.NbtUtils; import org.leavesmc.leaves.protocol.servux.litematics.utils.PositionUtils; import org.leavesmc.leaves.protocol.servux.litematics.utils.ReplaceBehavior; import org.leavesmc.leaves.protocol.servux.litematics.utils.SchematicPlacingUtils; @@ -45,27 +45,65 @@ public class SchematicPlacement { public static SchematicPlacement createFromNbt(CompoundTag tags) { SchematicPlacement placement = new SchematicPlacement( - LitematicaSchematic.readFromNBT(tags.getCompound("Schematics")), - NbtUtils.readBlockPos(tags, "Origin").orElseThrow(), - tags.getString("Name") + LitematicaSchematic.readFromNBT(tags.getCompoundOrEmpty("Schematics")), + NbtUtils.readBlockPosFromArrayTag(tags, "Origin"), + tags.getStringOr("Name", "") ); - placement.mirror = Mirror.values()[tags.getInt("Mirror")]; - placement.rotation = Rotation.values()[tags.getInt("Rotation")]; - for (String name : tags.getCompound("SubRegions").getAllKeys()) { - CompoundTag compound = tags.getCompound("SubRegions").getCompound(name); + placement.mirror = Mirror.values()[tags.getIntOr("Mirror", 0)]; + placement.rotation = Rotation.values()[tags.getIntOr("Rotation", 0)]; + for (String name : tags.getCompoundOrEmpty("SubRegions").keySet()) { + CompoundTag compound = tags.getCompoundOrEmpty("SubRegions").getCompoundOrEmpty(name); var sub = new SubRegionPlacement( - compound.getString("Name"), - NbtUtils.readBlockPos(compound, "Pos").orElseThrow(), - Rotation.values()[compound.getInt("Rotation")], - Mirror.values()[compound.getInt("Mirror")], - compound.getBoolean("Enabled"), - compound.getBoolean("IgnoreEntities") + compound.getStringOr("Name", "?"), + NbtUtils.readBlockPosFromArrayTag(compound, "Pos"), + Rotation.values()[compound.getIntOr("Rotation", 0)], + Mirror.values()[compound.getIntOr("Mirror", 0)], + compound.getBooleanOr("Enabled", true), + compound.getBooleanOr("IgnoreEntities", false) ); placement.relativeSubRegionPlacements.put(name, sub); } return placement; } + public static IntBoundingBox getBoundsWithinChunkForBox(Box box, int chunkX, int chunkZ) { + final int chunkXMin = chunkX << 4; + final int chunkZMin = chunkZ << 4; + final int chunkXMax = chunkXMin + 15; + final int chunkZMax = chunkZMin + 15; + BlockPos boxPos1 = box.pos1(); + BlockPos boxPos2 = box.pos2(); + if (boxPos1 == null || boxPos2 == null) { + return null; + } + + int x1 = boxPos1.getX(); + int x2 = boxPos2.getX(); + int y1 = boxPos1.getY(); + int y2 = boxPos2.getY(); + int z1 = boxPos1.getZ(); + int z2 = boxPos2.getZ(); + final int boxXMin = Math.min(x1, x2); + final int boxZMin = Math.min(z1, z2); + final int boxXMax = Math.max(x1, x2); + final int boxZMax = Math.max(z1, z2); + + boolean notOverlapping = boxXMin > chunkXMax || boxZMin > chunkZMax || boxXMax < chunkXMin || boxZMax < chunkZMin; + + if (!notOverlapping) { + final int xMin = Math.max(chunkXMin, boxXMin); + final int yMin = Math.min(y1, y2); + final int zMin = Math.max(chunkZMin, boxZMin); + final int xMax = Math.min(chunkXMax, boxXMax); + final int yMax = Math.max(y1, y2); + final int zMax = Math.min(chunkZMax, boxZMax); + + return new IntBoundingBox(xMin, yMin, zMin, xMax, yMax, zMax); + } + + return null; + } + public boolean ignoreEntities() { return false; } @@ -129,44 +167,6 @@ public class SchematicPlacement { builder.put(name, new Box(boxOriginAbsolute, pos2, name)); } - public static IntBoundingBox getBoundsWithinChunkForBox(Box box, int chunkX, int chunkZ) { - final int chunkXMin = chunkX << 4; - final int chunkZMin = chunkZ << 4; - final int chunkXMax = chunkXMin + 15; - final int chunkZMax = chunkZMin + 15; - BlockPos boxPos1 = box.pos1(); - BlockPos boxPos2 = box.pos2(); - if (boxPos1 == null || boxPos2 == null) { - return null; - } - - int x1 = boxPos1.getX(); - int x2 = boxPos2.getX(); - int y1 = boxPos1.getY(); - int y2 = boxPos2.getY(); - int z1 = boxPos1.getZ(); - int z2 = boxPos2.getZ(); - final int boxXMin = Math.min(x1, x2); - final int boxZMin = Math.min(z1, z2); - final int boxXMax = Math.max(x1, x2); - final int boxZMax = Math.max(z1, z2); - - boolean notOverlapping = boxXMin > chunkXMax || boxZMin > chunkZMax || boxXMax < chunkXMin || boxZMax < chunkZMin; - - if (!notOverlapping) { - final int xMin = Math.max(chunkXMin, boxXMin); - final int yMin = Math.min(y1, y2); - final int zMin = Math.max(chunkZMin, boxZMin); - final int xMax = Math.min(chunkXMax, boxXMax); - final int yMax = Math.max(y1, y2); - final int zMax = Math.min(chunkZMax, boxZMax); - - return new IntBoundingBox(xMin, yMin, zMin, xMax, yMax, zMax); - } - - return null; - } - public ImmutableMap getSubRegionBoxFor(String regionName, SubRegionPlacement.RequiredEnabled required) { SubRegionPlacement placement = this.relativeSubRegionPlacements.get(regionName); if (placement == null) return ImmutableMap.of(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/EntityUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/EntityUtils.java index a594e2b7..5586a54d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/EntityUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/EntityUtils.java @@ -3,7 +3,6 @@ package org.leavesmc.leaves.protocol.servux.litematics.utils; import com.google.common.collect.ImmutableList; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; @@ -46,11 +45,11 @@ public class EntityUtils { if (entity == null) { return null; } - if (nbt.contains("Passengers", Tag.TAG_LIST)) { - ListTag tagList = nbt.getList("Passengers", Tag.TAG_LIST); + if (nbt.contains("Passengers")) { + ListTag tagList = nbt.getListOrEmpty("Passengers"); for (int i = 0; i < tagList.size(); ++i) { - Entity passenger = createEntityAndPassengersFromNBT(tagList.getCompound(i), world); + Entity passenger = createEntityAndPassengersFromNBT(tagList.getCompoundOrEmpty(i), world); if (passenger != null) { passenger.startRiding(entity, true); @@ -65,7 +64,7 @@ public class EntityUtils { ImmutableList passengers = entity.passengers; if (world.addFreshEntity(entity) && !passengers.isEmpty()) { for (Entity passenger : passengers) { - passenger.absMoveTo( + passenger.snapTo( entity.getX(), entity.getY() + entity.getPassengerRidingPosition(passenger).y(), entity.getZ(), diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Int2ObjectBiMap.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Int2ObjectBiMap.java index dc8d044b..3c46a824 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Int2ObjectBiMap.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Int2ObjectBiMap.java @@ -36,6 +36,14 @@ public class Int2ObjectBiMap implements Iterable { return new Int2ObjectBiMap<>((int) ((float) expectedSize / 0.8F)); } + private static int idealHash(int value) { + value ^= value >>> 16; + value *= -2048144789; + value ^= value >>> 13; + value *= -1028477387; + return value ^ value >>> 16; + } + public int getRawId(@Nullable K value) { return this.getIdFromIndex(this.findIndex(value, this.getIdealIndex(value))); } @@ -111,14 +119,6 @@ public class Int2ObjectBiMap implements Iterable { } } - private static int idealHash(int value) { - value ^= value >>> 16; - value *= -2048144789; - value ^= value >>> 13; - value *= -1028477387; - return value ^ value >>> 16; - } - private int getIdealIndex(@Nullable K value) { return (idealHash(System.identityHashCode(value)) & 2147483647) % this.values.length; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/NbtUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/NbtUtils.java index 88257aa8..386d3a9e 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/NbtUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/NbtUtils.java @@ -5,10 +5,9 @@ import net.minecraft.core.Vec3i; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.DoubleTag; import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; import net.minecraft.world.phys.Vec3; - -import javax.annotation.Nullable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class NbtUtils { @@ -20,11 +19,8 @@ public class NbtUtils { @Nullable public static BlockPos readBlockPos(@Nullable CompoundTag tag) { - if (tag != null && - tag.contains("x", Tag.TAG_INT) && - tag.contains("y", Tag.TAG_INT) && - tag.contains("z", Tag.TAG_INT)) { - return new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); + if (tag != null && tag.contains("x") && tag.contains("y") && tag.contains("z")) { + return new BlockPos(tag.getIntOr("x", 0), tag.getIntOr("y", 0), tag.getIntOr("z", 0)); } return null; @@ -41,38 +37,39 @@ public class NbtUtils { @Nullable public static Vec3 readVec3(@Nullable CompoundTag tag) { - if (tag != null && - tag.contains("dx", Tag.TAG_DOUBLE) && - tag.contains("dy", Tag.TAG_DOUBLE) && - tag.contains("dz", Tag.TAG_DOUBLE)) { - return new Vec3(tag.getDouble("dx"), tag.getDouble("dy"), tag.getDouble("dz")); + if (tag != null && tag.contains("dx") && tag.contains("dy") && tag.contains("dz")) { + return new Vec3(tag.getDoubleOr("dx", 0.0), tag.getDoubleOr("dy", 0.0), tag.getDoubleOr("dz", 0.0)); } - return null; } @Nullable public static Vec3 readEntityPositionFromTag(@Nullable CompoundTag tag) { - if (tag != null && tag.contains("Pos", Tag.TAG_LIST)) { - ListTag tagList = tag.getList("Pos", Tag.TAG_DOUBLE); - - if (tagList.getElementType() == Tag.TAG_DOUBLE && tagList.size() == 3) { - return new Vec3(tagList.getDouble(0), tagList.getDouble(1), tagList.getDouble(2)); - } + if (tag == null || !tag.contains("Pos")) { + return null; } - - return null; + ListTag tagList = tag.getListOrEmpty("Pos"); + if (tagList.size() != 3) { + return null; + } + return new Vec3(tagList.getDoubleOr(0, 0.0), tagList.getDoubleOr(1, 0.0), tagList.getDoubleOr(2, 0.0)); } @Nullable public static Vec3i readVec3iFromTag(@Nullable CompoundTag tag) { - if (tag != null && - tag.contains("x", Tag.TAG_INT) && - tag.contains("y", Tag.TAG_INT) && - tag.contains("z", Tag.TAG_INT)) { - return new Vec3i(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); + if (tag != null && tag.contains("x") && tag.contains("y") && tag.contains("z")) { + return new Vec3i(tag.getIntOr("x", 0), tag.getIntOr("y", 0), tag.getIntOr("z", 0)); } + return null; + } + public static BlockPos readBlockPosFromArrayTag(@NotNull CompoundTag tag, String tagName) { + if (tag.contains(tagName)) { + int[] pos = tag.getIntArray(tagName).orElse(new int[0]); + if (pos.length == 3) { + return new BlockPos(pos[0], pos[1], pos[2]); + } + } return null; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Schema.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Schema.java index 5a108348..b5370f69 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Schema.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Schema.java @@ -5,6 +5,9 @@ import javax.annotation.Nullable; public enum Schema { // TODO --> Add Schema Versions to this as versions get released // Minecraft Data Versions + SCHEMA_FUTURE(9999, "FUTURE"), + SCHEMA_1_21_05(4325, "1.21.5"), + SCHEMA_25W10A(4319, "25w10a"), SCHEMA_25W03A(4304, "25w03a"), // Entity Data Components ( https://www.minecraft.net/en-us/article/minecraft-snapshot-25w03a ) SCHEMA_25W02A(4298, "25w02a"), SCHEMA_1_21_04(4189, "1.21.4"), @@ -116,14 +119,6 @@ public enum Schema { this.str = ver; } - public int getDataVersion() { - return this.schemaId; - } - - public String getString() { - return this.str; - } - /** * Returns the Schema of the closest dataVersion, or below it. * @@ -140,6 +135,14 @@ public enum Schema { return null; } + public int getDataVersion() { + return this.schemaId; + } + + public String getString() { + return this.str; + } + @Override public String toString() { return "MC: " + this.getString() + " [Schema: " + this.getDataVersion() + "]"; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/SchematicPlacingUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/SchematicPlacingUtils.java index a2834138..161c8751 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/SchematicPlacingUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/SchematicPlacingUtils.java @@ -5,7 +5,7 @@ import net.minecraft.core.Direction; import net.minecraft.core.Vec3i; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Container; import net.minecraft.world.entity.Display; @@ -197,10 +197,10 @@ public class SchematicPlacingUtils { ((Container) te).clearContent(); } - world.setBlock(pos, barrier, 4 | 16 | (notifyNeighbors ? 0 : 1024)); + world.setBlock(pos, barrier, 2 | 16 | (notifyNeighbors ? 0 : 512)); } - if (world.setBlock(pos, state, 2 | 16 | (notifyNeighbors ? 0 : 1024)) && teNBT != null) { + if (world.setBlock(pos, state, 2 | 16 | (notifyNeighbors ? 0 : 512)) && teNBT != null) { te = world.getBlockEntity(pos); if (te == null) { @@ -210,8 +210,7 @@ public class SchematicPlacingUtils { NbtUtils.writeBlockPosToTag(pos, teNBT); try { - te.loadWithComponents(teNBT, world.registryAccess().freeze()); - + te.loadWithComponents(teNBT, MinecraftServer.getServer().registryAccess()); } catch (Exception e) { ServuxProtocol.LOGGER.warn("Failed to load BlockEntity data for {} @ {}", state, pos); } @@ -332,7 +331,7 @@ public class SchematicPlacingUtils { continue; } CompoundTag tag = info.nbt().copy(); - String id = tag.getString("id"); + String id = tag.getStringOr("id", ""); // Avoid warning about invalid hanging position. // Note that this position isn't technically correct, but it only needs to be within 16 blocks @@ -348,14 +347,12 @@ public class SchematicPlacingUtils { NbtUtils.writeEntityPositionToTag(p, tag); } - tag.putInt("TileX", (int) p.x); - tag.putInt("TileY", (int) p.y); - tag.putInt("TileZ", (int) p.z); + tag.store("block_pos", BlockPos.CODEC, new BlockPos((int) p.x, (int) p.y, (int) p.z)); } - ListTag rotation = tag.getList("Rotation", Tag.TAG_FLOAT); - origRot[0] = rotation.getFloat(0); - origRot[1] = rotation.getFloat(1); + ListTag rotation = tag.getListOrEmpty("Rotation"); + origRot[0] = rotation.getFloatOr(0, 0F); + origRot[1] = rotation.getFloatOr(1, 0F); Entity entity = EntityUtils.createEntityAndPassengersFromNBT(tag, world); @@ -420,7 +417,7 @@ public class SchematicPlacingUtils { rotationYaw += entity.getYRot() - entity.rotate(rotationCombined); } - entity.absMoveTo(x, y, z, rotationYaw, entity.getXRot()); + entity.snapTo(x, y, z, rotationYaw, entity.getXRot()); EntityUtils.setEntityRotations(entity, rotationYaw, entity.getXRot()); } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java index 365b07d8..e19ec8fe 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java @@ -31,19 +31,16 @@ import java.util.List; import java.util.Map; import java.util.UUID; -@LeavesProtocol(namespace = "syncmatica") -public class CommunicationManager { - - private static final Map> downloadingFile = new HashMap<>(); - private static final Map playerMap = new HashMap<>(); +@LeavesProtocol.Register(namespace = "syncmatica") +public class CommunicationManager implements LeavesProtocol { protected static final Collection broadcastTargets = new ArrayList<>(); - protected static final Map downloadState = new HashMap<>(); protected static final Map modifyState = new HashMap<>(); - protected static final Rotation[] rotOrdinals = Rotation.values(); protected static final Mirror[] mirOrdinals = Mirror.values(); + private static final Map> downloadingFile = new HashMap<>(); + private static final Map playerMap = new HashMap<>(); public CommunicationManager() { } @@ -52,23 +49,8 @@ public class CommunicationManager { return playerMap.get(exchangeTarget).getGameProfile(); } - public void sendMessage(final @NotNull ExchangeTarget client, final MessageType type, final String identifier) { - if (client.getFeatureSet().hasFeature(Feature.MESSAGE)) { - final FriendlyByteBuf newPacketBuf = new FriendlyByteBuf(Unpooled.buffer()); - newPacketBuf.writeUtf(type.toString()); - newPacketBuf.writeUtf(identifier); - client.sendPacket(PacketType.MESSAGE.identifier, newPacketBuf); - } else if (playerMap.containsKey(client)) { - final ServerPlayer player = playerMap.get(client); - player.sendSystemMessage(Component.literal("Syncmatica " + type.toString() + " " + identifier)); - } - } - @ProtocolHandler.PlayerJoin public static void onPlayerJoin(ServerPlayer player) { - if (!LeavesConfig.protocol.syncmatica.enable) { - return; - } final ExchangeTarget newPlayer = player.connection.exchangeTarget; final VersionHandshakeServer hi = new VersionHandshakeServer(newPlayer); playerMap.put(newPlayer, player); @@ -79,9 +61,6 @@ public class CommunicationManager { @ProtocolHandler.PlayerLeave public static void onPlayerLeave(ServerPlayer player) { - if (!LeavesConfig.protocol.syncmatica.enable) { - return; - } final ExchangeTarget oldPlayer = player.connection.exchangeTarget; final Collection potentialMessageTarget = oldPlayer.getExchanges(); if (potentialMessageTarget != null) { @@ -94,11 +73,8 @@ public class CommunicationManager { playerMap.remove(oldPlayer); } - @ProtocolHandler.PayloadReceiver(payload = SyncmaticaPayload.class, payloadId = "main") + @ProtocolHandler.PayloadReceiver(payload = SyncmaticaPayload.class) public static void onPacketGet(ServerPlayer player, SyncmaticaPayload payload) { - if (!LeavesConfig.protocol.syncmatica.enable) { - return; - } onPacket(player.connection.exchangeTarget, payload.packetType(), payload.data()); } @@ -393,4 +369,21 @@ public class CommunicationManager { e.getPartner().getExchanges().remove(e); handleExchange(e); } + + public void sendMessage(final @NotNull ExchangeTarget client, final MessageType type, final String identifier) { + if (client.getFeatureSet().hasFeature(Feature.MESSAGE)) { + final FriendlyByteBuf newPacketBuf = new FriendlyByteBuf(Unpooled.buffer()); + newPacketBuf.writeUtf(type.toString()); + newPacketBuf.writeUtf(identifier); + client.sendPacket(PacketType.MESSAGE.identifier, newPacketBuf); + } else if (playerMap.containsKey(client)) { + final ServerPlayer player = playerMap.get(client); + player.sendSystemMessage(Component.literal("Syncmatica " + type.toString() + " " + identifier)); + } + } + + @Override + public boolean isActive() { + return LeavesConfig.protocol.syncmatica.enable; + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/FeatureSet.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/FeatureSet.java index ddd0f498..fdd2e32b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/FeatureSet.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/FeatureSet.java @@ -12,8 +12,18 @@ import java.util.Map; public class FeatureSet { private static final Map versionFeatures; + + static { + versionFeatures = new HashMap<>(); + versionFeatures.put("0.1", new FeatureSet(Collections.singletonList(Feature.CORE))); + } + private final Collection features; + public FeatureSet(final Collection features) { + this.features = features; + } + @Nullable public static FeatureSet fromVersionString(@NotNull String version) { if (version.matches("^\\d+(\\.\\d+){2,4}$")) { @@ -52,16 +62,7 @@ public class FeatureSet { return output.toString(); } - public FeatureSet(final Collection features) { - this.features = features; - } - public boolean hasFeature(final Feature f) { return features.contains(f); } - - static { - versionFeatures = new HashMap<>(); - versionFeatures.put("0.1", new FeatureSet(Collections.singletonList(Feature.CORE))); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/ServerPlacement.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/ServerPlacement.java index 70759c9d..2c7ca6c1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/ServerPlacement.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/ServerPlacement.java @@ -34,6 +34,49 @@ public class ServerPlacement { lastModifiedBy = owner; } + @Nullable + public static ServerPlacement fromJson(final @NotNull JsonObject obj) { + if (obj.has("id") + && obj.has("file_name") + && obj.has("hash") + && obj.has("origin") + && obj.has("rotation") + && obj.has("mirror")) { + final UUID id = UUID.fromString(obj.get("id").getAsString()); + final String name = obj.get("file_name").getAsString(); + final UUID hashValue = UUID.fromString(obj.get("hash").getAsString()); + + PlayerIdentifier owner = PlayerIdentifier.MISSING_PLAYER; + if (obj.has("owner")) { + owner = SyncmaticaProtocol.getPlayerIdentifierProvider().fromJson(obj.get("owner").getAsJsonObject()); + } + + final ServerPlacement newPlacement = new ServerPlacement(id, name, hashValue, owner); + final ServerPosition pos = ServerPosition.fromJson(obj.get("origin").getAsJsonObject()); + if (pos == null) { + return null; + } + newPlacement.origin = pos; + newPlacement.rotation = Rotation.valueOf(obj.get("rotation").getAsString()); + newPlacement.mirror = Mirror.valueOf(obj.get("mirror").getAsString()); + + if (obj.has("lastModifiedBy")) { + newPlacement.lastModifiedBy = SyncmaticaProtocol.getPlayerIdentifierProvider() + .fromJson(obj.get("lastModifiedBy").getAsJsonObject()); + } else { + newPlacement.lastModifiedBy = owner; + } + + if (obj.has("subregionData")) { + newPlacement.subRegionData = SubRegionData.fromJson(obj.get("subregionData")); + } + + return newPlacement; + } + + return null; + } + public UUID getId() { return id; } @@ -120,47 +163,4 @@ public class ServerPlacement { return obj; } - - @Nullable - public static ServerPlacement fromJson(final @NotNull JsonObject obj) { - if (obj.has("id") - && obj.has("file_name") - && obj.has("hash") - && obj.has("origin") - && obj.has("rotation") - && obj.has("mirror")) { - final UUID id = UUID.fromString(obj.get("id").getAsString()); - final String name = obj.get("file_name").getAsString(); - final UUID hashValue = UUID.fromString(obj.get("hash").getAsString()); - - PlayerIdentifier owner = PlayerIdentifier.MISSING_PLAYER; - if (obj.has("owner")) { - owner = SyncmaticaProtocol.getPlayerIdentifierProvider().fromJson(obj.get("owner").getAsJsonObject()); - } - - final ServerPlacement newPlacement = new ServerPlacement(id, name, hashValue, owner); - final ServerPosition pos = ServerPosition.fromJson(obj.get("origin").getAsJsonObject()); - if (pos == null) { - return null; - } - newPlacement.origin = pos; - newPlacement.rotation = Rotation.valueOf(obj.get("rotation").getAsString()); - newPlacement.mirror = Mirror.valueOf(obj.get("mirror").getAsString()); - - if (obj.has("lastModifiedBy")) { - newPlacement.lastModifiedBy = SyncmaticaProtocol.getPlayerIdentifierProvider() - .fromJson(obj.get("lastModifiedBy").getAsJsonObject()); - } else { - newPlacement.lastModifiedBy = owner; - } - - if (obj.has("subregionData")) { - newPlacement.subRegionData = SubRegionData.fromJson(obj.get("subregionData")); - } - - return newPlacement; - } - - return null; - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/ServerPosition.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/ServerPosition.java index 9775c6c4..63573bce 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/ServerPosition.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/ServerPosition.java @@ -15,6 +15,21 @@ public class ServerPosition { dimensionId = dim; } + public static ServerPosition fromJson(final JsonObject obj) { + if (obj.has("position") && obj.has("dimension")) { + final int x; + final int y; + final int z; + final JsonArray arr = obj.get("position").getAsJsonArray(); + x = arr.get(0).getAsInt(); + y = arr.get(1).getAsInt(); + z = arr.get(2).getAsInt(); + final BlockPos pos = new BlockPos(x, y, z); + return new ServerPosition(pos, obj.get("dimension").getAsString()); + } + return null; + } + public BlockPos getBlockPosition() { return position; } @@ -33,19 +48,4 @@ public class ServerPosition { obj.add("dimension", new JsonPrimitive(dimensionId)); return obj; } - - public static ServerPosition fromJson(final JsonObject obj) { - if (obj.has("position") && obj.has("dimension")) { - final int x; - final int y; - final int z; - final JsonArray arr = obj.get("position").getAsJsonArray(); - x = arr.get(0).getAsInt(); - y = arr.get(1).getAsInt(); - z = arr.get(2).getAsInt(); - final BlockPos pos = new BlockPos(x, y, z); - return new ServerPosition(pos, obj.get("dimension").getAsString()); - } - return null; - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SubRegionData.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SubRegionData.java index 22fdf92d..09bf7958 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SubRegionData.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SubRegionData.java @@ -24,6 +24,19 @@ public class SubRegionData { this.modificationData = modificationData; } + @NotNull + public static SubRegionData fromJson(final @NotNull JsonElement obj) { + final SubRegionData newSubRegionData = new SubRegionData(); + + newSubRegionData.isModified = true; + + for (final JsonElement modification : obj.getAsJsonArray()) { + newSubRegionData.modify(SubRegionPlacementModification.fromJson(modification.getAsJsonObject())); + } + + return newSubRegionData; + } + public void reset() { isModified = false; modificationData = null; @@ -67,19 +80,6 @@ public class SubRegionData { return arr; } - @NotNull - public static SubRegionData fromJson(final @NotNull JsonElement obj) { - final SubRegionData newSubRegionData = new SubRegionData(); - - newSubRegionData.isModified = true; - - for (final JsonElement modification : obj.getAsJsonArray()) { - newSubRegionData.modify(SubRegionPlacementModification.fromJson(modification.getAsJsonObject())); - } - - return newSubRegionData; - } - @Override public String toString() { if (!isModified) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SubRegionPlacementModification.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SubRegionPlacementModification.java index a52e299b..24100754 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SubRegionPlacementModification.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SubRegionPlacementModification.java @@ -23,22 +23,6 @@ public class SubRegionPlacementModification { this.mirror = mirror; } - public JsonObject toJson() { - final JsonObject obj = new JsonObject(); - - final JsonArray arr = new JsonArray(); - arr.add(position.getX()); - arr.add(position.getY()); - arr.add(position.getZ()); - obj.add("position", arr); - - obj.add("name", new JsonPrimitive(name)); - obj.add("rotation", new JsonPrimitive(rotation.name())); - obj.add("mirror", new JsonPrimitive(mirror.name())); - - return obj; - } - @Nullable public static SubRegionPlacementModification fromJson(final @NotNull JsonObject obj) { if (!obj.has("name") || !obj.has("position") || !obj.has("rotation") || !obj.has("mirror")) { @@ -58,6 +42,22 @@ public class SubRegionPlacementModification { return new SubRegionPlacementModification(name, position, rotation, mirror); } + public JsonObject toJson() { + final JsonObject obj = new JsonObject(); + + final JsonArray arr = new JsonArray(); + arr.add(position.getX()); + arr.add(position.getY()); + arr.add(position.getZ()); + obj.add("position", arr); + + obj.add("name", new JsonPrimitive(name)); + obj.add("rotation", new JsonPrimitive(rotation.name())); + obj.add("mirror", new JsonPrimitive(mirror.name())); + + return obj; + } + @Override public String toString() { return String.format("[name=%s, position=%s, rotation=%s, mirror=%s]", name, position, rotation, mirror); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SyncmaticaPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SyncmaticaPayload.java index 37710a78..d161e736 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SyncmaticaPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SyncmaticaPayload.java @@ -1,26 +1,18 @@ package org.leavesmc.leaves.protocol.syncmatica; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; -public record SyncmaticaPayload(ResourceLocation packetType, FriendlyByteBuf data) implements LeavesCustomPayload { +public record SyncmaticaPayload(ResourceLocation packetType, FriendlyByteBuf data) implements LeavesCustomPayload { + @ID private static final ResourceLocation NETWORK_ID = ResourceLocation.tryBuild(SyncmaticaProtocol.PROTOCOL_ID, "main"); - @New - public static SyncmaticaPayload decode(ResourceLocation location, FriendlyByteBuf buf) { - return new SyncmaticaPayload(buf.readResourceLocation(), new FriendlyByteBuf(buf.readBytes(buf.readableBytes()))); - } - - @Override - public void write(FriendlyByteBuf buf) { - buf.writeResourceLocation(this.packetType); - buf.writeBytes(this.data.readBytes(this.data.readableBytes())); - } - - @Override - public ResourceLocation id() { - return NETWORK_ID; - } + @Codec + private static final StreamCodec CODEC = StreamCodec.of( + (buf, payload) -> buf.writeResourceLocation(payload.packetType()).writeBytes(payload.data()), + buf -> new SyncmaticaPayload(buf.readResourceLocation(), new FriendlyByteBuf(buf.readBytes(buf.readableBytes()))) + ); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SyncmaticaProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SyncmaticaProtocol.java index 055da192..d092043f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SyncmaticaProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/SyncmaticaProtocol.java @@ -17,14 +17,15 @@ public class SyncmaticaProtocol { public static final String PROTOCOL_ID = "syncmatica"; public static final String PROTOCOL_VERSION = "leaves-syncmatica-1.1.0"; - - private static boolean loaded = false; private static final File litematicFolder = new File("." + File.separator + "syncmatics"); private static final PlayerIdentifierProvider playerIdentifierProvider = new PlayerIdentifierProvider(); private static final CommunicationManager communicationManager = new CommunicationManager(); private static final FeatureSet featureSet = new FeatureSet(Arrays.asList(Feature.values())); private static final SyncmaticManager syncmaticManager = new SyncmaticManager(); private static final FileStorage fileStorage = new FileStorage(); + private static final int[] ILLEGAL_CHARS = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47}; + private static final String ILLEGAL_PATTERNS = "(^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\\..*)?$)|(^\\.\\.*$)"; + private static boolean loaded = false; public static File getLitematicFolder() { return litematicFolder; @@ -75,9 +76,6 @@ public class SyncmaticaProtocol { return UUID.nameUUIDFromBytes(messageDigest.digest()); } - private static final int[] ILLEGAL_CHARS = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47}; - private static final String ILLEGAL_PATTERNS = "(^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\\..*)?$)|(^\\.\\.*$)"; - @NotNull public static String sanitizeFileName(final @NotNull String badFileName) { final StringBuilder sanitized = new StringBuilder(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/AbstractExchange.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/AbstractExchange.java index b06ffeac..aa40f0a1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/AbstractExchange.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/AbstractExchange.java @@ -8,14 +8,21 @@ import java.util.UUID; public abstract class AbstractExchange implements Exchange { + private final ExchangeTarget partner; private boolean success = false; private boolean finished = false; - private final ExchangeTarget partner; protected AbstractExchange(final ExchangeTarget partner) { this.partner = partner; } + protected static boolean checkUUID(final FriendlyByteBuf sourceBuf, final UUID targetId) { + final int r = sourceBuf.readerIndex(); + final UUID sourceId = sourceBuf.readUUID(); + sourceBuf.readerIndex(r); + return sourceId.equals(targetId); + } + @Override public ExchangeTarget getPartner() { return partner; @@ -56,11 +63,4 @@ public abstract class AbstractExchange implements Exchange { success = true; onClose(); } - - protected static boolean checkUUID(final FriendlyByteBuf sourceBuf, final UUID targetId) { - final int r = sourceBuf.readerIndex(); - final UUID sourceId = sourceBuf.readUUID(); - sourceBuf.readerIndex(r); - return sourceId.equals(targetId); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/DownloadExchange.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/DownloadExchange.java index b0463dc8..5880678b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/DownloadExchange.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/exchange/DownloadExchange.java @@ -4,6 +4,7 @@ import io.netty.buffer.Unpooled; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.protocol.syncmatica.CommunicationManager; import org.leavesmc.leaves.protocol.syncmatica.MessageType; import org.leavesmc.leaves.protocol.syncmatica.PacketType; import org.leavesmc.leaves.protocol.syncmatica.ServerPlacement; @@ -101,7 +102,8 @@ public class DownloadExchange extends AbstractExchange { @Override protected void onClose() { - getManager().setDownloadState(toDownload, false); + getManager(); + CommunicationManager.setDownloadState(toDownload, false); try { outputStream.close(); } catch (final IOException e) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/region/IRegionFile.java b/leaves-server/src/main/java/org/leavesmc/leaves/region/IRegionFile.java index d4f6ed71..506843c7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/region/IRegionFile.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/region/IRegionFile.java @@ -37,4 +37,6 @@ public interface IRegionFile extends ChunkSystemRegionFile, AutoCloseable { boolean hasChunk(ChunkPos pos); boolean recalculateHeader() throws IOException; + + int getRecalculateCount(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/region/linear/LinearRegionFile.java b/leaves-server/src/main/java/org/leavesmc/leaves/region/linear/LinearRegionFile.java index c002d6f1..07982b9c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/region/linear/LinearRegionFile.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/region/linear/LinearRegionFile.java @@ -611,6 +611,11 @@ public class LinearRegionFile implements IRegionFile { return false; } + @Override + public int getRecalculateCount() { + return 0; + } + public void setOversized(int x, int z, boolean something) { } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/replay/Recorder.java b/leaves-server/src/main/java/org/leavesmc/leaves/replay/Recorder.java index d8ea3495..d1d34793 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/replay/Recorder.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/replay/Recorder.java @@ -46,21 +46,19 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; -import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executor; import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; public class Recorder extends Connection { - private static final LeavesLogger LOGGER = LeavesLogger.LOGGER; + public static final Executor saveService = Executors.newVirtualThreadPerTaskExecutor(); + public static final LeavesLogger LOGGER = LeavesLogger.LOGGER; private final ReplayFile replayFile; private final ServerPhotographer photographer; private final RecorderOption recorderOption; private final RecordMetaData metaData; - private final ExecutorService saveService = Executors.newSingleThreadExecutor(); - private boolean stopped = false; private boolean paused = false; private boolean resumeOnNextPacket = true; @@ -209,7 +207,7 @@ public class Recorder extends Connection { } private void saveMetadata() { - saveService.submit(() -> { + saveService.execute(() -> { try { replayFile.saveMetaData(metaData); } catch (IOException e) { @@ -225,14 +223,7 @@ public class Recorder extends Connection { private void savePacket(Packet packet, final ConnectionProtocol protocol) { try { final long timestamp = getCurrentTimeAndUpdate(); - saveService.submit(() -> { - try { - replayFile.savePacket(timestamp, packet, protocol); - } catch (Exception e) { - LOGGER.severe("Error saving packet"); - e.printStackTrace(); - } - }); + replayFile.savePacket(timestamp, packet, protocol); } catch (Exception e) { LOGGER.severe("Error saving packet"); e.printStackTrace(); @@ -250,13 +241,7 @@ public class Recorder extends Connection { metaData.duration = (int) lastPacket; return CompletableFuture.runAsync(() -> { saveMetadata(); - saveService.shutdown(); boolean interrupted = false; - try { - saveService.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - interrupted = true; - } try { if (save) { replayFile.closeAndSave(dest); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/replay/ReplayFile.java b/leaves-server/src/main/java/org/leavesmc/leaves/replay/ReplayFile.java index 8d96445f..4b1579b1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/replay/ReplayFile.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/replay/ReplayFile.java @@ -3,6 +3,7 @@ package org.leavesmc.leaves.replay; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import net.minecraft.SharedConstants; import net.minecraft.network.ConnectionProtocol; @@ -37,6 +38,9 @@ import java.util.zip.CRC32; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import static org.leavesmc.leaves.replay.Recorder.LOGGER; +import static org.leavesmc.leaves.replay.Recorder.saveService; + public class ReplayFile { private static final String RECORDING_FILE = "recording.tmcpr"; @@ -93,8 +97,7 @@ public class ReplayFile { protocol.codec().encode(buf, packet); buf.readerIndex(0); - byte[] ret = new byte[buf.readableBytes()]; - buf.readBytes(ret); + byte[] ret = ByteBufUtil.getBytes(buf); buf.release(); return ret; } @@ -118,9 +121,16 @@ public class ReplayFile { public void savePacket(long timestamp, Packet packet, ConnectionProtocol protocol) throws Exception { byte[] data = getPacketBytes(packet, protocol); - packetStream.writeInt((int) timestamp); - packetStream.writeInt(data.length); - packetStream.write(data); + saveService.execute(() -> { + try { + packetStream.writeInt((int) timestamp); + packetStream.writeInt(data.length); + packetStream.write(data); + } catch (Exception e) { + LOGGER.severe("Error saving packet"); + e.printStackTrace(); + } + }); } public synchronized void closeAndSave(File file) throws IOException { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/ArrayConstants.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/ArrayConstants.java deleted file mode 100644 index 232e3cb0..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/ArrayConstants.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.leavesmc.leaves.util; - -import net.minecraft.server.level.ServerLevel; - -// Powered by Gale(https://github.com/GaleMC/Gale) - -public class ArrayConstants { - - private ArrayConstants() { - } - - public static final Object[] emptyObjectArray = new Object[0]; - public static final int[] emptyIntArray = new int[0]; - public static final int[] zeroSingletonIntArray = new int[]{0}; - public static final byte[] emptyByteArray = new byte[0]; - public static final String[] emptyStringArray = new String[0]; - public static final long[] emptyLongArray = new long[0]; - public static final org.bukkit.entity.Entity[] emptyBukkitEntityArray = new org.bukkit.entity.Entity[0]; - public static final net.minecraft.world.entity.Entity[] emptyEntityArray = new net.minecraft.world.entity.Entity[0]; - public static final ServerLevel[] emptyServerLevelArray = new ServerLevel[0]; - -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/ElytraAeronauticsHelper.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/ElytraAeronauticsHelper.java index dfc081cc..6dd530e7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/ElytraAeronauticsHelper.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/util/ElytraAeronauticsHelper.java @@ -3,38 +3,143 @@ package org.leavesmc.leaves.util; import ca.spottedleaf.moonrise.common.PlatformHooks; import net.minecraft.core.SectionPos; import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.FireworkRocketEntity; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.FireworkExplosion; +import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.phys.Vec3; +import org.bukkit.event.entity.CreatureSpawnEvent; import org.leavesmc.leaves.LeavesConfig; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + public class ElytraAeronauticsHelper { - public static void flightBehaviour(Player player, Vec3 velocity) { - if (LeavesConfig.modify.elytraAeronautics.noChunk) { - if ((LeavesConfig.modify.elytraAeronautics.noChunkSpeed <= 0.0D || velocity.horizontalDistanceSqr() >= LeavesConfig.modify.elytraAeronautics.noChunkSpeed) - && (LeavesConfig.modify.elytraAeronautics.noChunkHeight <= 0.0D || player.getY() >= LeavesConfig.modify.elytraAeronautics.noChunkHeight)) { - if (!player.elytraAeronauticsNoChunk) { - player.elytraAeronauticsNoChunk = true; - ServerPlayer serverPlayer = (ServerPlayer) player; - if (LeavesConfig.modify.elytraAeronautics.noChunkMes) { - serverPlayer.sendSystemMessage(Component.literal(LeavesConfig.modify.elytraAeronautics.noChunkStartMes), true); - } - PlatformHooks.get().removePlayerFromDistanceMaps(serverPlayer.serverLevel(), serverPlayer); - serverPlayer.serverLevel().chunkSource.chunkMap.getDistanceManager().removePlayer(serverPlayer.getLastSectionPos(), serverPlayer); + public static final Map> globalTickingFireworks = new HashMap<>(); + + public static void tick(ServerLevel level) { + List tickingFireworks = globalTickingFireworks.getOrDefault(level, Collections.emptyList()); + for (Iterator it = tickingFireworks.iterator(); it.hasNext(); ) { + FireworkRocketEntity firework = it.next(); + firework.life++; + Vec3 handHoldingItemAngle; + if (!firework.isAlive()) { + it.remove(); + } + if (firework.attachedToEntity == null || firework.life > firework.lifetime) { + explodeNoClip(firework); + continue; + } + if (firework.attachedToEntity.isFallFlying()) { + if (firework.attachedToEntity instanceof ServerPlayer player) { + player.connection.send(new ClientboundSetEntityMotionPacket(player)); } + Vec3 lookAngle = firework.attachedToEntity.getLookAngle(); + Vec3 deltaMovement = firework.attachedToEntity.getDeltaMovement(); + firework.attachedToEntity.setDeltaMovement(deltaMovement.add( + lookAngle.x * 0.1 + (lookAngle.x * 1.5 - deltaMovement.x) * 0.5, + lookAngle.y * 0.1 + (lookAngle.y * 1.5 - deltaMovement.y) * 0.5, + lookAngle.z * 0.1 + (lookAngle.z * 1.5 - deltaMovement.z) * 0.5 + )); + firework.attachedToEntity.hurtMarked = true; + handHoldingItemAngle = firework.attachedToEntity.getHandHoldingItemAngle(Items.FIREWORK_ROCKET); } else { - if (player.elytraAeronauticsNoChunk) { - player.elytraAeronauticsNoChunk = false; - ServerPlayer serverPlayer = (ServerPlayer) player; - if (LeavesConfig.modify.elytraAeronautics.noChunkMes) { - serverPlayer.sendSystemMessage(Component.literal(LeavesConfig.modify.elytraAeronautics.noChunkEndMes), true); - } - PlatformHooks.get().addPlayerToDistanceMaps((ServerLevel) serverPlayer.level(), serverPlayer); - ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap.getDistanceManager().addPlayer(SectionPos.of(serverPlayer), serverPlayer); - } + handHoldingItemAngle = Vec3.ZERO; + } + + firework.setPos( + firework.attachedToEntity.getX() + handHoldingItemAngle.x, + firework.attachedToEntity.getY() + handHoldingItemAngle.y, + firework.attachedToEntity.getZ() + handHoldingItemAngle.z + ); + firework.setDeltaMovement(firework.attachedToEntity.getDeltaMovement()); + } + } + + private static void explodeNoClip(FireworkRocketEntity firework) { + if (firework.life <= firework.lifetime) { + firework.discard(); + } + ServerLevel level = firework.level().getMinecraftWorld(); + List explosions = firework.getExplosions(); + if (!explosions.isEmpty() && firework.attachedToEntity != null && + org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(firework)) { + level.broadcastEntityEvent(firework, (byte) 17); + firework.gameEvent(GameEvent.EXPLODE, firework.getOwner()); + firework.attachedToEntity.hurtServer(level, firework.damageSources().fireworks(firework, firework.getOwner()), 5.0F + explosions.size() * 2); + firework.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.EXPLODE); + } + } + + public static boolean proxySpawnAndTick(FireworkRocketEntity entity) { + if (!LeavesConfig.modify.elytraAeronautics.enableNoChunkLoad) { + return false; + } + entity.generation = false; + if (entity.valid) { + MinecraftServer.LOGGER.error("Attempted Double World add on {}", entity, new Throwable()); + return true; + } + if (entity.spawnReason == null) entity.spawnReason = CreatureSpawnEvent.SpawnReason.DEFAULT; + if (entity.isRemoved()) { + return false; + } + if (!org.bukkit.craftbukkit.event.CraftEventFactory.doEntityAddEventCalling(entity.level(), entity, CreatureSpawnEvent.SpawnReason.DEFAULT)) { + return false; + } + globalTickingFireworks.computeIfAbsent(entity.level().getMinecraftWorld(), w -> new ArrayList<>()).add(entity); + return true; + } + + public static void flightBehaviour(Player player, Vec3 velocity) { + if (!LeavesConfig.modify.elytraAeronautics.enableNoChunkLoad) { + return; + } + if ((LeavesConfig.modify.elytraAeronautics.noChunkSpeed <= 0.0D || velocity.horizontalDistanceSqr() >= LeavesConfig.modify.elytraAeronautics.noChunkSpeed) + && (LeavesConfig.modify.elytraAeronautics.noChunkHeight <= 0.0D || player.getY() >= LeavesConfig.modify.elytraAeronautics.noChunkHeight)) { + handleCruiseActivate(player); + } else { + handleCruiseDeactivate(player); + } + } + + public static void handleCruiseActivate(Player player) { + if (!player.elytraAeronauticsNoChunk) { + player.elytraAeronauticsNoChunk = true; + ServerPlayer serverPlayer = (ServerPlayer) player; + if (LeavesConfig.modify.elytraAeronautics.doSendMessages) { + serverPlayer.sendSystemMessage(Component.literal(LeavesConfig.modify.elytraAeronautics.startMessage), true); + } + try { + PlatformHooks.get().removePlayerFromDistanceMaps(serverPlayer.serverLevel(), serverPlayer); + serverPlayer.serverLevel().chunkSource.chunkMap.getDistanceManager().removePlayer(serverPlayer.getLastSectionPos(), serverPlayer); + } catch (Exception ignored) { } } } -} + + public static void handleCruiseDeactivate(Player player) { + if (player.elytraAeronauticsNoChunk) { + player.elytraAeronauticsNoChunk = false; + ServerPlayer serverPlayer = (ServerPlayer) player; + if (LeavesConfig.modify.elytraAeronautics.doSendMessages) { + serverPlayer.sendSystemMessage(Component.literal(LeavesConfig.modify.elytraAeronautics.endMessage), true); + } + try { + PlatformHooks.get().addPlayerToDistanceMaps((ServerLevel) serverPlayer.level(), serverPlayer); + ((ServerLevel) serverPlayer.level()).chunkSource.chunkMap.getDistanceManager().addPlayer(SectionPos.of(serverPlayer), serverPlayer); + } catch (Exception ignored) { + } + } + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/HopperCounter.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/HopperCounter.java index 9c101506..83fe0ead 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/HopperCounter.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/util/HopperCounter.java @@ -235,6 +235,7 @@ public class HopperCounter { entry(Items.AMETHYST_SHARD, Blocks.AMETHYST_BLOCK) ); + @SuppressWarnings("deprecation") @Nullable public static TextColor guessColor(@NotNull MinecraftServer server, Item item) { RegistryAccess registryAccess = server.registryAccess(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/LeavesVersionFetcher.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/LeavesVersionFetcher.java index 78c6873b..ea0d07e2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/LeavesVersionFetcher.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/util/LeavesVersionFetcher.java @@ -37,7 +37,7 @@ public class LeavesVersionFetcher extends PaperVersionFetcher { @NotNull @Override - public Component getVersionMessage(@NotNull String serverVersion) { + public Component getVersionMessage() { final Component updateMessage; final ServerBuildInfo build = ServerBuildInfo.buildInfo(); if (build.buildNumber().isEmpty() && build.gitCommit().isEmpty()) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/ReturnPortalManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/ReturnPortalManager.java index 67eb48e5..aebed438 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/ReturnPortalManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/util/ReturnPortalManager.java @@ -1,6 +1,7 @@ package org.leavesmc.leaves.util; import net.minecraft.core.BlockPos; +import net.minecraft.core.UUIDUtil; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -27,6 +28,7 @@ public class ReturnPortalManager { private static final String FROM_POS = "FromPos"; private static final String TO_POS = "ToPos"; + @SuppressWarnings("deprecation") public static BlockPos findPortalAt(Player player, ResourceKey dim, BlockPos pos) { MinecraftServer server = player.level().getServer(); if (server != null) { @@ -42,7 +44,7 @@ public class ReturnPortalManager { public static ListTag getPlayerPortalList(Player player) { CompoundTag data = player.getLeavesData(); - ListTag list = data.getList(RETURN_PORTAL_LIST, Tag.TAG_COMPOUND); + ListTag list = data.getListOrEmpty(RETURN_PORTAL_LIST); data.put(RETURN_PORTAL_LIST, list); return list; } @@ -52,12 +54,12 @@ public class ReturnPortalManager { ListTag portalList = getPlayerPortalList(player); for (Tag entry : portalList) { CompoundTag portal = (CompoundTag) entry; - ResourceKey entryFromDim = ResourceKey.create(Registries.DIMENSION, ResourceLocation.parse(portal.getString(FROM_DIM))); + ResourceKey entryFromDim = ResourceKey.create(Registries.DIMENSION, ResourceLocation.parse(portal.getString(FROM_DIM).orElseThrow())); if (entryFromDim == fromDim) { - BlockPos portalTrigger = BlockPos.of(portal.getLong(FROM_POS)); + BlockPos portalTrigger = BlockPos.of(portal.getLong(FROM_POS).orElseThrow()); if (portalTrigger.distSqr(fromPos) <= MAX_PORTAL_DISTANCE_SQ) { - final var uid = portal.hasUUID(RETURN_PORTAL_UID) ? portal.getUUID(RETURN_PORTAL_UID) : UUID.randomUUID(); - final var pos = BlockPos.of(portal.getLong(TO_POS)); + final UUID uid = portal.contains(RETURN_PORTAL_UID) ? portal.read(RETURN_PORTAL_UID, UUIDUtil.CODEC).orElseThrow() : UUID.randomUUID(); + final BlockPos pos = BlockPos.of(portal.getLong(TO_POS).orElseThrow()); return new ReturnPortal(uid, pos); } } @@ -74,7 +76,7 @@ public class ReturnPortalManager { } CompoundTag portalCompound = new CompoundTag(); - portalCompound.putUUID(RETURN_PORTAL_UID, UUID.randomUUID()); + portalCompound.store(RETURN_PORTAL_UID, UUIDUtil.CODEC, UUID.randomUUID()); portalCompound.putString(FROM_DIM, String.valueOf(fromDim.location())); portalCompound.putLong(FROM_POS, fromPos.asLong()); portalCompound.putLong(TO_POS, toPos.asLong()); @@ -86,7 +88,7 @@ public class ReturnPortalManager { ListTag portalList = getPlayerPortalList(player); for (int i = 0; i < portalList.size(); i++) { CompoundTag entry = (CompoundTag) portalList.get(i); - if (entry.hasUUID(RETURN_PORTAL_UID) && entry.getUUID(RETURN_PORTAL_UID).equals(portal.uid)) { + if (entry.contains(RETURN_PORTAL_UID) && entry.read(RETURN_PORTAL_UID, UUIDUtil.CODEC).orElseThrow().equals(portal.uid)) { portalList.remove(i); break; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/ShulkerBoxUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/ShulkerBoxUtils.java index ce2ad5a5..a0227fad 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/ShulkerBoxUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/util/ShulkerBoxUtils.java @@ -1,14 +1,17 @@ package org.leavesmc.leaves.util; import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomData; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.level.block.ShulkerBoxBlock; -import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; +import java.util.Optional; + public class ShulkerBoxUtils { public static boolean shulkerBoxNoItem(@NotNull ItemStack stack) { @@ -23,10 +26,34 @@ public class ShulkerBoxUtils { return stack.getMaxStackSize(); } - public static ItemStack correctItemStackMaxStackSize(ItemStack itemStack) { - int trulyMaxStackSize = getItemStackMaxCount(itemStack); - if (itemStack.getMaxStackSize() != trulyMaxStackSize) { - itemStack.set(DataComponents.MAX_STACK_SIZE, trulyMaxStackSize); + public static int getItemStackMaxCountReal(ItemStack stack) { + CompoundTag nbt = Optional.ofNullable(stack.get(DataComponents.CUSTOM_DATA)).orElse(CustomData.EMPTY).copyTag(); + return nbt.getInt("Leaves.RealStackSize").orElse(stack.getMaxStackSize()); + } + + public static ItemStack encodeMaxStackSize(ItemStack itemStack) { + int realMaxStackSize = getItemStackMaxCountReal(itemStack); + int modifiedMaxStackSize = getItemStackMaxCount(itemStack); + if (itemStack.getMaxStackSize() != modifiedMaxStackSize) { + itemStack.set(DataComponents.MAX_STACK_SIZE, modifiedMaxStackSize); + CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); + nbt.putInt("Leaves.RealStackSize", realMaxStackSize); + itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt)); + } + return itemStack; + } + + public static ItemStack decodeMaxStackSize(ItemStack itemStack) { + int realMaxStackSize = getItemStackMaxCountReal(itemStack); + if (itemStack.getMaxStackSize() != realMaxStackSize) { + itemStack.set(DataComponents.MAX_STACK_SIZE, realMaxStackSize); + CompoundTag nbt = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); + nbt.remove("Leaves.RealStackSize"); + if (nbt.isEmpty()) { + itemStack.remove(DataComponents.CUSTOM_DATA); + } else { + itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(nbt)); + } } return itemStack; } @@ -34,4 +61,4 @@ public class ShulkerBoxUtils { public static boolean isStackable(ItemStack itemStack) { return getItemStackMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged()); } -} +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/TicketHelper.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/TicketHelper.java index a47c3236..7e21fa51 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/TicketHelper.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/util/TicketHelper.java @@ -29,9 +29,10 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Set; +@SuppressWarnings("rawtypes") public class TicketHelper { - private static final Set> NEED_SAVED = Set.of(TicketType.PLAYER, TicketType.PORTAL, RegionizedPlayerChunkLoader.PLAYER_TICKET); + private static final Set NEED_SAVED = Set.of(TicketType.PORTAL, RegionizedPlayerChunkLoader.PLAYER_TICKET); public static void tryToLoadTickets() { if (!LeavesConfig.modify.fastResume) { @@ -98,10 +99,10 @@ public class TicketHelper { JsonArray levelArray = new JsonArray(); DistanceManager chunkDistanceManager = level.getChunkSource().chunkMap.distanceManager; - for (Long2ObjectMap.Entry>> chunkTickets : chunkDistanceManager.moonrise$getChunkHolderManager().getTicketsCopy().long2ObjectEntrySet()) { + for (Long2ObjectMap.Entry> chunkTickets : chunkDistanceManager.moonrise$getChunkHolderManager().getTicketsCopy().long2ObjectEntrySet()) { long chunkKey = chunkTickets.getLongKey(); JsonArray ticketArray = new JsonArray(); - SortedArraySet> tickets = chunkTickets.getValue(); + SortedArraySet tickets = chunkTickets.getValue(); for (Ticket ticket : tickets) { if (!NEED_SAVED.contains(ticket.getType())) { @@ -132,24 +133,20 @@ public class TicketHelper { json.addProperty("type", ticket.getType().toString()); json.addProperty("ticketLevel", ticket.getTicketLevel()); json.addProperty("removeDelay", ticket.moonrise$getRemoveDelay()); - if (ticket.key instanceof BlockPos pos) { - json.addProperty("key", pos.asLong()); - } else if (ticket.key instanceof ChunkPos pos) { - json.addProperty("key", pos.toLong()); - } else if (ticket.key instanceof Long l) { - json.addProperty("key", l); + switch (ticket.getIdentifier()) { + case BlockPos pos -> json.addProperty("key", pos.asLong()); + case ChunkPos pos -> json.addProperty("key", pos.toLong()); + case Long l -> json.addProperty("key", l); + default -> { + } } return json; } private static Ticket tickFormJson(JsonObject json) { - TicketType ticketType = null; + TicketType ticketType = null; Object key = null; switch (json.get("type").getAsString()) { - case "player" -> { - ticketType = TicketType.PLAYER; - key = new ChunkPos(json.get("key").getAsLong()); - } case "portal" -> { ticketType = TicketType.PORTAL; key = BlockPos.of(json.get("key").getAsLong()); @@ -166,8 +163,7 @@ public class TicketHelper { int ticketLevel = json.get("ticketLevel").getAsInt(); long removeDelay = json.get("removeDelay").getAsLong(); - @SuppressWarnings("unchecked") - Ticket ticket = new Ticket<>((TicketType) ticketType, ticketLevel, (T) key); + Ticket ticket = new Ticket<>(ticketType, ticketLevel, key); ticket.moonrise$setRemoveDelay(removeDelay); return ticket; diff --git a/leaves-server/src/main/resources/assets/minecraft/lang/zh_cn.json b/leaves-server/src/main/resources/assets/minecraft/lang/zh_cn.json index be39e96f..41409c82 100644 --- a/leaves-server/src/main/resources/assets/minecraft/lang/zh_cn.json +++ b/leaves-server/src/main/resources/assets/minecraft/lang/zh_cn.json @@ -46,6 +46,8 @@ "advancements.adventure.crafters_crafting_crafters.title": "合成器合成合成器", "advancements.adventure.fall_from_world_height.description": "从世界顶部(建筑高度限制处)自由落体,坠至世界底部并存活下来", "advancements.adventure.fall_from_world_height.title": "上天入地", + "advancements.adventure.heart_transplanter.description": "将嘎枝之心以正确朝向放在两个苍白橡木原木方块中间", + "advancements.adventure.heart_transplanter.title": "移心接木", "advancements.adventure.hero_of_the_village.description": "成功在袭击中保卫村庄", "advancements.adventure.hero_of_the_village.title": "村庄英雄", "advancements.adventure.honey_block_slide.description": "跳入蜂蜜块以缓冲摔落", @@ -106,6 +108,8 @@ "advancements.adventure.two_birds_one_arrow.title": "一箭双雕", "advancements.adventure.under_lock_and_key.description": "用试炼钥匙解锁宝库", "advancements.adventure.under_lock_and_key.title": "珍藏密敛", + "advancements.adventure.use_lodestone.description": "对着磁石使用指南针", + "advancements.adventure.use_lodestone.title": "天涯共此石", "advancements.adventure.very_very_frightening.description": "雷击一名村民", "advancements.adventure.very_very_frightening.title": "魔女审判", "advancements.adventure.voluntary_exile.description": "杀死一名袭击队长。\n或许该考虑暂时远离村庄……", @@ -149,7 +153,7 @@ "advancements.husbandry.breed_an_animal.title": "我从哪儿来?", "advancements.husbandry.complete_catalogue.description": "驯服所有种类的猫!", "advancements.husbandry.complete_catalogue.title": "百猫全书", - "advancements.husbandry.feed_snifflet.description": "喂食一只幼年嗅探兽", + "advancements.husbandry.feed_snifflet.description": "喂食一只小嗅探兽", "advancements.husbandry.feed_snifflet.title": "小小嗅探兽", "advancements.husbandry.fishy_business.description": "钓到一条鱼", "advancements.husbandry.fishy_business.title": "腥味十足的生意", @@ -165,6 +169,8 @@ "advancements.husbandry.netherite_hoe.title": "终极奉献", "advancements.husbandry.obtain_sniffer_egg.description": "获得嗅探兽蛋", "advancements.husbandry.obtain_sniffer_egg.title": "怪味蛋", + "advancements.husbandry.place_dried_ghast_in_water.description": "将失水恶魂方块放在水中", + "advancements.husbandry.place_dried_ghast_in_water.title": "补水保湿!", "advancements.husbandry.plant_any_sniffer_seed.description": "种植任意嗅探兽种子", "advancements.husbandry.plant_any_sniffer_seed.title": "播种往事", "advancements.husbandry.plant_seed.description": "种下种子,见证它的成长", @@ -342,6 +348,7 @@ "argument.float.big": "浮点型数据不能大于%s,但发现了%s", "argument.float.low": "浮点型数据不能小于%s,但发现了%s", "argument.gamemode.invalid": "未知的游戏模式:%s", + "argument.hexcolor.invalid": "无效的十六进制颜色代码:“%s”", "argument.id.invalid": "无效的ID", "argument.id.unknown": "未知的ID:%s", "argument.integer.big": "整型数据不能大于%s,但发现了%s", @@ -384,10 +391,11 @@ "argument.scoreHolder.empty": "找不到与分数关联的持有者", "argument.scoreboardDisplaySlot.invalid": "未知的显示位置“%s”", "argument.style.invalid": "无效的样式:%s", - "argument.time.invalid_tick_count": "刻的计数必须为非负数", + "argument.time.invalid_tick_count": "刻数必须为非负数", "argument.time.invalid_unit": "无效的单位", "argument.time.tick_count_too_low": "刻数不能小于%s,却发现了%s", "argument.uuid.invalid": "无效的UUID", + "argument.waypoint.invalid": "选择的实体不是路径点", "arguments.block.tag.unknown": "未知的方块标签“%s”", "arguments.function.tag.unknown": "未知的函数标签“%s”", "arguments.function.unknown": "未知的函数%s", @@ -426,6 +434,7 @@ "attribute.name.block_break_speed": "方块破坏速度", "attribute.name.block_interaction_range": "方块交互距离", "attribute.name.burning_time": "着火时间", + "attribute.name.camera_distance": "摄像机距离", "attribute.name.entity_interaction_range": "实体交互距离", "attribute.name.explosion_knockback_resistance": "爆炸击退抗性", "attribute.name.fall_damage_multiplier": "摔落伤害倍数", @@ -483,6 +492,8 @@ "attribute.name.sweeping_damage_ratio": "横扫伤害比率", "attribute.name.tempt_range": "生物引诱范围", "attribute.name.water_movement_efficiency": "水中移动效率", + "attribute.name.waypoint_receive_range": "路径点接收距离", + "attribute.name.waypoint_transmit_range": "路径点传输距离", "attribute.name.zombie.spawn_reinforcements": "僵尸增援", "biome.minecraft.badlands": "恶地", "biome.minecraft.bamboo_jungle": "竹林", @@ -1389,7 +1400,9 @@ "block.minecraft.bubble_coral_fan": "气泡珊瑚扇", "block.minecraft.bubble_coral_wall_fan": "墙上的气泡珊瑚扇", "block.minecraft.budding_amethyst": "紫水晶母岩", + "block.minecraft.bush": "灌木丛", "block.minecraft.cactus": "仙人掌", + "block.minecraft.cactus_flower": "仙人掌花", "block.minecraft.cake": "蛋糕", "block.minecraft.calcite": "方解石", "block.minecraft.calibrated_sculk_sensor": "校频幽匿感测体", @@ -1588,6 +1601,7 @@ "block.minecraft.dragon_egg": "龙蛋", "block.minecraft.dragon_head": "龙首", "block.minecraft.dragon_wall_head": "墙上的龙首", + "block.minecraft.dried_ghast": "失水恶魂", "block.minecraft.dried_kelp_block": "干海带块", "block.minecraft.dripstone_block": "滴水石块", "block.minecraft.dropper": "投掷器", @@ -1620,6 +1634,7 @@ "block.minecraft.fire_coral_block": "火珊瑚块", "block.minecraft.fire_coral_fan": "火珊瑚扇", "block.minecraft.fire_coral_wall_fan": "墙上的火珊瑚扇", + "block.minecraft.firefly_bush": "萤火虫灌木丛", "block.minecraft.fletching_table": "制箭台", "block.minecraft.flower_pot": "花盆", "block.minecraft.flowering_azalea": "盛开的杜鹃花丛", @@ -2100,6 +2115,7 @@ "block.minecraft.sea_pickle": "海泡菜", "block.minecraft.seagrass": "海草", "block.minecraft.set_spawn": "已设置重生点", + "block.minecraft.short_dry_grass": "矮枯草丛", "block.minecraft.short_grass": "矮草丛", "block.minecraft.shroomlight": "菌光体", "block.minecraft.shulker_box": "潜影盒", @@ -2196,6 +2212,7 @@ "block.minecraft.suspicious_gravel": "可疑的沙砾", "block.minecraft.suspicious_sand": "可疑的沙子", "block.minecraft.sweet_berry_bush": "甜浆果丛", + "block.minecraft.tall_dry_grass": "高枯草丛", "block.minecraft.tall_grass": "高草丛", "block.minecraft.tall_seagrass": "高海草", "block.minecraft.target": "标靶", @@ -2204,6 +2221,7 @@ "block.minecraft.test_instance_block": "测试实例方块", "block.minecraft.tinted_glass": "遮光玻璃", "block.minecraft.tnt": "TNT", + "block.minecraft.tnt.disabled": "TNT爆炸已禁用", "block.minecraft.torch": "火把", "block.minecraft.torchflower": "火把花", "block.minecraft.torchflower_crop": "火把花植株", @@ -2527,6 +2545,11 @@ "commands.data.storage.get": "在存储%2$s中的%1$s在乘以倍率%3$s后的值是%4$s", "commands.data.storage.modified": "已修改存储%s", "commands.data.storage.query": "存储%s含有以下内容:%s", + "commands.datapack.create.already_exists": "名为“%s”的包已经存在", + "commands.datapack.create.invalid_name": "新包名“%s”中包含无效字符", + "commands.datapack.create.io_failure": "无法创建名称为“%s”的包,请检查日志", + "commands.datapack.create.metadata_encode_failure": "无法编码名称为“%s”的包的元数据:%s", + "commands.datapack.create.success": "已创建名为“%s”的空包", "commands.datapack.disable.failed": "数据包“%s”并未启用!", "commands.datapack.disable.failed.feature": "无法禁用数据包“%s”,因为它属于已启用功能!", "commands.datapack.enable.failed": "数据包“%s”已经启用!", @@ -2662,7 +2685,7 @@ "commands.locate.structure.success": "最近的%s位于%s(%s个方块外)", "commands.message.display.incoming": "%s悄悄地对你说:%s", "commands.message.display.outgoing": "你悄悄地对%s说:%s", - "commands.op.failed": "无变化,该玩家已是管理员", + "commands.op.failed": "无变化,此玩家已是管理员", "commands.op.success": "已将%s设为服务器管理员", "commands.pardon.failed": "无变化,该玩家未被封禁", "commands.pardon.success": "已解封%s", @@ -2862,7 +2885,7 @@ "commands.test.create.success": "已为测试%s创建测试设置", "commands.test.error.no_test_containing_pos": "找不到包含%s, %s, %s的测试实例", "commands.test.error.no_test_instances": "未找到测试实例", - "commands.test.error.non_existant_test": "测试实例%s不存在", + "commands.test.error.non_existant_test": "测试%s不存在", "commands.test.error.structure_not_found": "无法找到测试结构%s", "commands.test.error.test_instance_not_found": "无法找到测试实例方块实体", "commands.test.error.test_instance_not_found.position": "无法在%s, %s, %s处找到测试实例方块实体", @@ -2917,6 +2940,22 @@ "commands.trigger.failed.unprimed": "你尚无法触发这个记分项", "commands.trigger.set.success": "已触发%s(数值已设为%s)", "commands.trigger.simple.success": "已触发%s", + "commands.version.build_time": "build_time = %s", + "commands.version.data": "data = %s", + "commands.version.header": "服务器版本信息:", + "commands.version.id": "id = %s", + "commands.version.name": "name = %s", + "commands.version.pack.data": "pack_data = %s", + "commands.version.pack.resource": "pack_resource = %s", + "commands.version.protocol": "protocol = %s (%s)", + "commands.version.series": "series = %s", + "commands.version.stable.no": "stable = no", + "commands.version.stable.yes": "stable = yes", + "commands.waypoint.list.empty": "在%s内没有路径点", + "commands.waypoint.list.success": "在%2$s内找到%1$s个路径点:%3$s", + "commands.waypoint.modify.color": "路径点颜色现在为%s", + "commands.waypoint.modify.color.reset": "已重置路径点颜色", + "commands.waypoint.modify.style": "已更改路径点样式", "commands.weather.set.clear": "天气已设为晴天", "commands.weather.set.rain": "天气已设为雨天", "commands.weather.set.thunder": "天气已设为雷雨", @@ -3018,7 +3057,7 @@ "createWorld.customize.flat.layer.bottom": "底层 - %s", "createWorld.customize.flat.layer.top": "顶层 - %s", "createWorld.customize.flat.removeLayer": "移除层面", - "createWorld.customize.flat.tile": "此层的材料", + "createWorld.customize.flat.tile": "各层的材料", "createWorld.customize.flat.title": "自定义超平坦世界", "createWorld.customize.presets": "预设", "createWorld.customize.presets.list": "另外,这里是些我们早期制作好的!", @@ -3035,6 +3074,8 @@ "credits_and_attribution.screen.title": "鸣谢与著作权说明", "dataPack.bundle.description": "启用实验性收纳袋物品", "dataPack.bundle.name": "收纳袋", + "dataPack.locator_bar.description": "在多人游戏中显示其他玩家方位", + "dataPack.locator_bar.name": "定位栏", "dataPack.minecart_improvements.description": "改进了矿车的运动", "dataPack.minecart_improvements.name": "矿车改进", "dataPack.redstone_experiments.description": "实验性红石更改", @@ -3049,7 +3090,7 @@ "dataPack.validation.back": "返回", "dataPack.validation.failed": "数据包验证失败!", "dataPack.validation.reset": "重置为默认", - "dataPack.validation.working": "正在验证已选的数据包…", + "dataPack.validation.working": "正在验证选中的数据包…", "dataPack.vanilla.description": "Minecraft的默认数据包", "dataPack.vanilla.name": "默认", "dataPack.winter_drop.description": "冬季小更新的新功能与内容", @@ -3058,8 +3099,8 @@ "datapackFailure.safeMode.failed.description": "这个世界包含无效或损坏的存档数据。", "datapackFailure.safeMode.failed.title": "无法在安全模式下加载世界。", "datapackFailure.title": "当前选中的数据包中出现了错误,导致世界无法加载。\n你可以尝试仅加载原版数据包(“安全模式”)或回到标题屏幕手动修复该问题。", - "death.attack.anvil": "%1$s被坠落的铁砧压扁了", - "death.attack.anvil.player": "%1$s在与%2$s战斗时被坠落的铁砧压扁了", + "death.attack.anvil": "%1$s被下落的铁砧压扁了", + "death.attack.anvil.player": "%1$s在与%2$s战斗时被下落的铁砧压扁了", "death.attack.arrow": "%1$s被%2$s射杀", "death.attack.arrow.item": "%1$s被%2$s用%3$s射杀", "death.attack.badRespawnPoint.link": "刻意的游戏设计", @@ -3082,8 +3123,8 @@ "death.attack.fall.player": "%1$s在试图逃离%2$s时落地过猛", "death.attack.fallingBlock": "%1$s被下落的方块压扁了", "death.attack.fallingBlock.player": "%1$s在与%2$s战斗时被下落的方块压扁了", - "death.attack.fallingStalactite": "%1$s被坠落的钟乳石刺穿了", - "death.attack.fallingStalactite.player": "%1$s在与%2$s战斗时被坠落的钟乳石刺穿了", + "death.attack.fallingStalactite": "%1$s被下落的钟乳石刺穿了", + "death.attack.fallingStalactite.player": "%1$s在与%2$s战斗时被下落的钟乳石刺穿了", "death.attack.fireball": "%1$s被%2$s用火球烧死了", "death.attack.fireball.item": "%1$s被%2$s用%3$s发射的火球烧死了", "death.attack.fireworks": "%1$s随着一声巨响消失了", @@ -3208,6 +3249,8 @@ "debug.show_hitboxes.help": "F3 + B = 显示判定箱", "debug.show_hitboxes.off": "判定箱:隐藏", "debug.show_hitboxes.on": "判定箱:显示", + "debug.version.header": "客户端版本信息:", + "debug.version.help": "F3 + V = 显示客户端版本信息", "demo.day.1": "此试玩版会在5个游戏日后结束,尽力而为吧!", "demo.day.2": "第二天", "demo.day.3": "第三天", @@ -3237,7 +3280,7 @@ "disconnect.loginFailedInfo.insufficientPrivileges": "多人游戏已被禁用,请检查你的Microsoft账户设置。", "disconnect.loginFailedInfo.invalidSession": "无效会话(请尝试重启游戏及启动器)", "disconnect.loginFailedInfo.serversUnavailable": "暂时无法连接到身份验证服务器,请稍后再试。", - "disconnect.loginFailedInfo.userBanned": "你已被禁止进行多人游戏", + "disconnect.loginFailedInfo.userBanned": "你已被禁止进行在线游戏", "disconnect.lost": "连接已丢失", "disconnect.packetError": "网络协议错误", "disconnect.spam": "由于滥发消息而被踢出游戏", @@ -3410,6 +3453,7 @@ "entity.minecraft.glow_squid": "发光鱿鱼", "entity.minecraft.goat": "山羊", "entity.minecraft.guardian": "守卫者", + "entity.minecraft.happy_ghast": "快乐恶魂", "entity.minecraft.hoglin": "疣猪兽", "entity.minecraft.hopper_minecart": "漏斗矿车", "entity.minecraft.horse": "马", @@ -3588,6 +3632,8 @@ "gameMode.hardcore": "极限模式", "gameMode.spectator": "旁观模式", "gameMode.survival": "生存模式", + "gamerule.allowFireTicksAwayFromPlayer": "允许火在远离玩家处蔓延", + "gamerule.allowFireTicksAwayFromPlayer.description": "控制火和熔岩是否能够在距离任何玩家超过8个区块处蔓延", "gamerule.announceAdvancements": "进度通知", "gamerule.blockExplosionDropDecay": "在方块交互爆炸中,一些方块不会掉落战利品", "gamerule.blockExplosionDropDecay.description": "在与方块交互引起的爆炸中,部分被破坏方块的掉落物会被炸毁。", @@ -3639,6 +3685,8 @@ "gamerule.keepInventory": "死亡后保留物品栏", "gamerule.lavaSourceConversion": "允许流动熔岩转化为熔岩源", "gamerule.lavaSourceConversion.description": "流动熔岩在两面与熔岩源相邻时转化为熔岩源。", + "gamerule.locatorBar": "启用玩家定位栏", + "gamerule.locatorBar.description": "启用后,屏幕上会显示指示玩家方位的定位栏。", "gamerule.logAdminCommands": "通告管理员命令", "gamerule.maxCommandChainLength": "命令连锁执行数量限制", "gamerule.maxCommandChainLength.description": "应用于命令方块链和函数。", @@ -3671,6 +3719,7 @@ "gamerule.spawnRadius": "重生点半径", "gamerule.spawnRadius.description": "控制适合玩家生成的出生点周围区域大小。", "gamerule.spectatorsGenerateChunks": "允许旁观者生成地形", + "gamerule.tntExplodes": "允许TNT被点燃并爆炸", "gamerule.tntExplosionDropDecay": "在TNT爆炸中,一些方块不会掉落战利品", "gamerule.tntExplosionDropDecay.description": "在TNT引起的爆炸中,部分被破坏方块的掉落物会被炸毁。", "gamerule.universalAnger": "无差别愤怒", @@ -3759,11 +3808,11 @@ "gui.all": "全部", "gui.back": "返回", "gui.banned.description": "%s\n\n%s\n\n点击以下链接了解更多:%s", - "gui.banned.description.permanent": "你的账户已被永久封禁,无法进行多人游戏或加入Realms。", + "gui.banned.description.permanent": "你的账户已被永久封禁,无法进行在线游戏或加入Realms。", "gui.banned.description.reason": "我们最近收到举报称你的账户存在不良行为。我们的监督员已审核你的案件并将其认定为%s,这违反了Minecraft社区准则。", "gui.banned.description.reason_id": "代码:%s", "gui.banned.description.reason_id_message": "代码:%s - %s", - "gui.banned.description.temporary": "%s期限结束前,你无法进行多人游戏或加入Realms。", + "gui.banned.description.temporary": "%s期限结束前,你无法进行在线游戏或加入Realms。", "gui.banned.description.temporary.duration": "你的账户已被暂时封禁并将于%s后解封。", "gui.banned.description.unknownreason": "我们最近收到举报称你的账户存在不良行为。我们的监督员已审核你的案件并认定你违反了Minecraft社区准则。", "gui.banned.name.description": "你当前的名称(“%s”)违反了我们的社区准则。你可以进行单人游戏,但需要更改名称才能进行在线游戏。\n\n通过以下链接了解更多或提交案件审查:%s", @@ -3805,7 +3854,7 @@ "gui.chatReport.report_sent_msg": "我们已经成功收到你的举报。非常感谢!\n\n我们的团队会尽快进行审核。", "gui.chatReport.select_chat": "选择要举报的聊天消息", "gui.chatReport.select_reason": "选择举报类型", - "gui.chatReport.selected_chat": "已选择%s条要举报的聊天消息", + "gui.chatReport.selected_chat": "已选中%s条要举报的聊天消息", "gui.chatReport.send": "发送举报", "gui.chatReport.send.comments_too_long": "请缩短留言", "gui.chatReport.send.no_reason": "请选择举报类型", @@ -3825,6 +3874,7 @@ "gui.done": "完成", "gui.down": "向下", "gui.entity_tooltip.type": "类型:%s", + "gui.experience.level": "%s", "gui.fileDropFailure.detail": "拒绝了%s个文件", "gui.fileDropFailure.title": "添加文件失败", "gui.hours": "%s小时", @@ -3937,6 +3987,7 @@ "item.minecraft.birch_chest_boat": "白桦木运输船", "item.minecraft.black_bundle": "黑色收纳袋", "item.minecraft.black_dye": "黑色染料", + "item.minecraft.black_harness": "黑色挽具", "item.minecraft.blade_pottery_shard": "利刃纹样陶片", "item.minecraft.blade_pottery_sherd": "利刃纹样陶片", "item.minecraft.blaze_powder": "烈焰粉", @@ -3944,6 +3995,8 @@ "item.minecraft.blaze_spawn_egg": "烈焰人刷怪蛋", "item.minecraft.blue_bundle": "蓝色收纳袋", "item.minecraft.blue_dye": "蓝色染料", + "item.minecraft.blue_egg": "蓝色鸡蛋", + "item.minecraft.blue_harness": "蓝色挽具", "item.minecraft.bogged_spawn_egg": "沼骸刷怪蛋", "item.minecraft.bolt_armor_trim_smithing_template": "锻造模板", "item.minecraft.bolt_armor_trim_smithing_template.new": "镶铆盔甲纹饰", @@ -3962,6 +4015,8 @@ "item.minecraft.brick": "红砖", "item.minecraft.brown_bundle": "棕色收纳袋", "item.minecraft.brown_dye": "棕色染料", + "item.minecraft.brown_egg": "棕色鸡蛋", + "item.minecraft.brown_harness": "棕色挽具", "item.minecraft.brush": "刷子", "item.minecraft.bucket": "铁桶", "item.minecraft.bundle": "收纳袋", @@ -4016,8 +4071,11 @@ "item.minecraft.creeper_spawn_egg": "苦力怕刷怪蛋", "item.minecraft.crossbow": "弩", "item.minecraft.crossbow.projectile": "弹射物:", + "item.minecraft.crossbow.projectile.multiple": "弹射物:%s × %s", + "item.minecraft.crossbow.projectile.single": "弹射物:%s", "item.minecraft.cyan_bundle": "青色收纳袋", "item.minecraft.cyan_dye": "青色染料", + "item.minecraft.cyan_harness": "青色挽具", "item.minecraft.danger_pottery_shard": "危机纹样陶片", "item.minecraft.danger_pottery_sherd": "危机纹样陶片", "item.minecraft.dark_oak_boat": "深色橡木船", @@ -4072,6 +4130,8 @@ "item.minecraft.fire_charge": "火焰弹", "item.minecraft.firework_rocket": "烟花火箭", "item.minecraft.firework_rocket.flight": "飞行时间:", + "item.minecraft.firework_rocket.multiple_stars": "%s × %s", + "item.minecraft.firework_rocket.single_star": "%s", "item.minecraft.firework_star": "烟火之星", "item.minecraft.firework_star.black": "黑色", "item.minecraft.firework_star.blue": "蓝色", @@ -4147,14 +4207,18 @@ "item.minecraft.golden_sword": "金剑", "item.minecraft.gray_bundle": "灰色收纳袋", "item.minecraft.gray_dye": "灰色染料", + "item.minecraft.gray_harness": "灰色挽具", "item.minecraft.green_bundle": "绿色收纳袋", "item.minecraft.green_dye": "绿色染料", + "item.minecraft.green_harness": "绿色挽具", "item.minecraft.guardian_spawn_egg": "守卫者刷怪蛋", "item.minecraft.gunpowder": "火药", "item.minecraft.guster_banner_pattern": "旗帜图案", "item.minecraft.guster_banner_pattern.desc": "旋风", "item.minecraft.guster_banner_pattern.new": "旋风旗帜图案", "item.minecraft.guster_pottery_sherd": "旋风纹样陶片", + "item.minecraft.happy_ghast_spawn_egg": "快乐恶魂刷怪蛋", + "item.minecraft.harness": "挽具", "item.minecraft.heart_of_the_sea": "海洋之心", "item.minecraft.heart_pottery_shard": "爱心纹样陶片", "item.minecraft.heart_pottery_sherd": "爱心纹样陶片", @@ -4199,10 +4263,13 @@ "item.minecraft.leather_leggings": "皮革裤子", "item.minecraft.light_blue_bundle": "淡蓝色收纳袋", "item.minecraft.light_blue_dye": "淡蓝色染料", + "item.minecraft.light_blue_harness": "淡蓝色挽具", "item.minecraft.light_gray_bundle": "淡灰色收纳袋", "item.minecraft.light_gray_dye": "淡灰色染料", + "item.minecraft.light_gray_harness": "淡灰色挽具", "item.minecraft.lime_bundle": "黄绿色收纳袋", "item.minecraft.lime_dye": "黄绿色染料", + "item.minecraft.lime_harness": "黄绿色挽具", "item.minecraft.lingering_potion": "滞留药水", "item.minecraft.lingering_potion.effect.awkward": "滞留型粗制的药水", "item.minecraft.lingering_potion.effect.empty": "不可合成的滞留型药水", @@ -4235,6 +4302,7 @@ "item.minecraft.mace": "重锤", "item.minecraft.magenta_bundle": "品红色收纳袋", "item.minecraft.magenta_dye": "品红色染料", + "item.minecraft.magenta_harness": "品红色挽具", "item.minecraft.magma_cream": "岩浆膏", "item.minecraft.magma_cube_spawn_egg": "岩浆怪刷怪蛋", "item.minecraft.mangrove_boat": "红树木船", @@ -4318,6 +4386,7 @@ "item.minecraft.ominous_trial_key": "不祥试炼钥匙", "item.minecraft.orange_bundle": "橙色收纳袋", "item.minecraft.orange_dye": "橙色染料", + "item.minecraft.orange_harness": "橙色挽具", "item.minecraft.painting": "画", "item.minecraft.pale_oak_boat": "苍白橡木船", "item.minecraft.pale_oak_chest_boat": "苍白橡木运输船", @@ -4335,6 +4404,7 @@ "item.minecraft.pillager_spawn_egg": "掠夺者刷怪蛋", "item.minecraft.pink_bundle": "粉红色收纳袋", "item.minecraft.pink_dye": "粉红色染料", + "item.minecraft.pink_harness": "粉红色挽具", "item.minecraft.pitcher_plant": "瓶子草", "item.minecraft.pitcher_pod": "瓶子草荚果", "item.minecraft.plenty_pottery_shard": "富饶纹样陶片", @@ -4387,6 +4457,7 @@ "item.minecraft.pumpkin_seeds": "南瓜种子", "item.minecraft.purple_bundle": "紫色收纳袋", "item.minecraft.purple_dye": "紫色染料", + "item.minecraft.purple_harness": "紫色挽具", "item.minecraft.quartz": "下界石英", "item.minecraft.rabbit": "生兔肉", "item.minecraft.rabbit_foot": "兔子脚", @@ -4402,6 +4473,7 @@ "item.minecraft.recovery_compass": "追溯指针", "item.minecraft.red_bundle": "红色收纳袋", "item.minecraft.red_dye": "红色染料", + "item.minecraft.red_harness": "红色挽具", "item.minecraft.redstone": "红石粉", "item.minecraft.resin_brick": "树脂砖", "item.minecraft.resin_clump": "树脂团", @@ -4583,6 +4655,7 @@ "item.minecraft.wheat_seeds": "小麦种子", "item.minecraft.white_bundle": "白色收纳袋", "item.minecraft.white_dye": "白色染料", + "item.minecraft.white_harness": "白色挽具", "item.minecraft.wild_armor_trim_smithing_template": "锻造模板", "item.minecraft.wild_armor_trim_smithing_template.new": "荒野盔甲纹饰", "item.minecraft.wind_charge": "风弹", @@ -4600,6 +4673,7 @@ "item.minecraft.written_book": "成书", "item.minecraft.yellow_bundle": "黄色收纳袋", "item.minecraft.yellow_dye": "黄色染料", + "item.minecraft.yellow_harness": "黄色挽具", "item.minecraft.zoglin_spawn_egg": "僵尸疣猪兽刷怪蛋", "item.minecraft.zombie_horse_spawn_egg": "僵尸马刷怪蛋", "item.minecraft.zombie_spawn_egg": "僵尸刷怪蛋", @@ -4615,6 +4689,7 @@ "item.modifiers.legs": "穿在腿上时:", "item.modifiers.mainhand": "在主手时:", "item.modifiers.offhand": "在副手时:", + "item.modifiers.saddle": "装备鞍时:", "item.nbt_tags": "NBT:%s个标签", "item.op_block_warning.line1": "警告:", "item.op_block_warning.line2": "使用该物品可能会导致命令执行", @@ -4859,7 +4934,7 @@ "mco.brokenworld.message.line1": "请重置或选择另一个世界。", "mco.brokenworld.message.line2": "你可以选择将世界下载至单人模式中。", "mco.brokenworld.minigame.title": "此小游戏已不受支持", - "mco.brokenworld.nonowner.error": "请等待Realms所有者重置世界", + "mco.brokenworld.nonowner.error": "请等待Realm所有者重置世界", "mco.brokenworld.nonowner.title": "世界已过期", "mco.brokenworld.play": "开始游戏", "mco.brokenworld.reset": "重置", @@ -4885,22 +4960,26 @@ "mco.configure.world.activityfeed.disabled": "玩家推送暂不可用", "mco.configure.world.backup": "世界备份", "mco.configure.world.buttons.activity": "玩家动态", - "mco.configure.world.buttons.close": "关闭Realm", + "mco.configure.world.buttons.close": "暂时关闭Realm", "mco.configure.world.buttons.delete": "删除", "mco.configure.world.buttons.done": "完成", "mco.configure.world.buttons.edit": "设置", "mco.configure.world.buttons.invite": "邀请玩家", "mco.configure.world.buttons.moreoptions": "更多选项", - "mco.configure.world.buttons.open": "开启Realm", + "mco.configure.world.buttons.newworld": "新的世界", + "mco.configure.world.buttons.open": "重新打开Realm", "mco.configure.world.buttons.options": "世界选项", "mco.configure.world.buttons.players": "玩家", + "mco.configure.world.buttons.region_preference": "选择地区…", "mco.configure.world.buttons.resetworld": "重置世界", + "mco.configure.world.buttons.save": "保存", "mco.configure.world.buttons.settings": "设置", "mco.configure.world.buttons.subscription": "订阅", "mco.configure.world.buttons.switchminigame": "切换小游戏", - "mco.configure.world.close.question.line1": "你的Realm将变为不可用。", + "mco.configure.world.close.question.line1": "你可以暂时关闭Realm,从而防止有人在你调整设置时进入游戏。准备就绪后Realm可以重新打开。\n\n此操作不会取消你的Realms订阅。", "mco.configure.world.close.question.line2": "你确定要继续吗?", - "mco.configure.world.closing": "关闭Realm中…", + "mco.configure.world.close.question.title": "要在不中断的情况下更改吗?", + "mco.configure.world.closing": "暂时关闭Realm中…", "mco.configure.world.commandBlocks": "命令方块", "mco.configure.world.delete.button": "删除Realm", "mco.configure.world.delete.question.line1": "你的Realm将被永久删除", @@ -4918,7 +4997,7 @@ "mco.configure.world.invites.normal.tooltip": "普通玩家", "mco.configure.world.invites.ops.tooltip": "管理员", "mco.configure.world.invites.remove.tooltip": "移除", - "mco.configure.world.leave.question.line1": "如果你离开这个Realm,你只有被再次邀请才能看见它。", + "mco.configure.world.leave.question.line1": "如果你离开这个Realm,你只有被再次邀请才能看见它", "mco.configure.world.leave.question.line2": "你确定要继续吗?", "mco.configure.world.location": "位置", "mco.configure.world.minigame": "当前:%s", @@ -4928,6 +5007,8 @@ "mco.configure.world.players.inviting": "邀请玩家中…", "mco.configure.world.players.title": "玩家", "mco.configure.world.pvp": "玩家对战", + "mco.configure.world.region_preference": "地区偏好", + "mco.configure.world.region_preference.title": "地区选择", "mco.configure.world.reset.question.line1": "你的Realm将被重新生成,而当前的Realm将会消失", "mco.configure.world.reset.question.line2": "你确定要继续吗?", "mco.configure.world.resourcepack.question": "这个Realm需要一个自定义的资源包\n\n你想要自动下载并安装它吗?", @@ -4966,6 +5047,7 @@ "mco.configure.world.subscription.remaining.months": "%1$s个月", "mco.configure.world.subscription.remaining.months.days": "%1$s个月%2$s天", "mco.configure.world.subscription.start": "开始日期", + "mco.configure.world.subscription.tab": "订阅", "mco.configure.world.subscription.timeleft": "剩余时间", "mco.configure.world.subscription.title": "订阅信息", "mco.configure.world.subscription.unknown": "未知", @@ -5016,6 +5098,7 @@ "mco.errorMessage.initialize.failed": "初始化Realm失败", "mco.errorMessage.noDetails": "未提供错误详情", "mco.errorMessage.realmsService": "出现错误(%s):", + "mco.errorMessage.realmsService.configurationError": "编辑意外的非活跃Realms槽位", "mco.errorMessage.realmsService.connectivity": "无法连接至Realm:%s", "mco.errorMessage.realmsService.realmsError": "Realms(%s):", "mco.errorMessage.realmsService.unknownCompatibility": "无法检查兼容版本,响应为:%s", @@ -5062,10 +5145,10 @@ "mco.reset.world.template": "世界模板", "mco.reset.world.title": "重置世界", "mco.reset.world.upload": "上传世界", - "mco.reset.world.warning": "这将替换掉你目前的Realm世界!", + "mco.reset.world.warning": "这将替换掉你目前的Realm世界", "mco.selectServer.buy": "购买Realm服务器!", "mco.selectServer.close": "关闭", - "mco.selectServer.closed": "已关闭的Realm", + "mco.selectServer.closed": "已失效的Realm", "mco.selectServer.closeserver": "关闭Realm", "mco.selectServer.configure": "配置Realm", "mco.selectServer.configureRealm": "配置Realm", @@ -5136,7 +5219,7 @@ "mco.trial.message.line2": "点击此处来获得更多消息!", "mco.upload.button.name": "上传", "mco.upload.cancelled": "上传已取消", - "mco.upload.close.failure": "无法关闭服务器,请稍后再试", + "mco.upload.close.failure": "无法关闭你的Realm,请稍后再试", "mco.upload.done": "上传已完成", "mco.upload.entry.cheats": "%1$s, %2$s", "mco.upload.entry.commands": "%1$s, %2$s", @@ -5196,6 +5279,7 @@ "mount.onboard": "按下%1$s来脱离", "multiplayer.applyingPack": "正在应用资源包", "multiplayer.disconnect.authservers_down": "身份验证服务器目前处于宕机状态。请稍后再试,抱歉!", + "multiplayer.disconnect.bad_chat_index": "检测到来自服务器的聊天消息部分缺失或已被重新排序", "multiplayer.disconnect.banned": "你已被此服务器封禁", "multiplayer.disconnect.banned.expiration": "\n你的封禁将于%s解除", "multiplayer.disconnect.banned.reason": "你已被此服务器封禁。\n原因:%s", @@ -5243,7 +5327,7 @@ "multiplayer.player.list.narration": "在线玩家:%s", "multiplayer.requiredTexturePrompt.disconnect": "服务器需要自定义资源包", "multiplayer.requiredTexturePrompt.line1": "这个服务器需要使用自定义的资源包。", - "multiplayer.requiredTexturePrompt.line2": "拒绝使用该自定义资源包将会断开你与该服务器间的连接。", + "multiplayer.requiredTexturePrompt.line2": "拒绝使用该自定义资源包将会断开你与该服务器的连接。", "multiplayer.socialInteractions.not_available": "社交屏幕仅在多人游戏世界中可用", "multiplayer.status.and_more": "…及其他%s名玩家…", "multiplayer.status.cancelled": "已取消", @@ -5415,10 +5499,10 @@ "options.difficulty.easy": "简单", "options.difficulty.easy.info": "敌对生物会生成,但伤害较低。生命值在饥饿值耗尽后最终会降至5颗心。", "options.difficulty.hard": "困难", - "options.difficulty.hard.info": "敌对生物会生成,伤害较高。饥饿值耗尽后最终会饿死。", + "options.difficulty.hard.info": "敌对生物会生成,且伤害较高。饥饿值耗尽后最终会饿死。", "options.difficulty.hardcore": "极限", "options.difficulty.normal": "普通", - "options.difficulty.normal.info": "敌对生物会生成,伤害适中。生命值在饥饿值耗尽后最终会降至半颗心。", + "options.difficulty.normal.info": "敌对生物会生成,且伤害适中。生命值在饥饿值耗尽后最终会降至半颗心。", "options.difficulty.online": "服务器难度", "options.difficulty.peaceful": "和平", "options.difficulty.peaceful.info": "不会生成绝大多数敌对生物。饥饿值不会消耗,且生命值会自然恢复。", @@ -5450,7 +5534,7 @@ "options.gamma.min": "昏暗", "options.generic_value": "%s:%s", "options.glintSpeed": "附魔光效闪烁速度", - "options.glintSpeed.tooltip": "控制附魔物品的光效闪动速度。", + "options.glintSpeed.tooltip": "控制附魔物品光效的闪动速度。", "options.glintStrength": "附魔光效闪烁强度", "options.glintStrength.tooltip": "控制附魔物品光效的透明程度。", "options.graphics": "图像品质", @@ -5542,6 +5626,7 @@ "options.realmsNotifications.tooltip": "在标题屏幕上获取Realms新闻和邀请,并在Realms按钮上显示相应图标。", "options.reducedDebugInfo": "简化调试信息", "options.renderClouds": "云", + "options.renderCloudsDistance": "云层距离", "options.renderDistance": "渲染距离", "options.resourcepack": "资源包…", "options.rotateWithMinecart": "同步矿车转动", @@ -5727,6 +5812,31 @@ "quickplay.error.realm_connect": "无法连接至Realm", "quickplay.error.realm_permission": "权限不足,无法连接至此Realm", "quickplay.error.title": "无法快速进入游戏", + "realms.configuration.region.australia_east": "澳大利亚新南威尔士州", + "realms.configuration.region.australia_southeast": "澳大利亚维多利亚州", + "realms.configuration.region.brazil_south": "巴西", + "realms.configuration.region.central_india": "印度", + "realms.configuration.region.central_us": "美国艾奥瓦州", + "realms.configuration.region.east_asia": "香港", + "realms.configuration.region.east_us": "美国弗吉尼亚州", + "realms.configuration.region.east_us_2": "美国北卡罗来纳州", + "realms.configuration.region.france_central": "法国", + "realms.configuration.region.japan_east": "日本东部", + "realms.configuration.region.japan_west": "日本西部", + "realms.configuration.region.korea_central": "韩国", + "realms.configuration.region.north_central_us": "美国伊利诺伊州", + "realms.configuration.region.north_europe": "爱尔兰", + "realms.configuration.region.south_central_us": "美国得克萨斯州", + "realms.configuration.region.southeast_asia": "新加坡", + "realms.configuration.region.sweden_central": "瑞典", + "realms.configuration.region.uae_north": "阿联酋", + "realms.configuration.region.uk_south": "英国南部", + "realms.configuration.region.west_central_us": "美国犹他州", + "realms.configuration.region.west_europe": "荷兰", + "realms.configuration.region.west_us": "美国加利福尼亚州", + "realms.configuration.region.west_us_2": "美国华盛顿州", + "realms.configuration.region_preference.automatic_owner": "自动(取决于Realm所有者的延迟)", + "realms.configuration.region_preference.automatic_player": "自动(取决于首个加入会话的玩家)", "realms.missing.snapshot.error.text": "快照当前不支持Realms", "recipe.notFound": "未知的配方:%s", "recipe.toast.description": "请检查你的配方书", @@ -5900,6 +6010,27 @@ "sleep.skipping_night": "今夜将在睡梦中度过", "slot.only_single_allowed": "只允许有单个槽位,实际为“%s”", "slot.unknown": "未知的槽位“%s”", + "snbt.parser.empty_key": "键不能为空", + "snbt.parser.expected_binary_numeral": "应为二进制数", + "snbt.parser.expected_decimal_numeral": "应为十进制数", + "snbt.parser.expected_float_type": "应为浮点数", + "snbt.parser.expected_hex_escape": "字符字面量长度应为%s", + "snbt.parser.expected_hex_numeral": "应为十六进制数", + "snbt.parser.expected_integer_type": "应为整数", + "snbt.parser.expected_non_negative_number": "应为非负数", + "snbt.parser.expected_number_or_boolean": "应为数字或布尔型", + "snbt.parser.expected_string_uuid": "应为表示有效UUID的字符串", + "snbt.parser.expected_unquoted_string": "应为有效的无引号字符串", + "snbt.parser.infinity_not_allowed": "不允许使用非有限数的数值", + "snbt.parser.invalid_array_element_type": "无效的数组元素类型", + "snbt.parser.invalid_character_name": "无效的Unicode字符名称", + "snbt.parser.invalid_codepoint": "无效的Unicode字符码位:%s", + "snbt.parser.invalid_string_contents": "无效的字符串内容", + "snbt.parser.invalid_unquoted_start": "无引号字符串不能以数字0-9、+或-开头", + "snbt.parser.leading_zero_not_allowed": "十进制数不能以0开头", + "snbt.parser.no_such_operation": "不存在的操作:%s", + "snbt.parser.number_parse_failure": "解析数字失败:%s", + "snbt.parser.undescore_not_allowed": "数字的开头和结尾不允许使用下划线字符", "soundCategory.ambient": "环境", "soundCategory.block": "方块", "soundCategory.hostile": "敌对生物", @@ -5944,6 +6075,7 @@ "stat.minecraft.fill_cauldron": "炼药锅装水次数", "stat.minecraft.fish_caught": "捕鱼数", "stat.minecraft.fly_one_cm": "飞行距离", + "stat.minecraft.happy_ghast_one_cm": "骑乘快乐恶魂移动距离", "stat.minecraft.horse_one_cm": "骑马移动距离", "stat.minecraft.inspect_dispenser": "搜查发射器次数", "stat.minecraft.inspect_dropper": "搜查投掷器次数", @@ -6104,12 +6236,18 @@ "subtitles.block.creaking_heart.hurt": "嘎枝之心:咕哝", "subtitles.block.creaking_heart.idle": "怪异的噪声", "subtitles.block.creaking_heart.spawn": "嘎枝之心:苏醒", + "subtitles.block.deadbush.idle": "干枯声", "subtitles.block.decorated_pot.insert": "饰纹陶罐:装入", "subtitles.block.decorated_pot.insert_fail": "饰纹陶罐:晃动", "subtitles.block.decorated_pot.shatter": "饰纹陶罐:碎裂", "subtitles.block.dispenser.dispense": "物品:被射出", "subtitles.block.dispenser.fail": "发射器:发射失败", "subtitles.block.door.toggle": "门:嘎吱作响", + "subtitles.block.dried_ghast.ambient": "干燥声", + "subtitles.block.dried_ghast.ambient_water": "失水恶魂:补水", + "subtitles.block.dried_ghast.place_in_water": "失水恶魂:浸泡", + "subtitles.block.dried_ghast.transition": "失水恶魂:恢复", + "subtitles.block.dry_grass.ambient": "风声", "subtitles.block.enchantment_table.use": "附魔台:使用", "subtitles.block.end_portal.spawn": "末地传送门:开启", "subtitles.block.end_portal_frame.fill": "末影之眼:嵌入", @@ -6119,6 +6257,7 @@ "subtitles.block.fence_gate.toggle": "栅栏门:嘎吱作响", "subtitles.block.fire.ambient": "火:噼啪作响", "subtitles.block.fire.extinguish": "火:熄灭", + "subtitles.block.firefly_bush.idle": "萤火虫:嗡嗡", "subtitles.block.frogspawn.hatch": "蝌蚪:孵化", "subtitles.block.furnace.fire_crackle": "熔炉:噼啪作响", "subtitles.block.generic.break": "方块:被破坏", @@ -6153,6 +6292,8 @@ "subtitles.block.respawn_anchor.charge": "重生锚:充能", "subtitles.block.respawn_anchor.deplete": "重生锚:耗能", "subtitles.block.respawn_anchor.set_spawn": "重生锚:设置出生点", + "subtitles.block.sand.idle": "沙沙声", + "subtitles.block.sand.wind": "风声", "subtitles.block.sculk.charge": "幽匿块:冒泡", "subtitles.block.sculk.spread": "幽匿块:蔓延", "subtitles.block.sculk_catalyst.bloom": "幽匿催发体:催发", @@ -6169,6 +6310,8 @@ "subtitles.block.sniffer_egg.plop": "嗅探兽:下蛋", "subtitles.block.sponge.absorb": "海绵:吸水", "subtitles.block.sweet_berry_bush.pick_berries": "浆果:弹出", + "subtitles.block.trapdoor.close": "活板门:关闭", + "subtitles.block.trapdoor.open": "活板门:打开", "subtitles.block.trapdoor.toggle": "活板门:嘎吱作响", "subtitles.block.trial_spawner.about_to_spawn_item": "不祥之物:准备", "subtitles.block.trial_spawner.ambient": "试炼刷怪笼:噼啪作响", @@ -6369,7 +6512,7 @@ "subtitles.entity.experience_orb.pickup": "获得经验", "subtitles.entity.firework_rocket.blast": "烟花:爆裂", "subtitles.entity.firework_rocket.launch": "烟花:发射", - "subtitles.entity.firework_rocket.twinkle": "烟火:闪烁", + "subtitles.entity.firework_rocket.twinkle": "烟花:闪烁", "subtitles.entity.fish.swim": "溅起水花", "subtitles.entity.fishing_bobber.retrieve": "浮漂:收回", "subtitles.entity.fishing_bobber.splash": "浮漂:溅起水花", @@ -6407,6 +6550,10 @@ "subtitles.entity.ghast.death": "恶魂:死亡", "subtitles.entity.ghast.hurt": "恶魂:受伤", "subtitles.entity.ghast.shoot": "恶魂:射击", + "subtitles.entity.ghastling.ambient": "小恶魂:咕咕", + "subtitles.entity.ghastling.death": "小恶魂:死亡", + "subtitles.entity.ghastling.hurt": "小恶魂:受伤", + "subtitles.entity.ghastling.spawn": "小恶魂:出现", "subtitles.entity.glow_item_frame.add_item": "荧光物品展示框:填充", "subtitles.entity.glow_item_frame.break": "荧光物品展示框:被破坏", "subtitles.entity.glow_item_frame.place": "荧光物品展示框:被放置", @@ -6433,6 +6580,13 @@ "subtitles.entity.guardian.death": "守卫者:死亡", "subtitles.entity.guardian.flop": "守卫者:扑腾", "subtitles.entity.guardian.hurt": "守卫者:受伤", + "subtitles.entity.happy_ghast.ambient": "快乐恶魂:哼唱", + "subtitles.entity.happy_ghast.death": "快乐恶魂:死亡", + "subtitles.entity.happy_ghast.equip": "挽具:装备", + "subtitles.entity.happy_ghast.harness_goggles_down": "快乐恶魂:就绪", + "subtitles.entity.happy_ghast.harness_goggles_up": "快乐恶魂:停下", + "subtitles.entity.happy_ghast.hurt": "快乐恶魂:受伤", + "subtitles.entity.happy_ghast.unequip": "挽具:卸下", "subtitles.entity.hoglin.ambient": "疣猪兽:咆哮", "subtitles.entity.hoglin.angry": "疣猪兽:怒吼", "subtitles.entity.hoglin.attack": "疣猪兽:攻击", @@ -6787,10 +6941,13 @@ "subtitles.entity.wither_skeleton.death": "凋灵骷髅:死亡", "subtitles.entity.wither_skeleton.hurt": "凋灵骷髅:受伤", "subtitles.entity.wolf.ambient": "狼:喘息", + "subtitles.entity.wolf.bark": "狼:吠叫", "subtitles.entity.wolf.death": "狼:死亡", "subtitles.entity.wolf.growl": "狼:嚎叫", "subtitles.entity.wolf.hurt": "狼:受伤", + "subtitles.entity.wolf.pant": "狼:喘息", "subtitles.entity.wolf.shake": "狼:摇动", + "subtitles.entity.wolf.whine": "狼:呜咽", "subtitles.entity.zoglin.ambient": "僵尸疣猪兽:咆哮", "subtitles.entity.zoglin.angry": "僵尸疣猪兽:怒吼", "subtitles.entity.zoglin.attack": "僵尸疣猪兽:攻击", @@ -6875,7 +7032,8 @@ "subtitles.item.mace.smash_ground": "重锤:猛击", "subtitles.item.nether_wart.plant": "作物:种植", "subtitles.item.ominous_bottle.dispose": "玻璃瓶:碎裂", - "subtitles.item.shears.shear": "剪刀:剪断", + "subtitles.item.shears.shear": "剪刀:咔嚓", + "subtitles.item.shears.snip": "剪刀:剪断", "subtitles.item.shield.block": "盾牌:格挡", "subtitles.item.shovel.flatten": "锹:压地", "subtitles.item.spyglass.stop_using": "望远镜:缩小", @@ -6991,7 +7149,7 @@ "test.error.fail": "满足失败条件", "test.error.invalid_block_type": "发现非预期的方块类型:%s", "test.error.missing_block_entity": "缺少方块实体", - "test.error.position": "%1$s,位于%2$s, %3$s, %4$s(相对位置:%5$s, %6$s, %7$s),%8$s刻", + "test.error.position": "%s,位于%s, %s, %s(相对位置:%s, %s, %s),%s刻", "test.error.sequence.condition_already_triggered": "条件已在%s刻时触发", "test.error.sequence.condition_not_triggered": "条件未触发", "test.error.sequence.invalid_tick": "成功于无效的刻:应为%s", @@ -6999,11 +7157,16 @@ "test.error.set_biome": "设置测试生物群系失败", "test.error.spawn_failure": "创建实体%s失败", "test.error.state_not_equal": "状态错误。应为%s,实际为%s", + "test.error.structure.failure": "为%s放置测试结构失败", "test.error.tick": "%s,时间为%s刻", + "test.error.ticking_without_structure": "尚未放置结构时执行了测试", + "test.error.timeout.no_result": "未在%s刻内成功或失败", + "test.error.timeout.no_sequences_finished": "在%s刻内没有序列完成", "test.error.too_many_entities": "%2$s, %3$s, %4$s周围应仅存在一个%1$s,实际为%5$s个", "test.error.unexpected_block": "方块不应为%s", "test.error.unexpected_entity": "%s不应存在", "test.error.unexpected_item": "物品不应为类型%s", + "test.error.unknown": "未知的内部错误:%s", "test.error.value_not_equal": "属性%s应为%s,实际为%s", "test.error.wrong_block_entity": "错误的方块实体类型:%s", "test_block.error.missing": "测试结构缺少%s方块", @@ -7106,4 +7269,4 @@ "tutorial.socialInteractions.description": "按%s打开", "tutorial.socialInteractions.title": "社交", "upgrade.minecraft.netherite_upgrade": "下界合金升级" -} +} \ No newline at end of file diff --git a/patches/removed/server/0022-Early-return-optimization-for-target-finding.patch b/patches/removed/server/0022-Early-return-optimization-for-target-finding.patch deleted file mode 100644 index 2281acf7..00000000 --- a/patches/removed/server/0022-Early-return-optimization-for-target-finding.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Sun, 14 Aug 2022 17:16:19 +0800 -Subject: [PATCH] Early return optimization for target finding - -This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) - -diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -index aecb0ad814586bfc5e56755ee14379a69388b38c..c618d7c87a0b2e2ee55cbe64cae80178fd8bd651 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -@@ -76,9 +76,17 @@ public class TargetingConditions { - } - - if (this.range > 0.0) { -+ // Leaves start - check range before getting visibility -+ double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); -+ if (org.leavesmc.leaves.LeavesConfig.entityTargetFindingOptimization) { -+ double followRangeRaw = this.useFollowRange ? this.getFollowRange(baseEntity) : this.range; -+ if (f > followRangeRaw * followRangeRaw) { // the actual follow range will always be this value or smaller, so if the distance is larger then it never will return true after getting invis -+ return false; -+ } -+ } -+ // Leaves end - check range before getting visibility - double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0; - double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0); // Paper - Fix MC-145656 -- double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); - if (f > e * e) { - return false; - } diff --git a/patches/removed/server/0024-Move-ThreadUnsafeRandom-Initialization.patch b/patches/removed/server/0024-Move-ThreadUnsafeRandom-Initialization.patch deleted file mode 100644 index 7b5df3f3..00000000 --- a/patches/removed/server/0024-Move-ThreadUnsafeRandom-Initialization.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Sun, 14 Aug 2022 10:54:33 +0800 -Subject: [PATCH] Move ThreadUnsafeRandom Initialization - -This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 81ebb247a8d5c5cd77a3d4ce729146c9fbfa3668..43977320ffefa9bff45e63194005375d9a2fe8b0 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -804,7 +804,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - } - // Paper start - optimise random block ticking - private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos(); -- private final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(this.random.nextLong()); -+ // private final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(this.random.nextLong()); // Leaves - moved to super - // Paper end - - public void tickChunk(LevelChunk chunk, int randomTickSpeed) { -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 41acb79ec31f6f53589d698d1d4547485f0adc71..42206013ca0790f1366319669fe433640a74798c 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -203,11 +203,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - } - // Paper end - -- public abstract ResourceKey getTypeKey(); -+ protected final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(java.util.concurrent.ThreadLocalRandom.current().nextLong()); // Leaves - move thread unsafe random initialization - -+ public abstract ResourceKey getTypeKey(); - // Paper start - rewrite chunk system - private ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup entityLookup; - -+ - @Override - public final ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup moonrise$getEntityLookup() { - return this.entityLookup; -@@ -255,14 +257,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - public ChunkAccess moonrise$getSpecificChunkIfLoaded(final int chunkX, final int chunkZ, final ChunkStatus leastStatus) { - return this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, false); - } -- - @Override - public void moonrise$midTickTasks() { - // no-op on ClientLevel - } - // Paper end - rewrite chunk system - -- protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config & Anti-Xray -+ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config; Async-Anti-Xray: Pass executor - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot - this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config - this.generator = gen; -@@ -347,6 +348,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - this.chunkPacketBlockController = this.paperConfig().anticheat.antiXray.enabled ? new com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) : com.destroystokyo.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray - } - -+ // Leaves start - thread unsafe random get -+ public net.minecraft.util.RandomSource getThreadUnsafeRandom() { -+ return randomTickRandom; -+ } -+ // Leaves end - thread unsafe random get -+ - // Paper start - Cancel hit for vanished players - // ret true if no collision - public final boolean checkEntityCollision(BlockState data, Entity source, net.minecraft.world.phys.shapes.CollisionContext voxelshapedcollision, diff --git a/patches/removed/server/0026-Remove-iterators-from-inventory-contains.patch b/patches/removed/server/0026-Remove-iterators-from-inventory-contains.patch deleted file mode 100644 index 002b1f2a..00000000 --- a/patches/removed/server/0026-Remove-iterators-from-inventory-contains.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Wed, 17 Aug 2022 11:04:12 +0800 -Subject: [PATCH] Remove iterators from inventory contains - -This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) - -diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java -index 0e214d502998e9eb959952b257844529992df0df..9506c4cf1c757219f9f01c06cf61ad3e40ee0979 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Inventory.java -+++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java -@@ -649,17 +649,31 @@ public class Inventory implements Container, Nameable { - } - - public boolean contains(ItemStack stack) { -- Iterator iterator = this.compartments.iterator(); -+ // Leaves start - don't allocate iterators -+ if (org.leavesmc.leaves.LeavesConfig.performance.remove.inventoryContainsIterators) { -+ for (int i = 0; i < this.compartments.size(); i++) { -+ List list = this.compartments.get(i); -+ for (int j = 0; j < list.size(); j++) { -+ ItemStack itemstack = list.get(j); -+ -+ if (!itemstack.isEmpty() && ItemStack.isSameItemSameComponents(itemstack, stack)) { -+ return true; -+ } -+ } -+ } -+ } else { -+ Iterator iterator = this.compartments.iterator(); - -- while (iterator.hasNext()) { -- List list = (List) iterator.next(); -- Iterator iterator1 = list.iterator(); -+ while (iterator.hasNext()) { -+ List list = (List) iterator.next(); -+ Iterator iterator1 = list.iterator(); - -- while (iterator1.hasNext()) { -- ItemStack itemstack1 = (ItemStack) iterator1.next(); -+ while (iterator1.hasNext()) { -+ ItemStack itemstack1 = (ItemStack) iterator1.next(); - -- if (!itemstack1.isEmpty() && ItemStack.isSameItemSameComponents(itemstack1, stack)) { -- return true; -+ if (!itemstack1.isEmpty() && ItemStack.isSameItemSameComponents(itemstack1, stack)) { -+ return true; -+ } - } - } - } -@@ -668,17 +682,30 @@ public class Inventory implements Container, Nameable { - } - - public boolean contains(TagKey tag) { -- Iterator iterator = this.compartments.iterator(); -+ if (org.leavesmc.leaves.LeavesConfig.performance.remove.inventoryContainsIterators) { -+ for (int i = 0; i < this.compartments.size(); i++) { -+ List list = this.compartments.get(i); -+ for (int j = 0; j < list.size(); j++) { -+ ItemStack itemstack = list.get(j); - -- while (iterator.hasNext()) { -- List list = (List) iterator.next(); -- Iterator iterator1 = list.iterator(); -+ if (!itemstack.isEmpty() && itemstack.is(tag)) { -+ return true; -+ } -+ } -+ } -+ } else { -+ Iterator iterator = this.compartments.iterator(); -+ -+ while (iterator.hasNext()) { -+ List list = (List) iterator.next(); -+ Iterator iterator1 = list.iterator(); - -- while (iterator1.hasNext()) { -- ItemStack itemstack = (ItemStack) iterator1.next(); -+ while (iterator1.hasNext()) { -+ ItemStack itemstack = (ItemStack) iterator1.next(); - -- if (!itemstack.isEmpty() && itemstack.is(tag)) { -- return true; -+ if (!itemstack.isEmpty() && itemstack.is(tag)) { -+ return true; -+ } - } - } - } -@@ -687,21 +714,34 @@ public class Inventory implements Container, Nameable { - } - - public boolean contains(Predicate predicate) { -- Iterator iterator = this.compartments.iterator(); -+ if (org.leavesmc.leaves.LeavesConfig.performance.remove.inventoryContainsIterators) { -+ for (int i = 0; i < this.compartments.size(); i++) { -+ List list = this.compartments.get(i); -+ for (int j = 0; j < list.size(); j++) { -+ ItemStack itemstack = list.get(j); - -- while (iterator.hasNext()) { -- List list = (List) iterator.next(); -- Iterator iterator1 = list.iterator(); -+ if (predicate.test(itemstack)) { -+ return true; -+ } -+ } -+ } -+ } else { -+ Iterator iterator = this.compartments.iterator(); - -- while (iterator1.hasNext()) { -- ItemStack itemstack = (ItemStack) iterator1.next(); -+ while (iterator.hasNext()) { -+ List list = (List) iterator.next(); -+ Iterator iterator1 = list.iterator(); - -- if (predicate.test(itemstack)) { -- return true; -+ while (iterator1.hasNext()) { -+ ItemStack itemstack = (ItemStack) iterator1.next(); -+ -+ if (predicate.test(itemstack)) { -+ return true; -+ } - } - } - } -- -+ // Leaves end - don't allocate iterators - return false; - } - diff --git a/patches/removed/server/0026-Use-thread-unsafe-random-for-mob-spawning.patch b/patches/removed/server/0026-Use-thread-unsafe-random-for-mob-spawning.patch deleted file mode 100644 index e8d2f211..00000000 --- a/patches/removed/server/0026-Use-thread-unsafe-random-for-mob-spawning.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Mon, 15 Aug 2022 08:23:51 +0800 -Subject: [PATCH] Use thread unsafe random for mob spawning - -This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) - -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 189a6bd4967aba72e12170e091dbb5b779e752a0..9c72271382fa0b6be5f38b45577fb1ae81ce80a3 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -408,12 +408,21 @@ public final class NaturalSpawner { - - private static BlockPos getRandomPosWithin(Level world, LevelChunk chunk) { - ChunkPos chunkcoordintpair = chunk.getPos(); -- int i = chunkcoordintpair.getMinBlockX() + world.random.nextInt(16); -- int j = chunkcoordintpair.getMinBlockZ() + world.random.nextInt(16); -- int k = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, i, j) + 1; -- int l = Mth.randomBetweenInclusive(world.random, world.getMinBuildHeight(), k); -- -- return new BlockPos(i, l, j); -+ // Leaves start - use thread unsafe random -+ if (org.leavesmc.leaves.LeavesConfig.useMoreThreadUnsafeRandom) { -+ int i = chunkcoordintpair.getMinBlockX() + world.getThreadUnsafeRandom().nextInt(16); -+ int j = chunkcoordintpair.getMinBlockZ() + world.getThreadUnsafeRandom().nextInt(16); -+ int k = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, i, j) + 1; -+ int l = Mth.randomBetweenInclusive(world.getThreadUnsafeRandom(), world.getMinBuildHeight(), k); -+ return new BlockPos(i, l, j); -+ } else { -+ int i = chunkcoordintpair.getMinBlockX() + world.random.nextInt(16); -+ int j = chunkcoordintpair.getMinBlockZ() + world.random.nextInt(16); -+ int k = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, i, j) + 1; -+ int l = Mth.randomBetweenInclusive(world.random, world.getMinBuildHeight(), k); -+ return new BlockPos(i, l, j); -+ } -+ // Leaves end - use thread unsafe random - } - - public static boolean isValidEmptySpawnBlock(BlockGetter blockView, BlockPos pos, BlockState state, FluidState fluidState, EntityType entityType) { diff --git a/patches/removed/server/0028-Remove-streams-and-iterators-from-range-check.patch b/patches/removed/server/0028-Remove-streams-and-iterators-from-range-check.patch deleted file mode 100644 index 35db91a9..00000000 --- a/patches/removed/server/0028-Remove-streams-and-iterators-from-range-check.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Wed, 17 Aug 2022 11:19:33 +0800 -Subject: [PATCH] Remove streams and iterators from range check - -This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 0451f7499121a53ce1bd13130581548f60b61996..e0650881a3f90532fc446607cf5ae34da4a2a1dc 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1284,19 +1284,45 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return ChunkMap.this.level.getServer().getScaledTrackingDistance(initialDistance); - } - -+ // Leaves start -+ private static int getHighestRange(Entity parent, int highest) { -+ List passengers = parent.getPassengers(); -+ -+ for (int i = 0, size = passengers.size(); i < size; i++) { -+ Entity entity = passengers.get(i); -+ int range = entity.getType().clientTrackingRange() * 16; -+ range = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, range); // Paper -+ -+ if (range > highest) { // Paper - we need the lowest range thanks to the fact that our tracker doesn't account for passenger logic // Tuinity - not anymore! -+ highest = range; -+ } -+ -+ highest = getHighestRange(entity, highest); -+ } -+ -+ return highest; -+ } -+ // Leaves end -+ - private int getEffectiveRange() { - int i = this.range; -- Iterator iterator = this.entity.getIndirectPassengers().iterator(); -+ // Leaves start - remove iterators and streams -+ if (org.leavesmc.leaves.LeavesConfig.removeRangeCheckStreams) { -+ i = getHighestRange(this.entity, i); -+ } else { -+ Iterator iterator = this.entity.getIndirectPassengers().iterator(); - -- while (iterator.hasNext()) { -- Entity entity = (Entity) iterator.next(); -- int j = entity.getType().clientTrackingRange() * 16; -- j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper -+ while (iterator.hasNext()) { -+ Entity entity = (Entity) iterator.next(); -+ int j = entity.getType().clientTrackingRange() * 16; -+ j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper - -- if (j > i) { -- i = j; -+ if (j > i) { -+ i = j; -+ } - } - } -+ // Leaves end - remove iterators and streams - - return this.scaledRange(i); - } diff --git a/patches/removed/server/0030-Use-aging-cache-for-biome-temperatures.patch b/patches/removed/server/0030-Use-aging-cache-for-biome-temperatures.patch deleted file mode 100644 index e0de2be5..00000000 --- a/patches/removed/server/0030-Use-aging-cache-for-biome-temperatures.patch +++ /dev/null @@ -1,236 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Thu, 18 Aug 2022 16:53:45 +0800 -Subject: [PATCH] Use aging cache for biome temperatures - -This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) - -diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java -index 90c165c890a2d998e3b0af9b4310e3995ede6f64..6db6f96af0058d5eaf725e743d3019e3a3b8604c 100644 ---- a/src/main/java/net/minecraft/world/level/biome/Biome.java -+++ b/src/main/java/net/minecraft/world/level/biome/Biome.java -@@ -63,7 +63,17 @@ public final class Biome { - private final BiomeGenerationSettings generationSettings; - private final MobSpawnSettings mobSettings; - private final BiomeSpecialEffects specialEffects; -- private final ThreadLocal temperatureCache = ThreadLocal.withInitial(() -> Util.make(() -> { -+ // Leaves start - use our cache -+ private final ThreadLocal temperatureCache; -+ private final ThreadLocal temperatureAgingCache; -+ -+ Biome(Biome.ClimateSettings weather, BiomeSpecialEffects effects, BiomeGenerationSettings generationSettings, MobSpawnSettings spawnSettings) { -+ this.climateSettings = weather; -+ this.generationSettings = generationSettings; -+ this.mobSettings = spawnSettings; -+ this.specialEffects = effects; -+ -+ temperatureCache = ThreadLocal.withInitial(() -> Util.make(() -> { - Long2FloatLinkedOpenHashMap long2FloatLinkedOpenHashMap = new Long2FloatLinkedOpenHashMap(1024, 0.25F) { - protected void rehash(int i) { - } -@@ -71,13 +81,13 @@ public final class Biome { - long2FloatLinkedOpenHashMap.defaultReturnValue(Float.NaN); - return long2FloatLinkedOpenHashMap; - })); -- -- Biome(Biome.ClimateSettings weather, BiomeSpecialEffects effects, BiomeGenerationSettings generationSettings, MobSpawnSettings spawnSettings) { -- this.climateSettings = weather; -- this.generationSettings = generationSettings; -- this.mobSettings = spawnSettings; -- this.specialEffects = effects; -+ temperatureAgingCache = ThreadLocal.withInitial(() -> { -+ return Util.make(() -> { -+ return new org.leavesmc.leaves.structs.Long2FloatAgingCache(TEMPERATURE_CACHE_SIZE); -+ }); -+ }); - } -+ // Leaves end - use our cache - - public int getSkyColor() { - return this.specialEffects.getSkyColor(); -@@ -111,7 +121,33 @@ public final class Biome { - - @Deprecated - public float getTemperature(BlockPos blockPos) { -- return this.getHeightAdjustedTemperature(blockPos); // Paper - optimise random ticking -+ long l = blockPos.asLong(); -+ // Leaves start - use our cache -+ if (org.leavesmc.leaves.LeavesConfig.biomeTemperaturesUseAgingCache) { -+ org.leavesmc.leaves.structs.Long2FloatAgingCache cache = this.temperatureAgingCache.get(); -+ float f = cache.getValue(l); -+ if (!Float.isNaN(f)) { -+ return f; -+ } else { -+ float g = this.getHeightAdjustedTemperature(blockPos); -+ cache.putValue(l, g); -+ return g; -+ } -+ } else { -+ Long2FloatLinkedOpenHashMap long2FloatLinkedOpenHashMap = this.temperatureCache.get(); -+ float f = long2FloatLinkedOpenHashMap.get(l); -+ if (!Float.isNaN(f)) { -+ return f; -+ } else { -+ float g = this.getHeightAdjustedTemperature(blockPos); -+ if (long2FloatLinkedOpenHashMap.size() == 1024) { -+ long2FloatLinkedOpenHashMap.removeFirstFloat(); -+ } -+ long2FloatLinkedOpenHashMap.put(l, g); -+ return g; -+ } -+ } -+ // Leaves end - use our cache - } - - public boolean shouldFreeze(LevelReader world, BlockPos blockPos) { -@@ -139,6 +175,7 @@ public final class Biome { - - return false; - } -+ // Leaves end - use our cache - } - - public boolean coldEnoughToSnow(BlockPos pos) { -@@ -166,6 +203,7 @@ public final class Biome { - - return false; - } -+ // Leaves end - use our cache - } - - public BiomeGenerationSettings getGenerationSettings() { -@@ -317,6 +355,7 @@ public final class Biome { - + this.generationSettings - + ",\n}"; - } -+ // Leaves end - use our cache - } - - public static record ClimateSettings(boolean hasPrecipitation, float temperature, Biome.TemperatureModifier temperatureModifier, float downfall) { -diff --git a/src/main/java/org/leavesmc/leaves/structs/Long2FloatAgingCache.java b/src/main/java/org/leavesmc/leaves/structs/Long2FloatAgingCache.java -new file mode 100644 -index 0000000000000000000000000000000000000000..cd8b1bbfe553c28b75ea92d344364650756e9fdd ---- /dev/null -+++ b/src/main/java/org/leavesmc/leaves/structs/Long2FloatAgingCache.java -@@ -0,0 +1,121 @@ -+package org.leavesmc.leaves.structs; -+ -+import it.unimi.dsi.fastutil.HashCommon; -+ -+// Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) -+ -+/** -+ * A replacement for the cache used in Biome. -+ */ -+public class Long2FloatAgingCache { -+ -+ private static class AgingEntry { -+ private long data; -+ private float value; -+ private int uses = 0; -+ private int age = 0; -+ -+ private AgingEntry(long data, float value) { -+ this.data = data; -+ this.value = value; -+ } -+ -+ public void replace(long data, float flag) { -+ this.data = data; -+ this.value = flag; -+ } -+ -+ public int getValue() { -+ return this.uses - (this.age >> 1); // age isn't as important as uses -+ } -+ -+ public void incrementUses() { -+ this.uses = this.uses + 1 & Integer.MAX_VALUE; -+ } -+ -+ public void incrementAge() { -+ this.age = this.age + 1 & Integer.MAX_VALUE; -+ } -+ } -+ -+ private final AgingEntry[] entries; -+ private final int mask; -+ private final int maxDistance; // the most amount of entries to check for a value -+ -+ public Long2FloatAgingCache(int size) { -+ int arraySize = HashCommon.nextPowerOfTwo(size); -+ this.entries = new AgingEntry[arraySize]; -+ this.mask = arraySize - 1; -+ this.maxDistance = Math.min(arraySize, 4); -+ } -+ -+ public float getValue(long data) { -+ AgingEntry curr; -+ int pos; -+ -+ if ((curr = this.entries[pos = HashCommon.mix(HashCommon.long2int(data)) & this.mask]) == null) { -+ return Float.NaN; -+ } else if (data == curr.data) { -+ curr.incrementUses(); -+ return curr.value; -+ } -+ -+ int checked = 1; // start at 1 because we already checked the first spot above -+ -+ while ((curr = this.entries[pos = (pos + 1) & this.mask]) != null) { -+ if (data == curr.data) { -+ curr.incrementUses(); -+ return curr.value; -+ } else if (++checked >= this.maxDistance) { -+ break; -+ } -+ } -+ -+ return Float.NaN; -+ } -+ -+ public void putValue(long data, float value) { -+ AgingEntry curr; -+ int pos; -+ -+ if ((curr = this.entries[pos = HashCommon.mix(HashCommon.long2int(data)) & this.mask]) == null) { -+ this.entries[pos] = new AgingEntry(data, value); // add -+ return; -+ } else if (data == curr.data) { -+ curr.incrementUses(); -+ return; -+ } -+ -+ int checked = 1; // start at 1 because we already checked the first spot above -+ -+ while ((curr = this.entries[pos = (pos + 1) & this.mask]) != null) { -+ if (data == curr.data) { -+ curr.incrementUses(); -+ return; -+ } else if (++checked >= this.maxDistance) { -+ this.forceAdd(data, value); -+ return; -+ } -+ } -+ -+ this.entries[pos] = new AgingEntry(data, value); // add -+ } -+ -+ private void forceAdd(long data, float value) { -+ int expectedPos = HashCommon.mix(HashCommon.long2int(data)) & this.mask; -+ AgingEntry entryToRemove = this.entries[expectedPos]; -+ -+ for (int i = expectedPos + 1; i < expectedPos + this.maxDistance; i++) { -+ int pos = i & this.mask; -+ AgingEntry entry = this.entries[pos]; -+ if (entry.getValue() < entryToRemove.getValue()) { -+ entryToRemove = entry; -+ } -+ -+ entry.incrementAge(); // use this as a mechanism to age the other entries -+ } -+ -+ // remove the least used/oldest entry -+ entryToRemove.replace(data, value); -+ } -+} diff --git a/patches/removed/server/0041-Improve-fluid-direction-caching.patch b/patches/removed/server/0041-Improve-fluid-direction-caching.patch deleted file mode 100644 index d92b446c..00000000 --- a/patches/removed/server/0041-Improve-fluid-direction-caching.patch +++ /dev/null @@ -1,262 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Fri, 16 Dec 2022 07:45:51 +0800 -Subject: [PATCH] Improve fluid direction caching - -This patch is Powered by Pufferfish -(https://github.com/pufferfish-gg/Pufferfish) - -diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -index 1c0712295695727ee9c4d430d4157b8e17cbd71f..1687ab4965433459219bb5d8aaf5ec8e5baeb605 100644 ---- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java -@@ -53,6 +53,11 @@ public abstract class FlowingFluid extends Fluid { - object2bytelinkedopenhashmap.defaultReturnValue((byte) 127); - return object2bytelinkedopenhashmap; - }); -+ // Leaves start - use our own cache -+ private static final ThreadLocal> localFluidDirectionCache = ThreadLocal.withInitial(() -> { -+ return new org.leavesmc.leaves.structs.FluidDirectionCache<>(2048); -+ }); -+ // Leaves end - use our own cache - private final Map shapes = Maps.newIdentityHashMap(); - - public FlowingFluid() {} -@@ -240,40 +245,70 @@ public abstract class FlowingFluid extends Fluid { - } - - private boolean canPassThroughWall(Direction face, BlockGetter world, BlockPos pos, BlockState state, BlockPos fromPos, BlockState fromState) { -- Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap; -+ // Leaves end - cache -+ if (!org.leavesmc.leaves.LeavesConfig.improveFluidDirectionCaching) { -+ Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap; -+ -+ if (!state.getBlock().hasDynamicShape() && !fromState.getBlock().hasDynamicShape()) { -+ object2bytelinkedopenhashmap = (Object2ByteLinkedOpenHashMap) FlowingFluid.OCCLUSION_CACHE.get(); -+ } else { -+ object2bytelinkedopenhashmap = null; -+ } - -- if (!state.getBlock().hasDynamicShape() && !fromState.getBlock().hasDynamicShape()) { -- object2bytelinkedopenhashmap = (Object2ByteLinkedOpenHashMap) FlowingFluid.OCCLUSION_CACHE.get(); -- } else { -- object2bytelinkedopenhashmap = null; -- } -+ Block.BlockStatePairKey block_a; -+ -+ if (object2bytelinkedopenhashmap != null) { -+ block_a = new Block.BlockStatePairKey(state, fromState, face); -+ byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a); -+ -+ if (b0 != 127) { -+ return b0 != 0; -+ } -+ } else { -+ block_a = null; -+ } - -- Block.BlockStatePairKey block_a; -+ VoxelShape voxelshape = state.getCollisionShape(world, pos); -+ VoxelShape voxelshape1 = fromState.getCollisionShape(world, fromPos); -+ boolean flag = !Shapes.mergedFaceOccludes(voxelshape, voxelshape1, face); - -- if (object2bytelinkedopenhashmap != null) { -- block_a = new Block.BlockStatePairKey(state, fromState, face); -- byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a); -+ if (object2bytelinkedopenhashmap != null) { -+ if (object2bytelinkedopenhashmap.size() == 200) { -+ object2bytelinkedopenhashmap.removeLastByte(); -+ } - -- if (b0 != 127) { -- return b0 != 0; -+ object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0)); - } -+ -+ return flag; - } else { -- block_a = null; -- } -+ org.leavesmc.leaves.structs.FluidDirectionCache cache = null; -+ if (!state.getBlock().hasDynamicShape() && !fromState.getBlock().hasDynamicShape()) { -+ cache = localFluidDirectionCache.get(); -+ } - -- VoxelShape voxelshape = state.getCollisionShape(world, pos); -- VoxelShape voxelshape1 = fromState.getCollisionShape(world, fromPos); -- boolean flag = !Shapes.mergedFaceOccludes(voxelshape, voxelshape1, face); -+ Block.BlockStatePairKey block_a; -+ if (cache != null) { -+ block_a = new Block.BlockStatePairKey(state, fromState, face); -+ Boolean flag = cache.getValue(block_a); -+ if (flag != null) { -+ return flag; -+ } -+ } else { -+ block_a = null; -+ } - -- if (object2bytelinkedopenhashmap != null) { -- if (object2bytelinkedopenhashmap.size() == 200) { -- object2bytelinkedopenhashmap.removeLastByte(); -+ VoxelShape voxelshape = state.getCollisionShape(world, pos); -+ VoxelShape voxelshape1 = fromState.getCollisionShape(world, fromPos); -+ boolean flag = !Shapes.mergedFaceOccludes(voxelshape, voxelshape1, face); -+ -+ if (cache != null) { -+ cache.putValue(block_a, flag); - } - -- object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0)); -+ return flag; - } -- -- return flag; -+ // Leaves start - cache - } - - public abstract Fluid getFlowing(); -diff --git a/src/main/java/org/leavesmc/leaves/structs/FluidDirectionCache.java b/src/main/java/org/leavesmc/leaves/structs/FluidDirectionCache.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e07a7c68d6d552767a77ffc507e6023b77daeac5 ---- /dev/null -+++ b/src/main/java/org/leavesmc/leaves/structs/FluidDirectionCache.java -@@ -0,0 +1,138 @@ -+package org.leavesmc.leaves.structs; -+ -+import it.unimi.dsi.fastutil.HashCommon; -+ -+// Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) -+ -+/** -+ * This is a replacement for the cache used in FluidTypeFlowing. -+ * The requirements for the previous cache were: -+ * - Store 200 entries -+ * - Look for the flag in the cache -+ * - If it exists, move to front of cache -+ * - If it doesn't exist, remove last entry in cache and insert in front -+ *

-+ * This class accomplishes something similar, however has a few different -+ * requirements put into place to make this more optimize: -+ *

-+ * - maxDistance is the most amount of entries to be checked, instead -+ * of having to check the entire list. -+ * - In combination with that, entries are all tracked by age and how -+ * frequently they're used. This enables us to remove old entries, -+ * without constantly shifting any around. -+ *

-+ * Usage of the previous map would have to reset the head every single usage, -+ * shifting the entire map. Here, nothing happens except an increment when -+ * the cache is hit, and when it needs to replace an old element only a single -+ * element is modified. -+ */ -+public class FluidDirectionCache { -+ -+ private static class FluidDirectionEntry { -+ private final T data; -+ private final boolean flag; -+ private int uses = 0; -+ private int age = 0; -+ -+ private FluidDirectionEntry(T data, boolean flag) { -+ this.data = data; -+ this.flag = flag; -+ } -+ -+ public int getValue() { -+ return this.uses - (this.age >> 1); // age isn't as important as uses -+ } -+ -+ public void incrementUses() { -+ this.uses = this.uses + 1 & Integer.MAX_VALUE; -+ } -+ -+ public void incrementAge() { -+ this.age = this.age + 1 & Integer.MAX_VALUE; -+ } -+ } -+ -+ private final FluidDirectionEntry[] entries; -+ private final int mask; -+ private final int maxDistance; // the most amount of entries to check for a value -+ -+ public FluidDirectionCache(int size) { -+ int arraySize = HashCommon.nextPowerOfTwo(size); -+ this.entries = new FluidDirectionEntry[arraySize]; -+ this.mask = arraySize - 1; -+ this.maxDistance = Math.min(arraySize, 4); -+ } -+ -+ public Boolean getValue(T data) { -+ FluidDirectionEntry curr; -+ int pos; -+ -+ if ((curr = this.entries[pos = HashCommon.mix(data.hashCode()) & this.mask]) == null) { -+ return null; -+ } else if (data.equals(curr.data)) { -+ curr.incrementUses(); -+ return curr.flag; -+ } -+ -+ int checked = 1; // start at 1 because we already checked the first spot above -+ -+ while ((curr = this.entries[pos = (pos + 1) & this.mask]) != null) { -+ if (data.equals(curr.data)) { -+ curr.incrementUses(); -+ return curr.flag; -+ } else if (++checked >= this.maxDistance) { -+ break; -+ } -+ } -+ -+ return null; -+ } -+ -+ public void putValue(T data, boolean flag) { -+ FluidDirectionEntry curr; -+ int pos; -+ -+ if ((curr = this.entries[pos = HashCommon.mix(data.hashCode()) & this.mask]) == null) { -+ this.entries[pos] = new FluidDirectionEntry<>(data, flag); // add -+ return; -+ } else if (data.equals(curr.data)) { -+ curr.incrementUses(); -+ return; -+ } -+ -+ int checked = 1; // start at 1 because we already checked the first spot above -+ -+ while ((curr = this.entries[pos = (pos + 1) & this.mask]) != null) { -+ if (data.equals(curr.data)) { -+ curr.incrementUses(); -+ return; -+ } else if (++checked >= this.maxDistance) { -+ this.forceAdd(data, flag); -+ return; -+ } -+ } -+ -+ this.entries[pos] = new FluidDirectionEntry<>(data, flag); // add -+ } -+ -+ private void forceAdd(T data, boolean flag) { -+ int expectedPos = HashCommon.mix(data.hashCode()) & this.mask; -+ -+ int toRemovePos = expectedPos; -+ FluidDirectionEntry entryToRemove = this.entries[toRemovePos]; -+ -+ for (int i = expectedPos + 1; i < expectedPos + this.maxDistance; i++) { -+ int pos = i & this.mask; -+ FluidDirectionEntry entry = this.entries[pos]; -+ if (entry.getValue() < entryToRemove.getValue()) { -+ toRemovePos = pos; -+ entryToRemove = entry; -+ } -+ -+ entry.incrementAge(); // use this as a mechanism to age the other entries -+ } -+ -+ // remove the least used/oldest entry -+ this.entries[toRemovePos] = new FluidDirectionEntry(data, flag); -+ } -+} diff --git a/patches/removed/server/0067-Cache-world-generator-sea-level.patch b/patches/removed/server/0067-Cache-world-generator-sea-level.patch deleted file mode 100644 index 65de710d..00000000 --- a/patches/removed/server/0067-Cache-world-generator-sea-level.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Tue, 18 Jul 2023 14:22:06 +0800 -Subject: [PATCH] Cache world generator sea level - -This patch is Powered by Gale(https://github.com/GaleMC/Gale) - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -index 3f39d6c786d9dfdd9ad591e08ff05fcbb41a1df6..be411653a89e4c3585db95509e3a93d140a05fba 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -@@ -61,12 +61,17 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - private static final BlockState AIR = Blocks.AIR.defaultBlockState(); - public final Holder settings; - private final Supplier globalFluidPicker; -+ private int cachedSeaLevel; // Leaves - cache world generator sea level - - public NoiseBasedChunkGenerator(BiomeSource biomeSource, Holder settings) { - super(biomeSource); - this.settings = settings; - this.globalFluidPicker = Suppliers.memoize(() -> { -- return NoiseBasedChunkGenerator.createFluidPicker((NoiseGeneratorSettings) settings.value()); -+ // Leaves start - cache world generator sea level -+ var fluidPicker = NoiseBasedChunkGenerator.createFluidPicker((NoiseGeneratorSettings) settings.value()); -+ this.cachedSeaLevel = settings.value().seaLevel(); -+ return fluidPicker; -+ // Leaves end - cache world generator sea level - }); - } - -@@ -409,7 +414,13 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - - @Override - public int getSeaLevel() { -- return ((NoiseGeneratorSettings) this.settings.value()).seaLevel(); -+ // Leaves start - cache world generator sea level -+ if (!org.leavesmc.leaves.LeavesConfig.performance.cacheWorldGeneratorSeaLevel) { -+ return ((NoiseGeneratorSettings) this.settings.value()).seaLevel(); -+ } else { -+ return cachedSeaLevel; -+ } -+ // Leaves end - cache world generator sea level - } - - @Override diff --git a/patches/removed/server/0077-Cache-BlockStatePairKey-hash.patch b/patches/removed/server/0077-Cache-BlockStatePairKey-hash.patch deleted file mode 100644 index 462ba53b..00000000 --- a/patches/removed/server/0077-Cache-BlockStatePairKey-hash.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Tue, 18 Jul 2023 14:59:26 +0800 -Subject: [PATCH] Cache BlockStatePairKey hash - -This patch is Powered by Gale(https://github.com/GaleMC/Gale) - -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 0c31c53b1512f0c47a525eff04c1b783cb782fd3..e09b35bfed9880ea6c8168ff6099f1a1a5fb6527 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -626,11 +626,18 @@ public class Block extends BlockBehaviour implements ItemLike { - private final BlockState first; - private final BlockState second; - private final Direction direction; -+ private final int hash; // Leaves - cache BlockStatePairKey hash - - public BlockStatePairKey(BlockState self, BlockState other, Direction facing) { - this.first = self; - this.second = other; - this.direction = facing; -+ // Leaves start - cache BlockStatePairKey hash -+ int hash = this.first.hashCode(); -+ hash = 31 * hash + this.second.hashCode(); -+ hash = 31 * hash + this.direction.hashCode(); -+ this.hash = hash; -+ // Leaves end - cache BlockStatePairKey hash - } - - public boolean equals(Object object) { -@@ -646,11 +653,17 @@ public class Block extends BlockBehaviour implements ItemLike { - } - - public int hashCode() { -- int i = this.first.hashCode(); -+ // Leaves start - cache BlockStatePairKey hash -+ if (!org.leavesmc.leaves.LeavesConfig.cacheBlockStatePairKeyHash) { -+ int i = this.first.hashCode(); - -- i = 31 * i + this.second.hashCode(); -- i = 31 * i + this.direction.hashCode(); -- return i; -+ i = 31 * i + this.second.hashCode(); -+ i = 31 * i + this.direction.hashCode(); -+ return i; -+ } else { -+ return this.hash; -+ } -+ // Leaves end - cache BlockStatePairKey hash - } - } - } diff --git a/patches/removed/server/0099-Disable-moved-wrongly-threshold.patch b/patches/removed/server/0099-Disable-moved-wrongly-threshold.patch deleted file mode 100644 index 097d97d0..00000000 --- a/patches/removed/server/0099-Disable-moved-wrongly-threshold.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Thu, 28 Sep 2023 20:30:46 +0800 -Subject: [PATCH] Disable moved wrongly threshold - - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index a0b0bee8c2c0452d41872722875dbb131ccceacf..fd05c29b888f7979e208e51cfc8a4110f3324eb9 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -574,7 +574,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - // Paper end - Prevent moving into unloaded chunks - -- if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { -+ if (!org.leavesmc.leaves.LeavesConfig.disableMovedWronglyThreshold && d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { // Leaves - disable can - // CraftBukkit end - ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[]{entity.getName().getString(), this.player.getName().getString(), d6, d7, d8}); - this.send(new ClientboundMoveVehiclePacket(entity)); -@@ -610,7 +610,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - d10 = d6 * d6 + d7 * d7 + d8 * d8; - boolean flag2 = false; - -- if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot -+ if (!org.leavesmc.leaves.LeavesConfig.disableMovedWronglyThreshold && d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot // Leaves - disable can - flag2 = true; // Paper - diff on change, this should be moved wrongly - ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", new Object[]{entity.getName().getString(), this.player.getName().getString(), Math.sqrt(d10)}); - } -@@ -1426,7 +1426,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY, - toX, toY, toZ, toYaw, toPitch, true); - if (!event.isAllowed()) { -- if (event.getLogWarning()) -+ if (!org.leavesmc.leaves.LeavesConfig.disableMovedWronglyThreshold && event.getLogWarning()) // Leaves - disable can - ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8}); - this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot()); - return; -@@ -1496,7 +1496,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - d10 = d6 * d6 + d7 * d7 + d8 * d8; - boolean movedWrongly = false; // Paper - Add fail move event; rename - -- if (!this.player.isChangingDimension() && d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot -+ if (!org.leavesmc.leaves.LeavesConfig.disableMovedWronglyThreshold && !this.player.isChangingDimension() && d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot // Leaves - disable can - // Paper start - Add fail move event - io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_WRONGLY, - toX, toY, toZ, toYaw, toPitch, true); diff --git a/patches/removed/server/0115-Fix-Warden-GameEventListener-register-on-load.patch b/patches/removed/server/0115-Fix-Warden-GameEventListener-register-on-load.patch deleted file mode 100644 index c7d6387f..00000000 --- a/patches/removed/server/0115-Fix-Warden-GameEventListener-register-on-load.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Sat, 8 Feb 2025 17:43:55 +0800 -Subject: [PATCH] Fix Warden GameEventListener register on load - -I completely don't understand why it can be fixed, but it fixed - -diff --git a/net/minecraft/world/level/gameevent/DynamicGameEventListener.java b/net/minecraft/world/level/gameevent/DynamicGameEventListener.java -index 2b98932e69271571e6e9350c55c82edc858d76f6..5a0297759836de779c5230d3d19497cd7ac4b37d 100644 ---- a/net/minecraft/world/level/gameevent/DynamicGameEventListener.java -+++ b/net/minecraft/world/level/gameevent/DynamicGameEventListener.java -@@ -41,7 +41,7 @@ public class DynamicGameEventListener { - - private static void ifChunkExists(LevelReader level, @Nullable SectionPos sectionPos, Consumer dispatcherConsumer) { - if (sectionPos != null) { -- ChunkAccess chunk = level.getChunkIfLoadedImmediately(sectionPos.getX(), sectionPos.getZ()); // Paper - Perf: can cause sync loads while completing a chunk, resulting in deadlock -+ ChunkAccess chunk = level.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.FULL, false); // Leaves - disable perf, to fix listener load - if (chunk != null) { - dispatcherConsumer.accept(chunk.getListenerRegistry(sectionPos.y())); - } diff --git a/patches/removed/server/0131-Optimize-random-calls-in-chunk-ticking.patch b/patches/removed/server/0131-Optimize-random-calls-in-chunk-ticking.patch deleted file mode 100644 index c5a94b75..00000000 --- a/patches/removed/server/0131-Optimize-random-calls-in-chunk-ticking.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Thu, 27 Jun 2024 20:15:05 +0800 -Subject: [PATCH] Optimize random calls in chunk ticking - -This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 421fa38abbef8037a3e90ff2e7c8acb76e77a4df..3db7d4ec535654fe8a3e425c6e55859fde37c8de 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -834,7 +834,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - gameprofilerfiller.push("thunder"); - final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change - -- if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - Option to disable thunder -+ if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && (org.leavesmc.leaves.LeavesConfig.optimizeChunkTicking ? chunk.shouldDoLightning(this.random) : this.random.nextInt(this.spigotConfig.thunderChance) == 0)) { // Spigot // Paper - Option to disable thunder // Leaves - replace random with shouldDoLightning - blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper - - if (this.isRainingAt(blockposition)) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 94015519f379fab094b4b24c4b3a1900c1194e17..45a6b59ba3d869e0d6a28de0139908dd35ce6fd9 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -86,6 +86,17 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - private final LevelChunkTicks blockTicks; - private final LevelChunkTicks fluidTicks; - -+ // Leaves start - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively -+ private int lightningTick; -+ public final boolean shouldDoLightning(net.minecraft.util.RandomSource random) { -+ if (this.lightningTick-- <= 0) { -+ this.lightningTick = random.nextInt(this.level.spigotConfig.thunderChance) << 1; -+ return true; -+ } -+ return false; -+ } -+ // Leaves end -+ - public LevelChunk(Level world, ChunkPos pos) { - this(world, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, (LevelChunkSection[]) null, (LevelChunk.PostLoadProcessor) null, (BlendingData) null); - } -@@ -109,6 +120,8 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p - this.postLoad = entityLoader; - this.blockTicks = blockTickScheduler; - this.fluidTicks = fluidTickScheduler; -+ -+ if (org.leavesmc.leaves.LeavesConfig.optimizeChunkTicking) this.lightningTick = this.level.getThreadUnsafeRandom().nextInt(100000) << 1; // Leaves - initialize lightning tick - } - - // CraftBukkit start diff --git a/patches/unapplied/server/0058-Spawn-ignore-lc.patch b/patches/unapplied/server/0058-Spawn-ignore-lc.patch deleted file mode 100644 index e43a352a..00000000 --- a/patches/unapplied/server/0058-Spawn-ignore-lc.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: violetc <58360096+s-yh-china@users.noreply.github.com> -Date: Thu, 29 Jun 2023 22:40:24 +0800 -Subject: [PATCH] Spawn ignore lc - - -diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 4772d0b1c70213bb73aa22eca820ade21335b3a8..9f188a921781f9620b6dcdc6c7549a8a4709efa1 100644 ---- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java -+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -230,6 +230,19 @@ public final class NaturalSpawner { - } - public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer trackEntity) { - // Paper end - Optional per player mob spawns -+ // Leaves start - ignore lc -+ if (org.leavesmc.leaves.LeavesConfig.ignoreLC) { -+ int spawnN = 0; -+ for (int i = chunk.getMinBuildHeight(); i < chunk.getMaxBuildHeight(); i += 16) { -+ net.minecraft.world.level.chunk.LevelChunkSection section = chunk.getSections()[chunk.getSectionIndex(i)]; -+ if (section != null && !section.hasOnlyAir()) { -+ BlockPos pos = getRandomPosInChunk(world, chunk).offset(0, i, 0); -+ spawnN += spawnCategoryForPosition(group, world, chunk, pos, checker, runner, maxSpawns, trackEntity); -+ } -+ } -+ return spawnN; -+ } -+ // Leaves stop - ignore lc - BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, chunk); - - if (blockposition.getY() >= world.getMinY() + 1) { -@@ -237,6 +250,16 @@ public final class NaturalSpawner { - } - } - -+ // Leaves start - ignore lc -+ private static BlockPos getRandomPosInChunk(Level world, LevelChunk chunk) { -+ ChunkPos chunkPos = chunk.getPos(); -+ int x = chunkPos.getMinBlockX() + world.random.nextInt(16); -+ int z = chunkPos.getMinBlockZ() + world.random.nextInt(16); -+ int y = world.random.nextInt(16) + 1; -+ return new BlockPos(x, y, z); -+ } -+ // Leaves stop - ignore lc -+ - @VisibleForDebug - public static void spawnCategoryForPosition(MobCategory group, ServerLevel world, BlockPos pos) { - NaturalSpawner.spawnCategoryForPosition(group, world, world.getChunk(pos), pos, (entitytypes, blockposition1, ichunkaccess) -> { diff --git a/scripts/PushToAPI.sh b/scripts/PushToAPI.sh index 1cf7cd49..a7378ed8 100644 --- a/scripts/PushToAPI.sh +++ b/scripts/PushToAPI.sh @@ -5,22 +5,21 @@ sha256() { prop() { grep "${1}" gradle.properties | cut -d'=' -f2 | sed 's/\r//' } + +# shellcheck disable=SC2154 echo "$tag" project_id="leaves" -project_name="leaves" mcversion=$(prop mcVersion) -ctime=$(date -u +"%Y-%m-%dT%H:%M:%SZ") -pre=$(prop preVersion) -if [ $pre = "true" ]; then +if [ "$(prop preVersion)" = "true" ]; then channel="experimental" else channel="default" fi -promoted=false -number=$(git log --oneline master ^`git describe --tags --abbrev=0` | wc -l) +number=$(git log --oneline master ^"$(git describe --tags --abbrev=0)" | wc -l) changes=$(git log --pretty='%H<<<%s>>>' -"$number" | sed ':a;N;$!ba;s/\n//g') jar_name="leaves-$mcversion.jar" -jar_sha256=`sha256 $jar_name` +jar_sha256=$(sha256 "$jar_name") +# shellcheck disable=SC2154 curl --location --request POST "https://api.leavesmc.org/v2/commit/build" --header "Content-Type: application/json" --header "Authentication: Bearer $secret_v2" --data-raw "{\"project_id\":\"$project_id\",\"version\":\"$mcversion\",\"channel\":\"$channel\",\"changes\":\"$changes\",\"jar_name\":\"$jar_name\",\"sha256\":\"$jar_sha256\",\"tag\":\"$tag\"}" \ No newline at end of file