From fb95f9ed0795421cc1b15a2fe882e39dba3d2191 Mon Sep 17 00:00:00 2001
From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
Date: Sun, 20 Oct 2024 14:01:56 -0400
Subject: [PATCH] Moonrise: Avoid streams for block retrieval in Entity#move
---
README.md | 1 +
...treams-for-block-retrieval-in-Entity.patch | 118 ++++++++++++++++++
2 files changed, 119 insertions(+)
create mode 100644 patches/server/0064-Moonrise-Avoid-streams-for-block-retrieval-in-Entity.patch
diff --git a/README.md b/README.md
index 9a5f39b4..7667b812 100644
--- a/README.md
+++ b/README.md
@@ -113,6 +113,7 @@ If these excellent projects hadn't appeared, Leaf wouldn't have become great.
• Matter
• Luminol
• Nitori
+ • Moonrise
diff --git a/patches/server/0064-Moonrise-Avoid-streams-for-block-retrieval-in-Entity.patch b/patches/server/0064-Moonrise-Avoid-streams-for-block-retrieval-in-Entity.patch
new file mode 100644
index 00000000..2246545a
--- /dev/null
+++ b/patches/server/0064-Moonrise-Avoid-streams-for-block-retrieval-in-Entity.patch
@@ -0,0 +1,118 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Spottedleaf
+Date: Thu, 5 Sep 2024 16:23:04 -0700
+Subject: [PATCH] Moonrise: Avoid streams for block retrieval in Entity#move
+
+Original license: GPLv3
+Original project: https://github.com/Tuinity/Moonrise
+
+https://github.com/Tuinity/Moonrise/commit/f9c99d1e32614666913bc614d019dd86e2a0b2e5
+
+Avoid streams for retrieving blocks
+
+diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
+index 085925162f5099609c9b82ca0103d8dd5d2cb22d..1ca8c17df3f0bf6cca8831145c3282834f20a6b5 100644
+--- a/src/main/java/net/minecraft/world/entity/Entity.java
++++ b/src/main/java/net/minecraft/world/entity/Entity.java
+@@ -1337,9 +1337,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+ }
+ }
+ // Gale end - skip negligible planar movement multiplication
+- if (this.level().getBlockStatesIfLoaded(this.getBoundingBox().deflate(1.0E-6D)).noneMatch((iblockdata2) -> {
+- return iblockdata2.is(BlockTags.FIRE) || iblockdata2.is(Blocks.LAVA);
+- })) {
++ if (noLavaAndFireNearEntityByRange(this.getBoundingBox().deflate(1.0E-6D))) { // Moonrise - Avoid streams for block retrieval in Entity#move
+ if (this.remainingFireTicks <= 0) {
+ this.setRemainingFireTicks(-this.getFireImmuneTicks());
+ }
+@@ -1363,6 +1361,90 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
+ // Paper end - detailed watchdog information
+ }
+
++ // Leaf start - Optimize check nearby fire or lava on entity move
++ private boolean nearByBlockStateNoneMatch(java.util.List into, Predicate predicate) {
++ if (into.isEmpty()) return true;
++
++ for (BlockState iblockdata : into) {
++ if (predicate.test(iblockdata)) {
++ return false;
++ }
++ }
++
++ return true;
++ }
++ // Leaf end - Optimize check nearby fire or lava on entity move
++
++ // Moonrise start - Avoid streams for block retrieval in Entity#move
++ private boolean noLavaAndFireNearEntityByRange(final AABB boundingBox) {
++ final int minBlockX = Mth.floor(boundingBox.minX);
++ final int minBlockY = Mth.floor(boundingBox.minY);
++ final int minBlockZ = Mth.floor(boundingBox.minZ);
++
++ final int maxBlockX = Mth.floor(boundingBox.maxX);
++ final int maxBlockY = Mth.floor(boundingBox.maxY);
++ final int maxBlockZ = Mth.floor(boundingBox.maxZ);
++
++ final int minChunkX = minBlockX >> 4;
++ final int minChunkY = minBlockY >> 4;
++ final int minChunkZ = minBlockZ >> 4;
++
++ final int maxChunkX = maxBlockX >> 4;
++ final int maxChunkY = maxBlockY >> 4;
++ final int maxChunkZ = maxBlockZ >> 4;
++
++ final Level world = this.level();
++
++ if (!((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel) world).moonrise$areChunksLoaded(minChunkX, minChunkZ, maxChunkX, maxChunkZ)) {
++ return true;
++ }
++
++ final int minSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection(world);
++ final net.minecraft.world.level.chunk.ChunkSource chunkSource = world.getChunkSource();
++
++ for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) {
++ for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) {
++ final net.minecraft.world.level.chunk.LevelChunkSection[] sections = chunkSource.getChunk(currChunkX, currChunkZ, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, false).getSections();
++
++ for (int currChunkY = minChunkY; currChunkY <= maxChunkY; ++currChunkY) {
++ final int sectionIdx = currChunkY - minSection;
++ if (sectionIdx < 0 || sectionIdx >= sections.length) {
++ continue;
++ }
++ final net.minecraft.world.level.chunk.LevelChunkSection section = sections[sectionIdx];
++ if (section.hasOnlyAir()) {
++ // empty
++ continue;
++ }
++
++ final net.minecraft.world.level.chunk.PalettedContainer blocks = section.states;
++
++ final int minXIterate = currChunkX == minChunkX ? (minBlockX & 15) : 0;
++ final int maxXIterate = currChunkX == maxChunkX ? (maxBlockX & 15) : 15;
++ final int minZIterate = currChunkZ == minChunkZ ? (minBlockZ & 15) : 0;
++ final int maxZIterate = currChunkZ == maxChunkZ ? (maxBlockZ & 15) : 15;
++ final int minYIterate = currChunkY == minChunkY ? (minBlockY & 15) : 0;
++ final int maxYIterate = currChunkY == maxChunkY ? (maxBlockY & 15) : 15;
++
++ for (int currY = minYIterate; currY <= maxYIterate; ++currY) {
++ for (int currZ = minZIterate; currZ <= maxZIterate; ++currZ) {
++ for (int currX = minXIterate; currX <= maxXIterate; ++currX) {
++ final BlockState blockState = blocks.get((currX) | (currZ << 4) | ((currY) << 8));
++
++ if (blockState.is(Blocks.LAVA) || blockState.is(BlockTags.FIRE)) {
++ return false;
++ }
++ }
++ }
++ }
++ }
++ }
++ }
++
++ return true;
++ }
++ // Moonrise end - Avoid streams for block retrieval in Entity#move
++
+ private boolean isStateClimbable(BlockState state) {
+ return state.is(BlockTags.CLIMBABLE) || state.is(Blocks.POWDER_SNOW);
+ }