修复了若干个伐木工作的寻路问题

添加了由女仆自动尝试脱离卡死的功能
This commit is contained in:
xypp
2025-09-15 00:19:36 +08:00
parent 01ec9c0b63
commit fa72af9bc3
10 changed files with 122 additions and 18 deletions

View File

@@ -165,15 +165,14 @@ dependencies {
// http://www.gradle.org/docs/current/userguide/dependency_management.html // http://www.gradle.org/docs/current/userguide/dependency_management.html
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
// compileOnly fg.deobf("curse.maven:touhou-little-maid-355044:6596061") compileOnly fg.deobf("curse.maven:touhou-little-maid-355044:6911704")
// runtimeOnly fg.deobf("curse.maven:touhou-little-maid-355044:6596061") runtimeOnly fg.deobf("curse.maven:touhou-little-maid-355044:6911704")
compileOnly fg.deobf("libs:touhoulittlemaid-${minecraft_version}-release:1.3.7") // compileOnly fg.deobf("libs:touhoulittlemaid-${minecraft_version}-release:1.3.7")
runtimeOnly fg.deobf("libs:touhoulittlemaid-${minecraft_version}-release:1.3.7") // runtimeOnly fg.deobf("libs:touhoulittlemaid-${minecraft_version}-release:1.3.7")
compileOnly fg.deobf("curse.maven:playerrevive-266890:6048921") compileOnly fg.deobf("curse.maven:playerrevive-266890:6048921")
compileOnly fg.deobf("curse.maven:creativecore-257814:6383884") compileOnly fg.deobf("curse.maven:creativecore-257814:6383884")
compileOnly fg.deobf("curse.maven:natures-compass-252848:4712189") compileOnly fg.deobf("curse.maven:natures-compass-252848:4712189")
compileOnly fg.deobf("curse.maven:explorers-compass-491794:4712194") compileOnly fg.deobf("curse.maven:explorers-compass-491794:4712194")
runtimeOnly fg.deobf("curse.maven:maid-storage-manager-1210244:6455832")
runtimeOnly fg.deobf("curse.maven:playerrevive-266890:6048921") runtimeOnly fg.deobf("curse.maven:playerrevive-266890:6048921")
runtimeOnly fg.deobf("curse.maven:creativecore-257814:6383884") runtimeOnly fg.deobf("curse.maven:creativecore-257814:6383884")
// runtimeOnly fg.deobf("curse.maven:natures-compass-252848:4712189") // runtimeOnly fg.deobf("curse.maven:natures-compass-252848:4712189")

View File

@@ -38,7 +38,7 @@ mod_name=maid useful task
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=MIT mod_license=MIT
# The mod version. See https://semver.org/ # The mod version. See https://semver.org/
mod_version=1.3.6 mod_version=1.3.7
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources. # This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html # See https://maven.apache.org/guides/mini/guide-naming-conventions.html

View File

@@ -11,6 +11,9 @@ import net.minecraftforge.fml.event.config.ModConfigEvent;
public class Config { public class Config {
private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder(); private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder();
private static final ForgeConfigSpec.BooleanValue SELF_RESCUE = BUILDER
.define("misc.self_rescue", true);
private static final ForgeConfigSpec.BooleanValue ENABLE_LOGGING = BUILDER private static final ForgeConfigSpec.BooleanValue ENABLE_LOGGING = BUILDER
.define("functions.logging", true); .define("functions.logging", true);
private static final ForgeConfigSpec.BooleanValue ENABLE_REVIVE = BUILDER private static final ForgeConfigSpec.BooleanValue ENABLE_REVIVE = BUILDER
@@ -33,6 +36,8 @@ public class Config {
static final ForgeConfigSpec SPEC = BUILDER.build(); static final ForgeConfigSpec SPEC = BUILDER.build();
public static boolean enableSelfRescue = false;
public static boolean enableLoggingTask = false; public static boolean enableLoggingTask = false;
public static boolean enableReviveTask = false; public static boolean enableReviveTask = false;
public static boolean enableLocateTask = false; public static boolean enableLocateTask = false;
@@ -47,6 +52,7 @@ public class Config {
@SubscribeEvent @SubscribeEvent
static void onLoad(final ModConfigEvent event) { static void onLoad(final ModConfigEvent event) {
enableSelfRescue = SELF_RESCUE.get();
enableLoggingTask = ENABLE_LOGGING.get(); enableLoggingTask = ENABLE_LOGGING.get();
enableReviveTask = ENABLE_REVIVE.get(); enableReviveTask = ENABLE_REVIVE.get();
enableLocateTask = ENABLE_LOCATE.get(); enableLocateTask = ENABLE_LOCATE.get();

View File

@@ -53,7 +53,7 @@ public class DestoryBlockBehavior extends Behavior<EntityMaid> {
BlockTargetMemory blockTargetMemory = MemoryUtil.getDestroyTargetMemory(maid); BlockTargetMemory blockTargetMemory = MemoryUtil.getDestroyTargetMemory(maid);
if (blockTargetMemory != null) { if (blockTargetMemory != null) {
blockPosSet = new ArrayList<>(blockTargetMemory.getBlockPosSet()); blockPosSet = new ArrayList<>(blockTargetMemory.getBlockPosSet());
blockPosSet.sort((o1, o2) -> (int) (o1.distSqr(maid.blockPosition()) - o2.distSqr(maid.blockPosition()))); blockPosSet.sort((o1, o2) -> (int) (o1.distSqr(maid.blockPosition().above()) - o2.distSqr(maid.blockPosition().above())));
} }
index = 0; index = 0;
task = (IMaidBlockDestroyTask) maid.getTask(); task = (IMaidBlockDestroyTask) maid.getTask();
@@ -65,6 +65,8 @@ public class DestoryBlockBehavior extends Behavior<EntityMaid> {
@Override @Override
protected boolean canStillUse(ServerLevel p_22545_, EntityMaid p_22546_, long p_22547_) { protected boolean canStillUse(ServerLevel p_22545_, EntityMaid p_22546_, long p_22547_) {
if (MemoryUtil.getCurrent(p_22546_) != CurrentWork.DESTROY && MemoryUtil.getCurrent(p_22546_) != CurrentWork.BLOCKUP_DESTROY)
return false;
return (blockPosSet != null && index < blockPosSet.size()) || targetPos != null; return (blockPosSet != null && index < blockPosSet.size()) || targetPos != null;
} }

View File

@@ -53,6 +53,7 @@ public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask {
protected boolean shouldMoveTo(@NotNull ServerLevel serverLevel, @NotNull EntityMaid entityMaid, @NotNull BlockPos blockPos) { protected boolean shouldMoveTo(@NotNull ServerLevel serverLevel, @NotNull EntityMaid entityMaid, @NotNull BlockPos blockPos) {
if (!task.shouldDestroyBlock(entityMaid, blockPos.immutable())) return false; if (!task.shouldDestroyBlock(entityMaid, blockPos.immutable())) return false;
targetPos = blockPos.immutable(); targetPos = blockPos.immutable();
BlockPos startPos = entityMaid.blockPosition();
if (blockPos instanceof BlockPos.MutableBlockPos mb) { if (blockPos instanceof BlockPos.MutableBlockPos mb) {
for (int dx = 0; dx < task.reachDistance(); dx = dx <= 0 ? 1 - dx : -dx) { for (int dx = 0; dx < task.reachDistance(); dx = dx <= 0 ? 1 - dx : -dx) {
for (int dy = 0; dy < task.reachDistance(); dy = dy <= 0 ? 1 - dy : -dy) { for (int dy = 0; dy < task.reachDistance(); dy = dy <= 0 ? 1 - dy : -dy) {
@@ -61,6 +62,9 @@ public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask {
if (!PosUtils.isSafePos(serverLevel, pos)) continue; if (!PosUtils.isSafePos(serverLevel, pos)) continue;
if (!Conditions.isGlobalValidTarget(entityMaid, pos, targetPos)) continue; if (!Conditions.isGlobalValidTarget(entityMaid, pos, targetPos)) continue;
if (pos.distSqr(targetPos) > task.reachDistance() * task.reachDistance()) continue; if (pos.distSqr(targetPos) > task.reachDistance() * task.reachDistance()) continue;
if (Math.abs(startPos.getY() - pos.getY()) >= task.reachDistance()) continue;
if (Math.abs(startPos.getX() - pos.getX()) >= task.reachDistance()) continue;
if (Math.abs(startPos.getZ() - pos.getZ()) >= task.reachDistance()) continue;
if (pos.equals(entityMaid.blockPosition()) || (entityMaid.isWithinRestriction(pos) && pathfindingBFS.canPathReach(pos))) { if (pos.equals(entityMaid.blockPosition()) || (entityMaid.isWithinRestriction(pos) && pathfindingBFS.canPathReach(pos))) {
blockPosSet = task.toDestroyFromStanding(entityMaid, targetPos, pos); blockPosSet = task.toDestroyFromStanding(entityMaid, targetPos, pos);
if (blockPosSet != null) { if (blockPosSet != null) {
@@ -81,9 +85,9 @@ public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask {
protected @NotNull MaidPathFindingBFS getOrCreateArrivalMap(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) { protected @NotNull MaidPathFindingBFS getOrCreateArrivalMap(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) {
if (this.pathfindingBFS == null) if (this.pathfindingBFS == null)
if (maid.hasRestriction()) if (maid.hasRestriction())
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, (int) maid.getRestrictRadius(), 7); this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, (int) maid.getRestrictRadius() + 1, task.reachDistance() + 2);
else else
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 7, 7); this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, task.reachDistance() + 1, task.reachDistance() + 2);
return this.pathfindingBFS; return this.pathfindingBFS;
} }

View File

@@ -1,7 +1,6 @@
package studio.fantasyit.maid_useful_task.behavior.common; package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task.MaidCheckRateTask;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid; import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.MaidPathFindingBFS; import com.github.tartaricacid.touhoulittlemaid.entity.passive.MaidPathFindingBFS;
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities; import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;
@@ -41,9 +40,11 @@ abstract public class MaidCenterMoveToBlockTask extends Behavior<EntityMaid> {
this.verticalSearchRange = verticalSearchRange; this.verticalSearchRange = verticalSearchRange;
this.searchRange = defaultSearchRange; this.searchRange = defaultSearchRange;
} }
public void setSearchRange(int searchRange) { public void setSearchRange(int searchRange) {
this.searchRange = searchRange; this.searchRange = searchRange;
} }
protected final void searchForDestination(ServerLevel worldIn, EntityMaid maid) { protected final void searchForDestination(ServerLevel worldIn, EntityMaid maid) {
MaidPathFindingBFS pathFinding = this.getOrCreateArrivalMap(worldIn, maid); MaidPathFindingBFS pathFinding = this.getOrCreateArrivalMap(worldIn, maid);
BlockPos centrePos = this.getWorkSearchPos(maid); BlockPos centrePos = this.getWorkSearchPos(maid);
@@ -73,7 +74,7 @@ abstract public class MaidCenterMoveToBlockTask extends Behavior<EntityMaid> {
} }
protected MaidPathFindingBFS getOrCreateArrivalMap(ServerLevel worldIn, EntityMaid maid) { protected MaidPathFindingBFS getOrCreateArrivalMap(ServerLevel worldIn, EntityMaid maid) {
return new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid); return new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, maid.searchRadius(), 9);
} }
private BlockPos getWorkSearchPos(EntityMaid maid) { private BlockPos getWorkSearchPos(EntityMaid maid) {

View File

@@ -0,0 +1,80 @@
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.ai.behavior.Behavior;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.VoxelShape;
import studio.fantasyit.maid_useful_task.Config;
import studio.fantasyit.maid_useful_task.memory.CurrentWork;
import studio.fantasyit.maid_useful_task.task.IMaidBlockDestroyTask;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class MaidSelfRescueBehavior extends Behavior<EntityMaid> {
public MaidSelfRescueBehavior() {
super(Map.of(), 600);
}
boolean started = false;
private static boolean isNotSafeAndCanTryToDestroy(ServerLevel level, EntityMaid maid, BlockPos pos, IMaidBlockDestroyTask task) {
BlockState bs = level.getBlockState(pos);
if (bs.isAir()) return false;
VoxelShape collision = bs.getCollisionShape(level, pos);
if (collision.isEmpty()) return false;
return maid.getBoundingBox().intersects(collision.bounds().move(pos)) && bs.isSuffocating(level, pos) && task.mayDestroy(maid, pos);
}
@Override
protected boolean checkExtraStartConditions(ServerLevel level, EntityMaid maid) {
if (!Config.enableSelfRescue) return false;
if (!(maid.getTask() instanceof IMaidBlockDestroyTask ibdt)) return false;
if (isNotSafeAndCanTryToDestroy(level, maid, maid.blockPosition(), ibdt) || isNotSafeAndCanTryToDestroy(level, maid, maid.blockPosition().above(), ibdt))
return true;
return false;
}
@Override
protected boolean canStillUse(ServerLevel p_22545_, EntityMaid p_22546_, long p_22547_) {
return started && checkExtraStartConditions(p_22545_, p_22546_);
}
@Override
protected void start(ServerLevel p_22540_, EntityMaid maid, long p_22542_) {
started = false;
if (MemoryUtil.getCurrent(maid) == CurrentWork.DESTROY) {
//如果执行中破坏任务,则立刻停止。用以清空相关状态
MemoryUtil.setCurrent(maid, CurrentWork.IDLE);
return;
}
//等待上一个任务结束
if (MemoryUtil.getDestroyTargetMemory(maid) != null)
return;
if (!(maid.getTask() instanceof IMaidBlockDestroyTask task))
return;
started = true;
List<BlockPos> list = new ArrayList<>();
if (isNotSafeAndCanTryToDestroy(p_22540_, maid, maid.blockPosition(), task)) {
list.add(maid.blockPosition());
}
if (isNotSafeAndCanTryToDestroy(p_22540_, maid, maid.blockPosition().above(), task)) {
list.add(maid.blockPosition().above());
}
MemoryUtil.setDestroyTargetMemory(maid, list);
MemoryUtil.setTarget(maid, maid.blockPosition(), 0.5f);
MemoryUtil.setCurrent(maid, CurrentWork.DESTROY);
}
@Override
protected void stop(ServerLevel p_22548_, EntityMaid p_22549_, long p_22550_) {
MemoryUtil.clearTarget(p_22549_);
MemoryUtil.setCurrent(p_22549_, CurrentWork.IDLE);
}
}

View File

@@ -89,9 +89,9 @@ public class PlaceBlockMoveBehavior extends MaidCenterMoveToBlockTask {
protected @NotNull MaidPathFindingBFS getOrCreateArrivalMap(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) { protected @NotNull MaidPathFindingBFS getOrCreateArrivalMap(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) {
if (this.pathfindingBFS == null) if (this.pathfindingBFS == null)
if (maid.hasRestriction()) if (maid.hasRestriction())
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, (int) maid.getRestrictRadius(), 7); this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, (int) maid.getRestrictRadius(), 9);
else else
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 7, 7); this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 7, 9);
return this.pathfindingBFS; return this.pathfindingBFS;
} }

View File

@@ -55,7 +55,7 @@ public interface IMaidBlockUpTask {
} }
}; };
CenterOffsetBlockPosSet notAvailable = new CenterOffsetBlockPosSet(scanRange, scanRange + maxHeight / 2 + 1, scanRange, center.getX(), center.getY() + maxHeight / 2, center.getZ()); CenterOffsetBlockPosSet notAvailable = new CenterOffsetBlockPosSet(scanRange, scanRange + maxHeight / 2 + 1, scanRange, center.getX(), center.getY() + maxHeight / 2, center.getZ());
MaidPathFindingBFS pathFindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), level, maid, 7, scanRange); MaidPathFindingBFS pathFindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), level, maid, 7, scanRange+2);
for (int dx = 0; dx < scanRange; dx = dx <= 0 ? 1 - dx : -dx) { for (int dx = 0; dx < scanRange; dx = dx <= 0 ? 1 - dx : -dx) {
for (int dz = 0; dz < scanRange; dz = dz <= 0 ? 1 - dz : -dz) { for (int dz = 0; dz < scanRange; dz = dz <= 0 ? 1 - dz : -dz) {
//计算地面的位置 //计算地面的位置

View File

@@ -184,11 +184,22 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD
protected boolean isValidNatureTree(EntityMaid maid, BlockPos startPos) { protected boolean isValidNatureTree(EntityMaid maid, BlockPos startPos) {
return isValidNatureTree(maid, startPos, new HashSet<>(), 0); HashSet<BlockPos> vis = new HashSet<>();
BlockValidationMemory validationMemory = MemoryUtil.getBlockValidationMemory(maid);
boolean validNatureTree = isValidNatureTree(maid, startPos, vis, 0, validationMemory);
for (BlockPos pos : vis) {
BlockState blockState = maid.level().getBlockState(pos);
if (!blockState.is(BlockTags.LEAVES) && !blockState.is(BlockTags.LOGS))
continue;
if (validNatureTree)
validationMemory.setValid(pos);
else
validationMemory.setInvalid(pos);
}
return validNatureTree;
} }
protected boolean isValidNatureTree(EntityMaid maid, BlockPos startPos, Set<BlockPos> visited, int depth) { protected boolean isValidNatureTree(EntityMaid maid, BlockPos startPos, Set<BlockPos> visited, int depth, BlockValidationMemory validationMemory) {
BlockValidationMemory validationMemory = MemoryUtil.getBlockValidationMemory(maid);
if (validationMemory.hasRecord(startPos)) if (validationMemory.hasRecord(startPos))
return validationMemory.isValid(startPos, false); return validationMemory.isValid(startPos, false);
if (visited.contains(startPos)) if (visited.contains(startPos))
@@ -205,7 +216,7 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD
if (blockState.is(BlockTags.LEAVES) && blockState.hasProperty(LeavesBlock.PERSISTENT) && !blockState.getValue(LeavesBlock.PERSISTENT)) { if (blockState.is(BlockTags.LEAVES) && blockState.hasProperty(LeavesBlock.PERSISTENT) && !blockState.getValue(LeavesBlock.PERSISTENT)) {
valid = true; valid = true;
} }
if (blockState.is(BlockTags.LOGS) && isValidNatureTree(maid, offset, visited, depth + 1)) { if (blockState.is(BlockTags.LOGS) && isValidNatureTree(maid, offset, visited, depth + 1, validationMemory)) {
valid = true; valid = true;
} }
} }
@@ -221,6 +232,7 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD
@Override @Override
public List<Pair<Integer, BehaviorControl<? super EntityMaid>>> createBrainTasks(EntityMaid entityMaid) { public List<Pair<Integer, BehaviorControl<? super EntityMaid>>> createBrainTasks(EntityMaid entityMaid) {
ArrayList<Pair<Integer, BehaviorControl<? super EntityMaid>>> list = new ArrayList<>(); ArrayList<Pair<Integer, BehaviorControl<? super EntityMaid>>> list = new ArrayList<>();
list.add(Pair.of(0, new MaidSelfRescueBehavior()));
list.add(Pair.of(1, new DestoryBlockBehavior())); list.add(Pair.of(1, new DestoryBlockBehavior()));
list.add(Pair.of(1, new DestoryBlockMoveBehavior())); list.add(Pair.of(1, new DestoryBlockMoveBehavior()));