From 4e00b397a73def461772201b5f412d4018177a20 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Tue, 27 Jun 2023 13:34:09 +0800 Subject: [PATCH] Optimized dragon respawn (#29) --- ...004-Leaves-Server-Config-And-Command.patch | 9 +- .../0072-Optimized-dragon-respawn.patch | 145 ++++++++++++++++++ 2 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 patches/server/0072-Optimized-dragon-respawn.patch diff --git a/patches/server/0004-Leaves-Server-Config-And-Command.patch b/patches/server/0004-Leaves-Server-Config-And-Command.patch index cd5b7352..b643af20 100644 --- a/patches/server/0004-Leaves-Server-Config-And-Command.patch +++ b/patches/server/0004-Leaves-Server-Config-And-Command.patch @@ -128,10 +128,10 @@ index a53514f2c510b29f596c361de7bc0b405c27e964..269c7ba0707db4fdc45a70000e0be892 .withRequiredArg() diff --git a/src/main/java/top/leavesmc/leaves/LeavesConfig.java b/src/main/java/top/leavesmc/leaves/LeavesConfig.java new file mode 100644 -index 0000000000000000000000000000000000000000..5a93e6f42bcfde75818daad520da01cf5de6cc47 +index 0000000000000000000000000000000000000000..8a62ffa48472a3d3ef019154379bf2a5a30ce78c --- /dev/null +++ b/src/main/java/top/leavesmc/leaves/LeavesConfig.java -@@ -0,0 +1,752 @@ +@@ -0,0 +1,757 @@ +package top.leavesmc.leaves; + +import com.destroystokyo.paper.util.SneakyThrow; @@ -709,6 +709,11 @@ index 0000000000000000000000000000000000000000..5a93e6f42bcfde75818daad520da01cf + creativeNoClip = getBoolean("settings.modify.creative-no-clip", creativeNoClip); + } + ++ public static boolean optimizedDragonRespawn = false; ++ private static void optimizedDragonRespawn() { ++ optimizedDragonRespawn = getBoolean("settings.performance.optimized-dragon-respawn", optimizedDragonRespawn); ++ } ++ + public static final class WorldConfig { + + public final String worldName; diff --git a/patches/server/0072-Optimized-dragon-respawn.patch b/patches/server/0072-Optimized-dragon-respawn.patch new file mode 100644 index 00000000..a358f825 --- /dev/null +++ b/patches/server/0072-Optimized-dragon-respawn.patch @@ -0,0 +1,145 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: violetc <58360096+s-yh-china@users.noreply.github.com> +Date: Tue, 27 Jun 2023 13:22:34 +0800 +Subject: [PATCH] Optimized dragon respawn + + +diff --git a/src/main/java/net/minecraft/world/level/block/state/pattern/BlockPattern.java b/src/main/java/net/minecraft/world/level/block/state/pattern/BlockPattern.java +index d0a047fd8849e9210dc9424325561f5a1b9998df..b665410788aa7c889dc214c2a97a9c29080b6001 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/pattern/BlockPattern.java ++++ b/src/main/java/net/minecraft/world/level/block/state/pattern/BlockPattern.java +@@ -60,7 +60,7 @@ public class BlockPattern { + } + + @Nullable +- private BlockPattern.BlockPatternMatch matches(BlockPos frontTopLeft, Direction forwards, Direction up, LoadingCache cache) { ++ public BlockPattern.BlockPatternMatch matches(BlockPos frontTopLeft, Direction forwards, Direction up, LoadingCache cache) { // Leaves - private -> public + for(int i = 0; i < this.width; ++i) { + for(int j = 0; j < this.height; ++j) { + for(int k = 0; k < this.depth; ++k) { +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index e2cd77d9de9709aa50f4b6febabe21bfcf94dc5d..d6f2e8875464a0fbf53546424ed65f5e8d73b0e4 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -43,6 +43,7 @@ import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity; + import net.minecraft.world.level.block.entity.TheEndPortalBlockEntity; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; + import net.minecraft.world.level.block.state.pattern.BlockPattern; +@@ -258,8 +259,67 @@ public class EndDragonFight { + return false; + } + ++ // Leaves start - optimizedDragonRespawn ++ private int cachePortalChunkIteratorX = -8; ++ private int cachePortalChunkIteratorZ = -8; ++ private int cachePortalOriginIteratorY = -1; ++ + @Nullable + public BlockPattern.BlockPatternMatch findExitPortal() { ++ if (top.leavesmc.leaves.LeavesConfig.optimizedDragonRespawn) { ++ int i, j; ++ for (i = cachePortalChunkIteratorX; i <= 8; ++i) { ++ for (j = cachePortalChunkIteratorZ; j <= 8; ++j) { ++ LevelChunk worldChunk = this.level.getChunk(i, j); ++ for (BlockEntity blockEntity : worldChunk.getBlockEntities().values()) { ++ if (blockEntity instanceof TheEndGatewayBlockEntity) { ++ continue; ++ } ++ if (blockEntity instanceof TheEndPortalBlockEntity) { ++ BlockPattern.BlockPatternMatch blockPatternMatch = this.exitPortalPattern.find(this.level, blockEntity.getBlockPos()); ++ if (blockPatternMatch != null) { ++ BlockPos blockPos = blockPatternMatch.getBlock(3, 3, 3).getPos(); ++ if (this.portalLocation == null) { ++ this.portalLocation = blockPos; ++ } ++ //No need to judge whether optimizing option is open ++ cachePortalChunkIteratorX = i; ++ cachePortalChunkIteratorZ = j; ++ return blockPatternMatch; ++ } ++ } ++ } ++ } ++ } ++ ++ if (this.needsStateScanning || this.portalLocation == null) { ++ if (cachePortalOriginIteratorY != -1) { ++ i = cachePortalOriginIteratorY; ++ } else { ++ i = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.getLocation(BlockPos.ZERO)).getY(); ++ } ++ boolean notFirstSearch = false; ++ for (j = i; j >= 0; --j) { ++ BlockPattern.BlockPatternMatch result2 = null; ++ if (notFirstSearch) { ++ result2 = top.leavesmc.leaves.util.BlockPatternHelper.partialSearchAround(this.exitPortalPattern, this.level, new BlockPos(EndPodiumFeature.getLocation(BlockPos.ZERO).getY(), j, EndPodiumFeature.getLocation(BlockPos.ZERO).getZ())); ++ } else { ++ result2 = this.exitPortalPattern.find(this.level, new BlockPos(EndPodiumFeature.getLocation(BlockPos.ZERO).getX(), j, EndPodiumFeature.getLocation(BlockPos.ZERO).getZ())); ++ } ++ if (result2 != null) { ++ if (this.portalLocation == null) { ++ this.portalLocation = result2.getBlock(3, 3, 3).getPos(); ++ } ++ cachePortalOriginIteratorY = j; ++ return result2; ++ } ++ notFirstSearch = true; ++ } ++ } ++ ++ return null; ++ } ++ // Leaves end - optimizedDragonRespawn + ChunkPos chunkPos = new ChunkPos(this.origin); + + for(int i = -8 + chunkPos.x; i <= 8 + chunkPos.x; ++i) { +@@ -513,6 +573,11 @@ public class EndDragonFight { + } + + private void respawnDragon(List crystals) { ++ // Leaves - start optimizedDragonRespawn ++ cachePortalChunkIteratorX = -8; ++ cachePortalChunkIteratorZ = -8; ++ cachePortalOriginIteratorY = -1; ++ // Leaves - end optimizedDragonRespawn + if (this.dragonKilled && this.respawnStage == null) { + for(BlockPattern.BlockPatternMatch blockPatternMatch = this.findExitPortal(); blockPatternMatch != null; blockPatternMatch = this.findExitPortal()) { + for(int i = 0; i < this.exitPortalPattern.getWidth(); ++i) { +diff --git a/src/main/java/top/leavesmc/leaves/util/BlockPatternHelper.java b/src/main/java/top/leavesmc/leaves/util/BlockPatternHelper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..cbe424356db5237c261320f0ad5ef5bcf2c70ed4 +--- /dev/null ++++ b/src/main/java/top/leavesmc/leaves/util/BlockPatternHelper.java +@@ -0,0 +1,28 @@ ++package top.leavesmc.leaves.util; ++ ++import com.google.common.cache.LoadingCache; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.state.pattern.BlockInWorld; ++import net.minecraft.world.level.block.state.pattern.BlockPattern; ++ ++// Powered by Carpet-AMS-Addition(https://github.com/Minecraft-AMS/Carpet-AMS-Addition) ++public class BlockPatternHelper { ++ public static BlockPattern.BlockPatternMatch partialSearchAround(BlockPattern pattern, Level world, BlockPos pos) { ++ LoadingCache loadingCache = BlockPattern.createLevelCache(world, false); ++ int i = Math.max(Math.max(pattern.getWidth(), pattern.getHeight()), pattern.getDepth()); ++ ++ for (BlockPos blockPos : BlockPos.betweenClosed(pos, pos.offset(i - 1, 0, i - 1))) { ++ for (Direction direction : Direction.values()) { ++ for (Direction direction2 : Direction.values()) { ++ BlockPattern.BlockPatternMatch result; ++ if (direction2 == direction || direction2 == direction.getOpposite() || (result = pattern.matches(blockPos, direction, direction2, loadingCache)) == null) ++ continue; ++ return result; ++ } ++ } ++ } ++ return null; ++ } ++}