Fix wrong ticket update determination in RegionizedTaskQueue
This commit is contained in:
+279
@@ -0,0 +1,279 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NanaChiyo0721 <nanachiyo0721@163.com>
|
||||
Date: Sat, 25 Jul 2026 21:16:19 +0800
|
||||
Subject: [PATCH] Lithium optimized non poi block searching
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
|
||||
index c6e9b155c2341c13d569f28f54f0c1d2d7313676..7bd3c8a1c627cfd3e377a269c649c0c169634b49 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
|
||||
@@ -5,7 +5,7 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.PathfinderMob;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
|
||||
-public abstract class MoveToBlockGoal extends Goal {
|
||||
+public abstract class MoveToBlockGoal extends Goal implements net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.LithiumMoveToBlockGoal { // Shiroha - Lithium Optimizes move to block goal
|
||||
private static final int GIVE_UP_TICKS = 1200;
|
||||
private static final int STAY_TICKS = 1200;
|
||||
private static final int INTERVAL_TICKS = 200;
|
||||
@@ -133,4 +133,167 @@ public abstract class MoveToBlockGoal extends Goal {
|
||||
}
|
||||
|
||||
protected abstract boolean isValidTarget(LevelReader level, BlockPos pos);
|
||||
+ // Shiorha start - Lithium Optimizes move to block goal
|
||||
+ /**
|
||||
+ * Finds the nearest block matching the predicates.
|
||||
+ * <p>
|
||||
+ * Side effect: The matching block position is stored in the blockPos field.
|
||||
+ *
|
||||
+ * @return Whether a matching block was found.
|
||||
+ */
|
||||
+ @Override
|
||||
+ public boolean lithium$findNearestBlock(java.util.function.Predicate<net.minecraft.world.level.block.state.BlockState> requiredBlock, java.util.function.BiPredicate<net.minecraft.world.level.chunk.ChunkAccess,
|
||||
+ BlockPos.MutableBlockPos> lithium$isValidTarget, final boolean shouldChunkLoad) {
|
||||
+ //Center of the search starts 1 block below the mob's block position
|
||||
+ BlockPos center = this.mob.blockPosition().offset(0,-1,0);
|
||||
+
|
||||
+ //Range is +-(searchRange - 1), +-verticalSearchRange, +-(searchRange - 1)
|
||||
+ //Cache ChunkAccesses - getting them is surprisingly expensive - and track whether subchunks have the block
|
||||
+ final LevelReader levelReader = this.mob.level();
|
||||
+ net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CheckAndCacheBlockChecker checker = new net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CheckAndCacheBlockChecker(center,
|
||||
+ this.searchRange-1, this.verticalSearchRange,
|
||||
+ levelReader, requiredBlock, shouldChunkLoad);
|
||||
+ it.unimi.dsi.fastutil.longs.LongArrayList sortedChunksMaybeWithBlock = new it.unimi.dsi.fastutil.longs.LongArrayList(checker.getChunkSize());
|
||||
+ checker.initializeChunks(sortedChunksMaybeWithBlock::addLast);
|
||||
+
|
||||
+ if (checker.shouldStop()) {
|
||||
+ return false; //No chunks with the target block - return early
|
||||
+ }
|
||||
+
|
||||
+ final int minY = net.caffeinemc.mods.lithium.common.util.Pos.BlockCoord.getMinY(levelReader);
|
||||
+ final int maxY = net.caffeinemc.mods.lithium.common.util.Pos.BlockCoord.getMaxYInclusive(levelReader);
|
||||
+
|
||||
+ // Prefer chunk aware search because it also cuts iterations inside "empty" chunk sections
|
||||
+ if(!checker.hasUnloadedPossibleChunks()){
|
||||
+ return this.lithium$chunkAwareSearch(center, lithium$isValidTarget, checker, sortedChunksMaybeWithBlock, minY, maxY);
|
||||
+ }
|
||||
+
|
||||
+ // Use vanilla search because unordered search may observably alter chunk-loading behavior
|
||||
+ return this.lithium$vanillaOrderSearch(center, lithium$isValidTarget, checker, minY, maxY);
|
||||
+ }
|
||||
+
|
||||
+ private boolean lithium$vanillaOrderSearch(BlockPos center,
|
||||
+ java.util.function.BiPredicate<net.minecraft.world.level.chunk.ChunkAccess, BlockPos.MutableBlockPos> lithium$isValidTarget,
|
||||
+ net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CheckAndCacheBlockChecker checker, final int minY, final int maxY) {
|
||||
+ BlockPos.MutableBlockPos currentPos = new BlockPos.MutableBlockPos();
|
||||
+ final int centerY = center.getY();
|
||||
+
|
||||
+ for (int layer = this.verticalSearchStart; layer <= this.verticalSearchRange; layer = layer > 0 ? -layer : 1 - layer) {
|
||||
+ final int y = centerY + layer;
|
||||
+
|
||||
+ // Layer outside of build limit - skip
|
||||
+ // Note: this is likely to be hit because farms where this lags tend to be built at world floor
|
||||
+ if (y < minY || y > maxY) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ for (int ring = 0; ring < this.searchRange; ring++) {
|
||||
+ for (int dX = 0; dX <= ring; dX = dX > 0 ? -dX : 1 - dX) {
|
||||
+ for (int dZ = dX < ring && dX > -ring ? ring : 0; dZ <= ring; dZ = dZ > 0 ? -dZ : 1 - dZ) {
|
||||
+ currentPos.setWithOffset(center, dX, layer, dZ);
|
||||
+ if (this.mob.isWithinHome(currentPos) && checker.checkPosition(currentPos)) {
|
||||
+ // ChunkAccess is always loaded at this point
|
||||
+ net.minecraft.world.level.chunk.ChunkAccess chunkAccess = checker.getCachedChunkAccess(currentPos);
|
||||
+ if (lithium$isValidTarget.test(chunkAccess, currentPos)){
|
||||
+ this.blockPos = currentPos;
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ private boolean lithium$chunkAwareSearch(BlockPos center,
|
||||
+ java.util.function.BiPredicate<net.minecraft.world.level.chunk.ChunkAccess, BlockPos.MutableBlockPos> lithium$isValidTarget,
|
||||
+ net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CheckAndCacheBlockChecker checker, it.unimi.dsi.fastutil.longs.LongArrayList sortedChunksMaybeWithBlock,
|
||||
+ final int minY, final int maxY) {
|
||||
+ // Sort chunks by lowest sort order - has the earliest searched position
|
||||
+ // Note: In this search order, the closest point normally is also the closest point in the search
|
||||
+ sortedChunksMaybeWithBlock.sort((chunkLong0, chunkLong1) ->
|
||||
+ net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.NonPOISearchDistances.MoveToBlockGoalDistances.getMinimumSortOrderOfChunk(center, chunkLong0)
|
||||
+ - net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.NonPOISearchDistances.MoveToBlockGoalDistances.getMinimumSortOrderOfChunk(center, chunkLong1)
|
||||
+ );
|
||||
+
|
||||
+ java.util.function.Predicate<net.minecraft.world.level.block.state.BlockState> requiredBlock = checker.blockStatePredicate;
|
||||
+ final int minSectionY = checker.minSectionY;
|
||||
+
|
||||
+ BlockPos.MutableBlockPos foundPos = new BlockPos.MutableBlockPos();
|
||||
+ BlockPos.MutableBlockPos currentPos = new BlockPos.MutableBlockPos();
|
||||
+
|
||||
+ // Same layer order as vanilla - saves iterations if targets are found in the first layer
|
||||
+ for (int layer = this.verticalSearchStart; layer <= this.verticalSearchRange; layer = layer > 0 ? -layer : 1 - layer) {
|
||||
+ final int y = center.getY() + layer;
|
||||
+
|
||||
+ // Layer outside of build limit - skip
|
||||
+ // Note: this is likely to be hit because farms where this lags tend to be built at world floor
|
||||
+ if (y < minY || y > maxY) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final int chunkY = net.minecraft.core.SectionPos.blockToSectionCoord(y);
|
||||
+ final int ySectionIndex = chunkY - minSectionY;
|
||||
+
|
||||
+ int closestFound = Integer.MAX_VALUE;
|
||||
+ int ringMax = this.searchRange - 1;
|
||||
+
|
||||
+ // Iterate through slices of chunks that may have the target blockState
|
||||
+ for (long chunkPos: sortedChunksMaybeWithBlock) {
|
||||
+ final int chunkX = net.minecraft.world.level.ChunkPos.getX(chunkPos);
|
||||
+ final int chunkZ = net.minecraft.world.level.ChunkPos.getZ(chunkPos);
|
||||
+
|
||||
+ // Break since no subsequent chunks can be closer
|
||||
+ if (closestFound < net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.NonPOISearchDistances.MoveToBlockGoalDistances.getMinimumSortOrderOfChunk(center, chunkX, chunkZ)) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ // Skip if the current subchunk does not have the block
|
||||
+ if (!checker.checkCachedSection(chunkX, chunkY, chunkZ)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ net.minecraft.world.level.chunk.ChunkAccess chunkAccess = checker.getCachedChunkAccess(chunkPos);
|
||||
+ // If ChunkSection may have close enough targets, iterate layer in Paletted Container (x then z) order
|
||||
+ final int chunkBlockX = net.minecraft.core.SectionPos.sectionToBlockCoord(chunkX);
|
||||
+ int xMin = Math.max(center.getX() - ringMax, chunkBlockX);
|
||||
+ int xMax = Math.min(center.getX() + ringMax, chunkBlockX + 15);
|
||||
+ final int chunkBlockZ = net.minecraft.core.SectionPos.sectionToBlockCoord(chunkZ);
|
||||
+ int zMin = Math.max(center.getZ() - ringMax, chunkBlockZ);
|
||||
+ int zMax = Math.min(center.getZ() + ringMax, chunkBlockZ + 15);
|
||||
+ net.minecraft.world.level.chunk.LevelChunkSection levelChunkSection = chunkAccess.getSections()[ySectionIndex];
|
||||
+ for (int z = zMin; z <= zMax; z++) {
|
||||
+ for (int x = xMin; x <= xMax; x++) {
|
||||
+ int dX = x - center.getX();
|
||||
+ int dZ = z - center.getZ();
|
||||
+ int ring = net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.NonPOISearchDistances.MoveToBlockGoalDistances.getRing(dX, dZ);
|
||||
+ int currentDistance = net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.NonPOISearchDistances.MoveToBlockGoalDistances.getVanillaSortOrderInt(ring, dX, dZ);
|
||||
+ if (currentDistance < closestFound
|
||||
+ && this.mob.isWithinHome(currentPos.set(x, y, z))
|
||||
+ && requiredBlock.test(levelChunkSection.getBlockState(x & 15, y & 15, z & 15))
|
||||
+ && lithium$isValidTarget.test(chunkAccess, currentPos)) {
|
||||
+ // Constrain search size when we find a valid target
|
||||
+ ringMax = ring;
|
||||
+ xMin = Math.max(center.getX() - ringMax, chunkBlockX);
|
||||
+ xMax = Math.min(center.getX() + ringMax, chunkBlockX + 15);
|
||||
+ zMax = Math.min(center.getZ() + ringMax, chunkBlockZ + 15);
|
||||
+ foundPos.set(x, y, z);
|
||||
+ closestFound = currentDistance;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (closestFound < Integer.MAX_VALUE) {
|
||||
+ // Vanilla uses the mutable pos, no need to create immutable copy
|
||||
+ this.blockPos = foundPos;
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Shiorha end - Lithium Optimizes move to block goal
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
index ff0f99d4b560a1c0721885b0eba5bd5ab2087bd7..90beeee7b74324f81690776546713b4f04887f75 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
|
||||
@@ -25,6 +25,19 @@ public class RemoveBlockGoal extends MoveToBlockGoal {
|
||||
private final Mob removerMob;
|
||||
private int ticksSinceReachedGoal;
|
||||
private static final int WAIT_AFTER_BLOCK_FOUND = 20;
|
||||
+ // Shiroha start - Lithium Optimize remove block goal
|
||||
+ private static final java.util.function.BiPredicate<ChunkAccess, BlockPos.MutableBlockPos> IS_VALID_TARGET_ABOVE_BIPREDICATE =
|
||||
+ RemoveBlockGoal::lithium$isValidTargetAbove;
|
||||
+ //Split check condition in order to use maybeHas
|
||||
+ private boolean lithium$isValidTargetBlock(net.minecraft.world.level.block.state.BlockState blockState){
|
||||
+ return blockState.is(this.blockToRemove);
|
||||
+ }
|
||||
+
|
||||
+ private static boolean lithium$isValidTargetAbove(ChunkAccess chunkAccess, BlockPos.MutableBlockPos mutable) {
|
||||
+ return chunkAccess.getBlockState(mutable.move(0, 1, 0)).isAir()
|
||||
+ && chunkAccess.getBlockState(mutable.move(0, 1, 0)).isAir();
|
||||
+ }
|
||||
+ // Shiroha end - Lithium Optimize remove block goal
|
||||
|
||||
public RemoveBlockGoal(final Block blockToRemove, final PathfinderMob mob, final double speedModifier, final int verticalSearchRange) {
|
||||
super(mob, speedModifier, 24, verticalSearchRange);
|
||||
@@ -39,7 +52,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal {
|
||||
} else if (this.nextStartTick > 0) {
|
||||
this.nextStartTick--;
|
||||
return false;
|
||||
- } else if (this.findNearestBlock()) {
|
||||
+ } else if (((net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.LithiumMoveToBlockGoal) this).lithium$findNearestBlock(this::lithium$isValidTargetBlock, IS_VALID_TARGET_ABOVE_BIPREDICATE, false)) { // Shiroha - Lithium Optimize remove block goal
|
||||
this.nextStartTick = reducedTickDelay(20);
|
||||
return true;
|
||||
} else {
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/HoglinSpecificSensor.java b/net/minecraft/world/entity/ai/sensing/HoglinSpecificSensor.java
|
||||
index 7022679c84e184999b416e06d1af2cc2500cb12b..ac8f4acc2aaee8ca9f7598d842ecf29f2ad73be3 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/HoglinSpecificSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/HoglinSpecificSensor.java
|
||||
@@ -16,6 +16,14 @@ import net.minecraft.world.entity.monster.hoglin.Hoglin;
|
||||
import net.minecraft.world.entity.monster.piglin.Piglin;
|
||||
|
||||
public class HoglinSpecificSensor extends Sensor<Hoglin> {
|
||||
+ // Shiroha start - Lithium Optimizes Hoglin repellent search.
|
||||
+ private static final java.util.function.Predicate<net.minecraft.world.level.block.state.BlockState> IS_VALID_REPELLENT_PREDICATE =
|
||||
+ HoglinSpecificSensor::lithium$isValidRepellent;
|
||||
+
|
||||
+ private static boolean lithium$isValidRepellent(net.minecraft.world.level.block.state.BlockState blockState) {
|
||||
+ return blockState.is(BlockTags.HOGLIN_REPELLENTS);
|
||||
+ }
|
||||
+ // Shiroha end - Lithium Optimizes Hoglin repellent search.
|
||||
@Override
|
||||
public Set<MemoryModuleType<?>> requires() {
|
||||
return ImmutableSet.of(
|
||||
@@ -30,8 +38,8 @@ public class HoglinSpecificSensor extends Sensor<Hoglin> {
|
||||
|
||||
@Override
|
||||
protected void doTick(final ServerLevel level, final Hoglin body) {
|
||||
- Brain<?> brain = body.getBrain();
|
||||
- brain.setMemory(MemoryModuleType.NEAREST_REPELLENT, this.findNearestRepellent(level, body));
|
||||
+ Brain<?> brain = body.getBrain();;
|
||||
+ brain.setMemory(MemoryModuleType.NEAREST_REPELLENT, net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CommonBlockSearchesCheckAndCache.blockPosFindClosestMatch(level, body, 8, 4, IS_VALID_REPELLENT_PREDICATE, true)); // Shiroha - Lithium Optimizes Hoglin repellent search.
|
||||
Optional<Piglin> adultPiglin = Optional.empty();
|
||||
int adultPiglinCount = 0;
|
||||
List<Hoglin> adultHoglins = Lists.newArrayList();
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/PiglinSpecificSensor.java b/net/minecraft/world/entity/ai/sensing/PiglinSpecificSensor.java
|
||||
index 060a53da799a3036a343cc6f1d73e3e5ca4b7af9..7e5accce5a9183165e7604ca5e144e600b6f503d 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/PiglinSpecificSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/PiglinSpecificSensor.java
|
||||
@@ -26,6 +26,15 @@ import net.minecraft.world.level.block.CampfireBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class PiglinSpecificSensor extends Sensor<LivingEntity> {
|
||||
+ // Shiroha start - Lithium Optimizes Piglin repellent search.
|
||||
+ private static final java.util.function.Predicate<BlockState> IS_VALID_REPELLENT_PREDICATE =
|
||||
+ PiglinSpecificSensor::lithium$isValidRepellent;
|
||||
+ private static boolean lithium$isValidRepellent(BlockState blockState){
|
||||
+ final boolean isPiglinRepellent = blockState.is(BlockTags.PIGLIN_REPELLENTS);
|
||||
+ return isPiglinRepellent && blockState.is(Blocks.SOUL_CAMPFIRE) ?
|
||||
+ CampfireBlock.isLitCampfire(blockState) : isPiglinRepellent;
|
||||
+ }
|
||||
+ // Shiroha end - Lithium Optimizes Piglin repellent search.
|
||||
@Override
|
||||
public Set<MemoryModuleType<?>> requires() {
|
||||
return ImmutableSet.of(
|
||||
@@ -47,7 +56,7 @@ public class PiglinSpecificSensor extends Sensor<LivingEntity> {
|
||||
@Override
|
||||
protected void doTick(final ServerLevel level, final LivingEntity body) {
|
||||
Brain<?> brain = body.getBrain();
|
||||
- brain.setMemory(MemoryModuleType.NEAREST_REPELLENT, findNearestRepellent(level, body));
|
||||
+ brain.setMemory(MemoryModuleType.NEAREST_REPELLENT, net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CommonBlockSearchesCheckAndCache.blockPosFindClosestMatch(level, body, 8, 4, IS_VALID_REPELLENT_PREDICATE, true)); // Shiroha - Lithium Optimizes Piglin repellent search.
|
||||
Optional<Mob> nemesis = Optional.empty();
|
||||
Optional<Hoglin> huntableHoglin = Optional.empty();
|
||||
Optional<Hoglin> babyHoglin = Optional.empty();
|
||||
Reference in New Issue
Block a user