From 5eaf45a11301c5ed170bce9ea312267f9f59797f Mon Sep 17 00:00:00 2001 From: xypp <2952795729@qq.com> Date: Sun, 27 Apr 2025 22:57:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AF=BB=E8=B7=AF=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=A0=8D=E7=BD=9A=E7=9B=AE=E6=A0=87=E9=80=89?= =?UTF-8?q?=E6=8B=A9=20=E4=BC=98=E5=8C=96=E8=A1=8C=E4=B8=BA=E9=A1=BA?= =?UTF-8?q?=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maid_useful_task/UsefulTaskExtension.java | 3 +- .../behavior/BlockUpDestroyBehavior.java | 10 +- .../behavior/BlockUpPlaceBehavior.java | 16 ++- .../behavior/BlockUpScheduleBehavior.java | 29 +++-- .../behavior/DestoryBlockBehavior.java | 16 ++- .../behavior/DestoryBlockMoveBehavior.java | 24 ++-- .../behavior/MaidCenterMoveToBlockTask.java | 30 +++-- .../behavior/PlaceBlockBehavior.java | 7 +- .../behavior/PlaceBlockMoveBehavior.java | 22 ++-- .../UpdateValidationMemoryBehavior.java | 24 ++++ .../memory/BlockValidationMemory.java | 75 +++++++++++++ .../maid_useful_task/memory/CurrentWork.java | 10 ++ .../mixin/MaidCheckPickupItem.java | 4 +- .../mixin/MaidMoveControlMixin.java | 11 +- .../mixin/MaidRunOneMixin.java | 5 +- .../registry/MemoryModuleRegistry.java | 10 +- .../task/IMaidBlockUpTask.java | 105 +++++++++++------- .../maid_useful_task/task/MaidTreeTask.java | 82 ++++++++++++-- .../maid_useful_task/util/Conditions.java | 8 +- .../maid_useful_task/util/MaidUtils.java | 24 +++- .../maid_useful_task/util/MemoryUtil.java | 24 ++-- .../util/WrappedMaidFakePlayer.java | 31 ++++++ .../resources/META-INF/accesstransformer.cfg | 3 +- 23 files changed, 443 insertions(+), 130 deletions(-) create mode 100644 src/main/java/studio/fantasyit/maid_useful_task/behavior/UpdateValidationMemoryBehavior.java create mode 100644 src/main/java/studio/fantasyit/maid_useful_task/memory/BlockValidationMemory.java create mode 100644 src/main/java/studio/fantasyit/maid_useful_task/memory/CurrentWork.java diff --git a/src/main/java/studio/fantasyit/maid_useful_task/UsefulTaskExtension.java b/src/main/java/studio/fantasyit/maid_useful_task/UsefulTaskExtension.java index 54ec691..c8bd403 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/UsefulTaskExtension.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/UsefulTaskExtension.java @@ -28,7 +28,8 @@ public class UsefulTaskExtension implements ILittleMaid { MemoryModuleRegistry.DESTROY_TARGET.get(), MemoryModuleRegistry.PLACE_TARGET.get(), MemoryModuleRegistry.BLOCK_UP_TARGET.get(), - MemoryModuleRegistry.RATE_LIMIT_TOKEN.get() + MemoryModuleRegistry.BLOCK_VALIDATION.get(), + MemoryModuleRegistry.CURRENT_WORK.get() ); } }); diff --git a/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpDestroyBehavior.java b/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpDestroyBehavior.java index 32723d7..0a5c28e 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpDestroyBehavior.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpDestroyBehavior.java @@ -9,6 +9,7 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType; import net.minecraft.world.entity.ai.memory.MemoryStatus; import net.minecraft.world.level.block.state.BlockState; import studio.fantasyit.maid_useful_task.memory.BlockUpContext; +import studio.fantasyit.maid_useful_task.memory.CurrentWork; import studio.fantasyit.maid_useful_task.task.IMaidBlockUpTask; import studio.fantasyit.maid_useful_task.util.Conditions; import studio.fantasyit.maid_useful_task.util.MaidUtils; @@ -28,11 +29,12 @@ public class BlockUpDestroyBehavior extends Behavior { } public BlockUpDestroyBehavior() { - super(Map.of(),200); + super(Map.of(),500); } @Override protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid p_22539_) { + if(!Conditions.isCurrent(p_22539_, CurrentWork.BLOCKUP_DOWN)) return false; if (!MemoryUtil.getBlockUpContext(p_22539_).hasTarget()) return false; if (MemoryUtil.getBlockUpContext(p_22539_).getStatus() != BlockUpContext.STATUS.DOWN) return false; return Conditions.hasReachedValidTargetOrReset(p_22539_, 0.8f); @@ -63,8 +65,7 @@ public class BlockUpDestroyBehavior extends Behavior { BlockPos targetPos = maid.blockPosition().below(); maid.swing(InteractionHand.MAIN_HAND); MemoryUtil.setLookAt(maid, targetPos); - BlockState targetBlockState = level.getBlockState(targetPos); - float speed = fakePlayer.getMainHandItem().getDestroySpeed(targetBlockState) / fakePlayer.getDigSpeed(targetBlockState, targetPos) / 30; + float speed = MaidUtils.getDestroyProgressDelta(maid, targetPos); progress += speed; if (progress >= 1f) { MaidUtils.destroyBlock(maid, targetPos); @@ -75,7 +76,8 @@ public class BlockUpDestroyBehavior extends Behavior { @Override protected void stop(ServerLevel p_22548_, EntityMaid maid, long p_22550_) { super.stop(p_22548_, maid, p_22550_); - context.setStatus(BlockUpContext.STATUS.IDLE); + context.clearStartTarget(); MemoryUtil.clearTarget(maid); + MemoryUtil.setCurrent(maid, CurrentWork.IDLE); } } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpPlaceBehavior.java b/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpPlaceBehavior.java index 5a7012f..e0fdf7d 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpPlaceBehavior.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpPlaceBehavior.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import studio.fantasyit.maid_useful_task.memory.BlockUpContext; +import studio.fantasyit.maid_useful_task.memory.CurrentWork; import studio.fantasyit.maid_useful_task.task.IMaidBlockUpTask; import studio.fantasyit.maid_useful_task.util.Conditions; import studio.fantasyit.maid_useful_task.util.MaidUtils; @@ -34,6 +35,7 @@ public class BlockUpPlaceBehavior extends Behavior { @Override protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid p_22539_) { + if (!Conditions.isCurrent(p_22539_, CurrentWork.BLOCKUP_UP)) return false; if (!MemoryUtil.getBlockUpContext(p_22539_).hasTarget()) return false; if (MemoryUtil.getBlockUpContext(p_22539_).getStatus() != BlockUpContext.STATUS.UP) return false; return Conditions.hasReachedValidTargetOrReset(p_22539_, 0.8f); @@ -42,7 +44,7 @@ public class BlockUpPlaceBehavior extends Behavior { @Override protected boolean canStillUse(ServerLevel p_22545_, EntityMaid maid, long p_22547_) { if (MemoryUtil.getBlockUpContext(maid).getStatus() != BlockUpContext.STATUS.UP) return false; - if (!p_22545_.getBlockState(maid.blockPosition().above().above()).isAir()) return false; + if (maid.onGround() && !p_22545_.getBlockState(maid.blockPosition().above().above()).isAir()) return false; return !(maid.blockPosition().equals(context.getTargetPos()) && maid.onGround()); } @@ -99,10 +101,14 @@ public class BlockUpPlaceBehavior extends Behavior { protected void stop(ServerLevel p_22548_, EntityMaid maid, long p_22550_) { super.stop(p_22548_, maid, p_22550_); context.setStatus(BlockUpContext.STATUS.IDLE); - if (!maid.blockPosition().equals(context.getTargetPos())) { - BlockPos startPos = context.getStartPos(); - BlockPos blockPos = maid.blockPosition(); - context.setStartTarget(new BlockPos(blockPos.getX(), startPos.getY(), blockPos.getZ()), blockPos); + if (context.hasTarget()) { + if (!maid.blockPosition().equals(context.getTargetPos())) { + BlockPos startPos = context.getStartPos(); + BlockPos blockPos = maid.blockPosition(); + context.setStartTarget(new BlockPos(blockPos.getX(), startPos.getY(), blockPos.getZ()), blockPos); + } + + MemoryUtil.setCurrent(maid, CurrentWork.BLOCKUP_DESTROY); } MemoryUtil.clearTarget(maid); } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpScheduleBehavior.java b/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpScheduleBehavior.java index c4a9f2c..9ce3bbc 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpScheduleBehavior.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/behavior/BlockUpScheduleBehavior.java @@ -1,6 +1,5 @@ package studio.fantasyit.maid_useful_task.behavior; -import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task.MaidCheckRateTask; import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid; import com.github.tartaricacid.touhoulittlemaid.init.InitEntities; import com.google.common.collect.ImmutableMap; @@ -13,12 +12,11 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType; import net.minecraft.world.entity.ai.memory.MemoryStatus; import oshi.util.tuples.Pair; import studio.fantasyit.maid_useful_task.memory.BlockUpContext; -import studio.fantasyit.maid_useful_task.memory.TaskRateLimitToken; +import studio.fantasyit.maid_useful_task.memory.CurrentWork; import studio.fantasyit.maid_useful_task.task.IMaidBlockUpTask; +import studio.fantasyit.maid_useful_task.util.MaidUtils; import studio.fantasyit.maid_useful_task.util.MemoryUtil; -import java.util.Map; - public class BlockUpScheduleBehavior extends Behavior { public BlockUpScheduleBehavior() { super(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, InitEntities.TARGET_POS.get(), MemoryStatus.VALUE_ABSENT)); @@ -26,7 +24,10 @@ public class BlockUpScheduleBehavior extends Behavior { @Override protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid p_22539_) { - if (MemoryUtil.getRateLimitToken(p_22539_).isFor(TaskRateLimitToken.Level.L3)) { + if (!switch (MemoryUtil.getCurrent(p_22539_)) { + case BLOCKUP_UP, BLOCKUP_DOWN, BLOCKUP_DESTROY, IDLE -> true; + default -> false; + }) { return false; } return super.checkExtraStartConditions(p_22538_, p_22539_); @@ -37,23 +38,33 @@ public class BlockUpScheduleBehavior extends Behavior { BlockUpContext context = MemoryUtil.getBlockUpContext(maid); IMaidBlockUpTask task = (IMaidBlockUpTask) maid.getTask(); if (context.hasTarget()) { - if (context.getStatus() != BlockUpContext.STATUS.IDLE && MemoryUtil.getTargetPos(maid) == null) { + if (context.getStatus() != BlockUpContext.STATUS.UP && !context.isOnLine(maid.blockPosition())) { context.clearStartTarget(); + MemoryUtil.setCurrent(maid, CurrentWork.IDLE); + } else if (context.getStatus() != BlockUpContext.STATUS.IDLE && MemoryUtil.getTargetPos(maid) == null) { + if (context.getStatus() == BlockUpContext.STATUS.DOWN) { + MemoryUtil.setTarget(maid, context.getTargetPos(), 0.5f); + MemoryUtil.setCurrent(maid, CurrentWork.BLOCKUP_DOWN); + } else { + MemoryUtil.setTarget(maid, context.getStartPos(), 0.5f); + MemoryUtil.setCurrent(maid, CurrentWork.BLOCKUP_UP); + } } else if (!context.isOnLine(maid.blockPosition()) || context.getStartPos().equals(context.getTargetPos())) { context.clearStartTarget(); - } else if (context.getStatus() == BlockUpContext.STATUS.IDLE && !context.isTarget(maid.blockPosition()) && context.isOnLine(maid.blockPosition())) { - context.setStartTarget(context.getStartPos(), maid.blockPosition()); + MemoryUtil.setCurrent(maid, CurrentWork.IDLE); } else if (context.getStatus() == BlockUpContext.STATUS.IDLE && !task.stillValid(maid, maid.blockPosition())) { maid.getBrain().setMemory(InitEntities.TARGET_POS.get(), new BlockPosTracker(context.getTargetPos())); context.setStatus(BlockUpContext.STATUS.DOWN); + MemoryUtil.setCurrent(maid, CurrentWork.BLOCKUP_DOWN); } } else { - Pair targetPosBlockUp = task.findTargetPosBlockUp(maid, maid.blockPosition()); + Pair targetPosBlockUp = task.findTargetPosBlockUp(maid, MaidUtils.getMaidRestrictCenter(maid), task.countMaxUsableBlockItems(maid)); if (targetPosBlockUp != null) { context.setStartTarget(targetPosBlockUp.getA(), targetPosBlockUp.getB()); maid.getBrain().setMemory(InitEntities.TARGET_POS.get(), new BlockPosTracker(targetPosBlockUp.getA())); BehaviorUtils.setWalkAndLookTargetMemories(maid, targetPosBlockUp.getA(), 0.5f, 0); context.setStatus(BlockUpContext.STATUS.UP); + MemoryUtil.setCurrent(maid, CurrentWork.BLOCKUP_UP); } } } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/behavior/DestoryBlockBehavior.java b/src/main/java/studio/fantasyit/maid_useful_task/behavior/DestoryBlockBehavior.java index 444afbc..36eb6a5 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/behavior/DestoryBlockBehavior.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/behavior/DestoryBlockBehavior.java @@ -10,9 +10,11 @@ import net.minecraft.world.entity.ai.memory.MemoryStatus; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; import studio.fantasyit.maid_useful_task.memory.BlockTargetMemory; +import studio.fantasyit.maid_useful_task.memory.CurrentWork; import studio.fantasyit.maid_useful_task.registry.MemoryModuleRegistry; import studio.fantasyit.maid_useful_task.task.IMaidBlockDestroyTask; import studio.fantasyit.maid_useful_task.util.Conditions; +import studio.fantasyit.maid_useful_task.util.MaidUtils; import studio.fantasyit.maid_useful_task.util.MemoryUtil; import studio.fantasyit.maid_useful_task.util.WrappedMaidFakePlayer; @@ -32,7 +34,9 @@ public class DestoryBlockBehavior extends Behavior { @Override protected boolean checkExtraStartConditions(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) { - return Conditions.hasReachedValidTargetOrReset(maid,1); + if (!Conditions.isCurrent(maid, CurrentWork.DESTROY) && !Conditions.isCurrent(maid, CurrentWork.BLOCKUP_DESTROY)) + return false; + return Conditions.hasReachedValidTargetOrReset(maid, 1); } @@ -48,7 +52,7 @@ public class DestoryBlockBehavior extends Behavior { super.start(p_22540_, maid, p_22542_); BlockTargetMemory blockTargetMemory = MemoryUtil.getDestroyTargetMemory(maid); 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()))); } index = 0; @@ -87,14 +91,13 @@ public class DestoryBlockBehavior extends Behavior { } private void tickDestroyProgress(EntityMaid maid) { - float speed = fakePlayer.getMainHandItem().getDestroySpeed(targetBlockState) / fakePlayer.getDigSpeed(targetBlockState, targetPos) / 30; + float speed = MaidUtils.getDestroyProgressDelta(maid, targetPos); MemoryUtil.setLookAt(maid, targetPos); - if (task.availableToGetDrop(maid, fakePlayer, targetPos, targetBlockState)) { + if (speed != 0.0f && task.availableToGetDrop(maid, fakePlayer, targetPos, targetBlockState)) { maid.swing(InteractionHand.MAIN_HAND); destroyProgress += speed; if (destroyProgress >= 1f) { - maid.getMainHandItem().hurt(1, maid.getRandom(), fakePlayer); - task.tryDestroyBlock(maid,targetPos); + task.tryDestroyBlock(maid, targetPos); destroyProgress = 0f; targetPos = null; targetBlockState = null; @@ -110,6 +113,7 @@ public class DestoryBlockBehavior extends Behavior { super.stop(p_22548_, p_22549_, p_22550_); MemoryUtil.clearDestroyTargetMemory(p_22549_); MemoryUtil.clearTarget(p_22549_); + MemoryUtil.setCurrent(p_22549_, CurrentWork.IDLE); } @Override diff --git a/src/main/java/studio/fantasyit/maid_useful_task/behavior/DestoryBlockMoveBehavior.java b/src/main/java/studio/fantasyit/maid_useful_task/behavior/DestoryBlockMoveBehavior.java index 9d8260d..3921732 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/behavior/DestoryBlockMoveBehavior.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/behavior/DestoryBlockMoveBehavior.java @@ -1,13 +1,12 @@ package studio.fantasyit.maid_useful_task.behavior; -import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task.MaidMoveToBlockTask; import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid; import com.github.tartaricacid.touhoulittlemaid.entity.passive.MaidPathFindingBFS; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import studio.fantasyit.maid_useful_task.memory.TaskRateLimitToken; +import studio.fantasyit.maid_useful_task.memory.CurrentWork; import studio.fantasyit.maid_useful_task.task.IMaidBlockDestroyTask; import studio.fantasyit.maid_useful_task.util.Conditions; import studio.fantasyit.maid_useful_task.util.MemoryUtil; @@ -26,16 +25,17 @@ public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask { @Override - protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid p_22539_) { - if (MemoryUtil.getRateLimitToken(p_22539_).isFor(TaskRateLimitToken.Level.L1)) { + protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid maid) { + if (!Conditions.isCurrent(maid, CurrentWork.IDLE) && !Conditions.isCurrent(maid, CurrentWork.BLOCKUP_DESTROY)) return false; - } - return super.checkExtraStartConditions(p_22538_, p_22539_); + return super.checkExtraStartConditions(p_22538_, maid); } @Override protected void start(@NotNull ServerLevel p_22540_, @NotNull EntityMaid maid, long p_22542_) { super.start(p_22540_, maid, p_22542_); + if (maid.hasRestriction()) + this.setSearchRange((int) maid.getRestrictRadius()); task = (IMaidBlockDestroyTask) maid.getTask(); task.tryTakeOutTool(maid); searchForDestination(p_22540_, maid); @@ -43,11 +43,14 @@ public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask { if (target != null && blockPosSet != null) { blockPosSet.addAll(task.getTryDestroyBlockListBesidesStart(targetPos, target, maid)); MemoryUtil.setDestroyTargetMemory(maid, blockPosSet); + if (Conditions.isCurrent(maid, CurrentWork.IDLE)) + MemoryUtil.setCurrent(maid, CurrentWork.DESTROY); } } + @Override protected boolean shouldMoveTo(@NotNull ServerLevel serverLevel, @NotNull EntityMaid entityMaid, @NotNull BlockPos blockPos) { - if (!task.shouldDestroyBlock(entityMaid, blockPos)) return false; + if (!task.shouldDestroyBlock(entityMaid, blockPos.immutable())) return false; targetPos = blockPos.immutable(); if (blockPos instanceof BlockPos.MutableBlockPos mb) { for (int dx = 0; dx < task.reachDistance(); dx = dx <= 0 ? 1 - dx : -dx) { @@ -75,7 +78,10 @@ public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask { @Override protected @NotNull MaidPathFindingBFS getOrCreateArrivalMap(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) { if (this.pathfindingBFS == null) - this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 14); + if(maid.hasRestriction()) + this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 14, (int) maid.getRestrictRadius()); + else + this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 14); return this.pathfindingBFS; } @@ -84,4 +90,4 @@ public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask { super.clearCurrentArrivalMap(pathFinding); this.pathfindingBFS = null; } -} +} \ No newline at end of file diff --git a/src/main/java/studio/fantasyit/maid_useful_task/behavior/MaidCenterMoveToBlockTask.java b/src/main/java/studio/fantasyit/maid_useful_task/behavior/MaidCenterMoveToBlockTask.java index 9734c96..06e8dc9 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/behavior/MaidCenterMoveToBlockTask.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/behavior/MaidCenterMoveToBlockTask.java @@ -13,6 +13,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorUtils; import net.minecraft.world.entity.ai.behavior.BlockPosTracker; import net.minecraft.world.entity.ai.memory.MemoryModuleType; import net.minecraft.world.entity.ai.memory.MemoryStatus; +import studio.fantasyit.maid_useful_task.util.MaidUtils; /** * From https://github.com/TartaricAcid/TouhouLittleMaid @@ -23,7 +24,7 @@ abstract public class MaidCenterMoveToBlockTask extends Behavior { private static final int MAX_DELAY_TIME = 120; private final float movementSpeed; private final int verticalSearchRange; - private final int searchRange; + private int searchRange; protected int verticalSearchStart; public MaidCenterMoveToBlockTask(float movementSpeed) { @@ -33,26 +34,29 @@ abstract public class MaidCenterMoveToBlockTask extends Behavior { public MaidCenterMoveToBlockTask(float movementSpeed, int verticalSearchRange) { this(movementSpeed, verticalSearchRange, 7); } - public MaidCenterMoveToBlockTask(float movementSpeed, int verticalSearchRange,int searchRange) { + + public MaidCenterMoveToBlockTask(float movementSpeed, int verticalSearchRange, int defaultSearchRange) { super(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, InitEntities.TARGET_POS.get(), MemoryStatus.VALUE_ABSENT)); this.movementSpeed = movementSpeed; this.verticalSearchRange = verticalSearchRange; - this.searchRange = searchRange; + this.searchRange = defaultSearchRange; + } + public void setSearchRange(int searchRange) { + this.searchRange = searchRange; } - protected final void searchForDestination(ServerLevel worldIn, EntityMaid maid) { MaidPathFindingBFS pathFinding = this.getOrCreateArrivalMap(worldIn, maid); BlockPos centrePos = this.getWorkSearchPos(maid); BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); - for(int y = this.verticalSearchStart; y <= this.verticalSearchRange; y = y > 0 ? -y : 1 - y) { - for(int i = 0; i < searchRange; ++i) { - for(int x = 0; x <= i; x = x > 0 ? -x : 1 - x) { - for(int z = x < i && x > -i ? i : 0; z <= i; z = z > 0 ? -z : 1 - z) { + for (int y = this.verticalSearchStart; y <= this.verticalSearchRange; y = y > 0 ? -y : 1 - y) { + for (int i = 0; i < searchRange; ++i) { + for (int x = 0; x <= i; x = x > 0 ? -x : 1 - x) { + for (int z = x < i && x > -i ? i : 0; z <= i; z = z > 0 ? -z : 1 - z) { mutableBlockPos.setWithOffset(centrePos, x, y - 1, z); - if (maid.isWithinRestriction(mutableBlockPos) && this.shouldMoveTo(worldIn, maid, mutableBlockPos) && this.checkPathReach(maid, pathFinding, mutableBlockPos) && this.checkOwnerPos(maid, mutableBlockPos)) { + if (this.shouldMoveTo(worldIn, maid, mutableBlockPos) && this.checkPathReach(maid, pathFinding, mutableBlockPos) && this.checkOwnerPos(maid, mutableBlockPos)) { BehaviorUtils.setWalkAndLookTargetMemories(maid, mutableBlockPos, this.movementSpeed, 0); - maid.getBrain().setMemory((MemoryModuleType)InitEntities.TARGET_POS.get(), new BlockPosTracker(mutableBlockPos)); + maid.getBrain().setMemory((MemoryModuleType) InitEntities.TARGET_POS.get(), new BlockPosTracker(mutableBlockPos)); this.clearCurrentArrivalMap(pathFinding); return; } @@ -73,7 +77,7 @@ abstract public class MaidCenterMoveToBlockTask extends Behavior { } private BlockPos getWorkSearchPos(EntityMaid maid) { - return maid.blockPosition(); + return MaidUtils.getMaidRestrictCenter(maid); } private boolean checkOwnerPos(EntityMaid maid, BlockPos mutableBlockPos) { @@ -86,7 +90,9 @@ abstract public class MaidCenterMoveToBlockTask extends Behavior { protected abstract boolean shouldMoveTo(ServerLevel var1, EntityMaid var2, BlockPos var3); - /** @deprecated */ + /** + * @deprecated + */ @Deprecated( forRemoval = true ) diff --git a/src/main/java/studio/fantasyit/maid_useful_task/behavior/PlaceBlockBehavior.java b/src/main/java/studio/fantasyit/maid_useful_task/behavior/PlaceBlockBehavior.java index b356c57..15bdd0a 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/behavior/PlaceBlockBehavior.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/behavior/PlaceBlockBehavior.java @@ -7,6 +7,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.ai.behavior.Behavior; import net.minecraft.world.entity.ai.memory.MemoryStatus; +import studio.fantasyit.maid_useful_task.memory.CurrentWork; import studio.fantasyit.maid_useful_task.registry.MemoryModuleRegistry; import studio.fantasyit.maid_useful_task.task.IMaidBlockPlaceTask; import studio.fantasyit.maid_useful_task.util.Conditions; @@ -24,8 +25,9 @@ public class PlaceBlockBehavior extends Behavior { } @Override - protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid p_22539_) { - return Conditions.hasReachedValidTargetOrReset(p_22539_); + protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid maid) { + MemoryUtil.setCurrent(maid, CurrentWork.PLACE); + return Conditions.hasReachedValidTargetOrReset(maid); } @Override @@ -59,5 +61,6 @@ public class PlaceBlockBehavior extends Behavior { super.stop(p_22548_, p_22549_, p_22550_); MemoryUtil.clearPlaceTarget(p_22549_); MemoryUtil.clearTarget(p_22549_); + MemoryUtil.setCurrent(p_22549_, CurrentWork.IDLE); } } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/behavior/PlaceBlockMoveBehavior.java b/src/main/java/studio/fantasyit/maid_useful_task/behavior/PlaceBlockMoveBehavior.java index 4ec57f4..a73ee67 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/behavior/PlaceBlockMoveBehavior.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/behavior/PlaceBlockMoveBehavior.java @@ -1,6 +1,5 @@ package studio.fantasyit.maid_useful_task.behavior; -import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task.MaidMoveToBlockTask; import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid; import com.github.tartaricacid.touhoulittlemaid.entity.passive.MaidPathFindingBFS; import net.minecraft.core.BlockPos; @@ -10,7 +9,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraftforge.items.wrapper.CombinedInvWrapper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import studio.fantasyit.maid_useful_task.memory.TaskRateLimitToken; +import studio.fantasyit.maid_useful_task.memory.CurrentWork; import studio.fantasyit.maid_useful_task.task.IMaidBlockPlaceTask; import studio.fantasyit.maid_useful_task.util.Conditions; import studio.fantasyit.maid_useful_task.util.MemoryUtil; @@ -30,16 +29,16 @@ public class PlaceBlockMoveBehavior extends MaidCenterMoveToBlockTask { @Override - protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid p_22539_) { - if (MemoryUtil.getRateLimitToken(p_22539_).isFor(TaskRateLimitToken.Level.L2)) { - return false; - } - return super.checkExtraStartConditions(p_22538_, p_22539_); + protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid maid) { + if (!Conditions.isCurrent(maid, CurrentWork.IDLE)) return false; + return super.checkExtraStartConditions(p_22538_, maid); } @Override protected void start(ServerLevel p_22540_, EntityMaid maid, long p_22542_) { super.start(p_22540_, maid, p_22542_); + if (maid.hasRestriction()) + this.setSearchRange((int) maid.getRestrictRadius()); task = (IMaidBlockPlaceTask) maid.getTask(); CombinedInvWrapper inv = maid.getAvailableInv(true); List markedVis = new ArrayList<>(); @@ -52,6 +51,7 @@ public class PlaceBlockMoveBehavior extends MaidCenterMoveToBlockTask { @Nullable BlockPos target = MemoryUtil.getTargetPos(maid); if (target != null) { MemoryUtil.setPlaceTarget(maid, targetPos); + MemoryUtil.setCurrent(maid, CurrentWork.PLACE); inv.setStackInSlot(finalI, maid.getMainHandItem()); maid.setItemInHand(InteractionHand.MAIN_HAND, targetItem); return; @@ -62,7 +62,8 @@ public class PlaceBlockMoveBehavior extends MaidCenterMoveToBlockTask { @Override protected boolean shouldMoveTo(ServerLevel serverLevel, EntityMaid entityMaid, BlockPos blockPos) { - if (!task.shouldPlacePos(entityMaid, targetItem, blockPos)) return false; + if (!task.shouldPlacePos(entityMaid, targetItem, blockPos.immutable())) return false; + if (!entityMaid.isWithinRestriction(blockPos)) return false; targetPos = blockPos.immutable(); if (blockPos instanceof BlockPos.MutableBlockPos mb) { final int[] dv = {0, 1, -1}; @@ -87,7 +88,10 @@ public class PlaceBlockMoveBehavior extends MaidCenterMoveToBlockTask { @Override protected @NotNull MaidPathFindingBFS getOrCreateArrivalMap(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) { if (this.pathfindingBFS == null) - this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 10); + if (maid.hasRestriction()) + this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 14, (int) maid.getRestrictRadius()); + else + this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 14); return this.pathfindingBFS; } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/behavior/UpdateValidationMemoryBehavior.java b/src/main/java/studio/fantasyit/maid_useful_task/behavior/UpdateValidationMemoryBehavior.java new file mode 100644 index 0000000..da5c2f3 --- /dev/null +++ b/src/main/java/studio/fantasyit/maid_useful_task/behavior/UpdateValidationMemoryBehavior.java @@ -0,0 +1,24 @@ +package studio.fantasyit.maid_useful_task.behavior; + +import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task.MaidCheckRateTask; +import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.ai.memory.MemoryStatus; +import studio.fantasyit.maid_useful_task.registry.MemoryModuleRegistry; +import studio.fantasyit.maid_useful_task.util.MemoryUtil; + +import java.util.Map; + +public class UpdateValidationMemoryBehavior extends MaidCheckRateTask { + public UpdateValidationMemoryBehavior() { + super(Map.of(MemoryModuleRegistry.BLOCK_VALIDATION.get(), MemoryStatus.VALUE_PRESENT)); + this.setMaxCheckRate(600); + } + + @Override + protected void start(ServerLevel p_22540_, EntityMaid p_22541_, long p_22542_) { + //Hardcoded range? + MemoryUtil.getBlockValidationMemory(p_22541_).clearFaraway(p_22541_.blockPosition(), 72); + MemoryUtil.getBlockValidationMemory(p_22541_).clearIf(pos -> p_22540_.getBlockState(pos).isAir()); + } +} diff --git a/src/main/java/studio/fantasyit/maid_useful_task/memory/BlockValidationMemory.java b/src/main/java/studio/fantasyit/maid_useful_task/memory/BlockValidationMemory.java new file mode 100644 index 0000000..1fd6e80 --- /dev/null +++ b/src/main/java/studio/fantasyit/maid_useful_task/memory/BlockValidationMemory.java @@ -0,0 +1,75 @@ +package studio.fantasyit.maid_useful_task.memory; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.BlockPos; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; + +public class BlockValidationMemory { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.list(BlockPos.CODEC).fieldOf("validList").forGetter(BlockValidationMemory::getValidList), + Codec.list(BlockPos.CODEC).fieldOf("invalidList").forGetter(BlockValidationMemory::getInvalidList) + ).apply(instance, BlockValidationMemory::new) + ); + + private final Set validSet = new HashSet<>(); + private final Set invalidSet = new HashSet<>(); + + public BlockValidationMemory() { + } + + public BlockValidationMemory(List validList, List invalidList) { + validSet.addAll(validList); + invalidSet.addAll(invalidList); + } + + public List getValidList() { + return List.copyOf(validSet); + } + + public List getInvalidList() { + return List.copyOf(invalidSet); + } + + public void setValid(BlockPos blockPos) { + validSet.add(blockPos); + invalidSet.remove(blockPos); + } + + public void setInvalid(BlockPos blockPos) { + invalidSet.add(blockPos); + validSet.remove(blockPos); + } + + public void remove(BlockPos blockPos) { + validSet.remove(blockPos); + invalidSet.remove(blockPos); + } + + public boolean isValid(BlockPos blockPos, boolean defaultValue) { + if (validSet.contains(blockPos)) { + return true; + } + if (invalidSet.contains(blockPos)) { + return false; + } + return defaultValue; + } + + public boolean hasRecord(BlockPos blockPos) { + return validSet.contains(blockPos) || invalidSet.contains(blockPos); + } + + public void clearFaraway(BlockPos blockPos, int range) { + clearIf(pos->pos.distSqr(blockPos) > range * range); + } + + public void clearIf(Predicate o) { + validSet.removeIf(o); + invalidSet.removeIf(o); + } +} diff --git a/src/main/java/studio/fantasyit/maid_useful_task/memory/CurrentWork.java b/src/main/java/studio/fantasyit/maid_useful_task/memory/CurrentWork.java new file mode 100644 index 0000000..f3f4c3d --- /dev/null +++ b/src/main/java/studio/fantasyit/maid_useful_task/memory/CurrentWork.java @@ -0,0 +1,10 @@ +package studio.fantasyit.maid_useful_task.memory; + +public enum CurrentWork { + IDLE, + PLACE, + DESTROY, + BLOCKUP_UP, + BLOCKUP_DOWN, + BLOCKUP_DESTROY +} diff --git a/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidCheckPickupItem.java b/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidCheckPickupItem.java index fbb8ffe..252a642 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidCheckPickupItem.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidCheckPickupItem.java @@ -6,13 +6,15 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import studio.fantasyit.maid_useful_task.memory.CurrentWork; +import studio.fantasyit.maid_useful_task.util.Conditions; import studio.fantasyit.maid_useful_task.util.MemoryUtil; @Mixin(EntityMaid.class) public abstract class MaidCheckPickupItem { @Inject(method = "pickupItem", at = @At("HEAD"), cancellable = true, remap = false) public void maid_storage_manager$pickupItem(ItemEntity entityItem, boolean simulate, CallbackInfoReturnable cir) { - if (MemoryUtil.getBlockUpContext((EntityMaid) (Object) this).hasTarget()) { + if (!Conditions.isCurrent((EntityMaid) (Object) this, CurrentWork.IDLE)) { cir.setReturnValue(false); } } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidMoveControlMixin.java b/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidMoveControlMixin.java index a71f56c..0a9acc7 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidMoveControlMixin.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidMoveControlMixin.java @@ -16,12 +16,13 @@ abstract public class MaidMoveControlMixin { @Final private EntityMaid maid; - @Inject(method = "tick", at = @At("HEAD"), remap = false, cancellable = true) + @Inject(method = "tick", at = @At("HEAD"), cancellable = true) public void tick(CallbackInfo ci) { - if (MemoryUtil.getBlockUpContext(this.maid).hasTarget()) { - if (MemoryUtil.getBlockUpContext(this.maid).isOnLine(this.maid.blockPosition())) { - ci.cancel(); - } + if (switch (MemoryUtil.getCurrent(maid)) { + case BLOCKUP_DESTROY, BLOCKUP_DOWN -> true; + default -> false; + }) { + ci.cancel(); } } } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidRunOneMixin.java b/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidRunOneMixin.java index 1ab464e..97b7475 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidRunOneMixin.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/mixin/MaidRunOneMixin.java @@ -7,13 +7,16 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import studio.fantasyit.maid_useful_task.memory.CurrentWork; +import studio.fantasyit.maid_useful_task.util.Conditions; import studio.fantasyit.maid_useful_task.util.MemoryUtil; @Mixin(MaidRunOne.class) abstract public class MaidRunOneMixin { @Inject(method = "tryStart(Lnet/minecraft/server/level/ServerLevel;Lcom/github/tartaricacid/touhoulittlemaid/entity/passive/EntityMaid;J)Z", at = @At("HEAD"), cancellable = true, remap = false) public void runOne(ServerLevel pLevel, EntityMaid maid, long pGameTime, CallbackInfoReturnable cir) { - if (MemoryUtil.getDestroyTargetMemory(maid) != null || MemoryUtil.getPlaceTarget(maid) != null || MemoryUtil.getBlockUpContext(maid).hasTarget()) + if (!Conditions.isCurrent(maid, CurrentWork.IDLE)) { cir.setReturnValue(false); + } } } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/registry/MemoryModuleRegistry.java b/src/main/java/studio/fantasyit/maid_useful_task/registry/MemoryModuleRegistry.java index 0e82fe7..b69a20e 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/registry/MemoryModuleRegistry.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/registry/MemoryModuleRegistry.java @@ -7,9 +7,8 @@ import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.RegistryObject; import studio.fantasyit.maid_useful_task.MaidUsefulTask; -import studio.fantasyit.maid_useful_task.memory.BlockTargetMemory; -import studio.fantasyit.maid_useful_task.memory.BlockUpContext; -import studio.fantasyit.maid_useful_task.memory.TaskRateLimitToken; +import studio.fantasyit.maid_useful_task.memory.*; +import studio.fantasyit.maid_useful_task.util.WrappedMaidFakePlayer; import java.util.Optional; @@ -22,8 +21,9 @@ public class MemoryModuleRegistry { = REGISTER.register("place_target", () -> new MemoryModuleType<>(Optional.empty())); public static final RegistryObject> BLOCK_UP_TARGET = REGISTER.register("block_up", () -> new MemoryModuleType<>(Optional.of(BlockUpContext.CODEC))); - public static final RegistryObject> RATE_LIMIT_TOKEN - = REGISTER.register("task_rate_limit", () -> new MemoryModuleType<>(Optional.empty())); + public static final RegistryObject> BLOCK_VALIDATION + = REGISTER.register("block_validation", () -> new MemoryModuleType<>(Optional.of(BlockValidationMemory.CODEC))); + public static final RegistryObject> CURRENT_WORK = REGISTER.register("current_work", () -> new MemoryModuleType<>(Optional.empty())); public static void register(IEventBus eventBus) { REGISTER.register(eventBus); diff --git a/src/main/java/studio/fantasyit/maid_useful_task/task/IMaidBlockUpTask.java b/src/main/java/studio/fantasyit/maid_useful_task/task/IMaidBlockUpTask.java index 456e0ba..d55ca31 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/task/IMaidBlockUpTask.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/task/IMaidBlockUpTask.java @@ -3,12 +3,14 @@ package studio.fantasyit.maid_useful_task.task; import com.github.tartaricacid.touhoulittlemaid.api.task.IMaidTask; import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid; import com.github.tartaricacid.touhoulittlemaid.entity.passive.MaidPathFindingBFS; +import com.github.tartaricacid.touhoulittlemaid.util.CenterOffsetBlockPosSet; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; import net.minecraftforge.items.wrapper.CombinedInvWrapper; import oshi.util.tuples.Pair; +import studio.fantasyit.maid_useful_task.util.MaidUtils; import studio.fantasyit.maid_useful_task.util.PosUtils; public interface IMaidBlockUpTask { @@ -27,7 +29,6 @@ public interface IMaidBlockUpTask { for (int dz = 0; dz < touchLimit(); dz = dz <= 0 ? 1 - dz : -dz) { for (int dy = 0; dy < verticalDistance(); dy++) { BlockPos targetPos = startPos.offset(dx, dy, dz); - if (maid.hasRestriction() && !maid.isWithinRestriction(targetPos)) break; if (isFindingBlock(maid, targetPos, startPos)) { return true; } @@ -37,55 +38,75 @@ public interface IMaidBlockUpTask { return false; } - default Pair findTargetPosBlockUp(EntityMaid maid, BlockPos center) { + default Pair findTargetPosBlockUp(EntityMaid maid, BlockPos center, int maxUp) { ServerLevel level = (ServerLevel) maid.level(); - MaidPathFindingBFS pathFindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), level, maid); - for (int dx = 0; dx < scanRange(); dx = dx <= 0 ? 1 - dx : -dx) { - for (int dz = 0; dz < scanRange(); dz = dz <= 0 ? 1 - dz : -dz) { - BlockPos.MutableBlockPos mb = center.offset(dx, 0, dz).mutable(); - while (level.getBlockState(mb).canBeReplaced()) mb.move(0, -1, 0); - while (!level.getBlockState(mb).canBeReplaced()) mb.move(0, 1, 0); - if (!PosUtils.isFourSideAir(level, mb)) continue; - if (!pathFindingBFS.canPathReach(mb)) continue; + int maxHeight = verticalOffset() + verticalDistance(); + CenterOffsetBlockPosSet notAvailable = new CenterOffsetBlockPosSet(scanRange(maid), scanRange(maid) + maxHeight / 2 + 1, scanRange(maid), center.getX(), center.getY() + maxHeight / 2, center.getZ()); + MaidPathFindingBFS pathFindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), level, maid, 7, scanRange(maid)); + for (int dx = 0; dx < scanRange(maid); dx = dx <= 0 ? 1 - dx : -dx) { + for (int dz = 0; dz < scanRange(maid); dz = dz <= 0 ? 1 - dz : -dz) { + //计算地面的位置 + BlockPos.MutableBlockPos ground = center.offset(dx, 0, dz).mutable(); + while (level.getBlockState(ground).canBeReplaced()) ground.move(0, -1, 0); + while (!level.getBlockState(ground).canBeReplaced()) ground.move(0, 1, 0); + if (notAvailable.isVis(ground)) continue; + //地面基本判断 + if (!PosUtils.isFourSideAir(level, ground.immutable())) continue; + if (!pathFindingBFS.canPathReach(ground)) continue; boolean valid = true; for (int dy = 0; dy < verticalOffset(); dy++) { - BlockPos targetPos = center.offset(dx, dy, dz); + BlockPos targetPos = ground.above(dy); if (!level.getBlockState(targetPos).canBeReplaced()) { valid = false; break; } } - for (int dy = verticalDistance(); dy < verticalDistance() + 2; dy++) { - BlockPos targetPos = center.offset(dx, dy, dz); + for (int dy = verticalOffset(); dy < verticalOffset() + 2; dy++) { + BlockPos targetPos = ground.above(dy); if (!level.getBlockState(targetPos).isAir()) { valid = false; break; } } - if (!valid) + if (!valid) { + notAvailable.markVis(ground.immutable()); continue; - int touchLimit = touchLimit() + 1; - boolean continuous = true; - BlockPos standPos = center.offset(dx, verticalOffset(), dz); - for (int dy = verticalOffset(); dy < verticalDistance() + verticalOffset(); dy++) { - BlockPos targetPos = center.offset(dx, dy, dz); - if (maid.hasRestriction() && !maid.isWithinRestriction(targetPos)) break; - if (isFindingBlock(maid, targetPos, standPos)) { - return new Pair<>(mb, standPos); - } - //头顶一格是不是空气,不是:不连续空间(不能继续垫了,那么需要计算触及范围 - if (!level.getBlockState(standPos.above().above()).isAir()) { - continuous = false; - } - - if (!continuous) { - touchLimit--; - } else { - standPos = standPos.above(); - } - if (touchLimit <= 0) - break; } + //竖直方向触及 + for (int sdx = 0; sdx < 2; sdx = sdx <= 0 ? 1 - sdx : -sdx) + for (int sdz = 0; sdz < 2; sdz = sdz <= 0 ? 1 - sdz : -sdz) { + int touchLimit = touchLimit() + 1; + boolean continuous = true; + BlockPos standPos = ground.above(verticalOffset()).offset(sdx, 0, sdz); + if (standPos.getY() - ground.getY() > maxUp) + continue; + for (int dy = verticalOffset(); dy < verticalDistance() + verticalOffset(); dy++) { + BlockPos targetPos = ground.offset(sdx, dy, sdz); + if (targetPos.distSqr(standPos) > touchLimit * touchLimit) break; + if (maid.hasRestriction() && !maid.isWithinRestriction(standPos)) break; + if (isFindingBlock(maid, targetPos, standPos)) { + return new Pair<>(ground.immutable(), standPos); + } + //头顶一格是不是空气,不是:不连续空间(不能继续垫了,那么需要计算触及范围 + if (continuous) { + if (!level.getBlockState(standPos.above().above()).isAir()) { + continuous = false; + } else if (maid.hasRestriction() && !maid.isWithinRestriction(standPos.above())) { + continuous = false; + } + } + + if (!continuous) { + touchLimit--; + } else { + standPos = standPos.above(); + if (standPos.getY() - ground.getY() > maxUp) + break; + } + if (touchLimit <= 0) + break; + } + } } } return null; @@ -97,7 +118,7 @@ public interface IMaidBlockUpTask { for (int i = 0; i < inv.getSlots(); i++) { ItemStack stack = inv.getStackInSlot(i); if (isValidItemStack(maid, stack)) { - count++; + count += stack.getCount(); } } return count; @@ -141,11 +162,19 @@ public interface IMaidBlockUpTask { return 15; } - default int scanRange() { - return 10; + default int scanRange(EntityMaid maid) { + return maid.hasRestriction() ? (int) maid.getRestrictRadius() : 15; } default int touchLimit() { return 7; } + + default boolean tryPlaceBlockUp(EntityMaid maid, BlockPos targetPos) { + return MaidUtils.placeBlock(maid, targetPos); + } + + default boolean tryDestroyBlockUp(EntityMaid maid, BlockPos targetPos) { + return MaidUtils.destroyBlock(maid, targetPos); + } } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/task/MaidTreeTask.java b/src/main/java/studio/fantasyit/maid_useful_task/task/MaidTreeTask.java index c0cd289..77f3e89 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/task/MaidTreeTask.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/task/MaidTreeTask.java @@ -20,10 +20,15 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import studio.fantasyit.maid_useful_task.MaidUsefulTask; import studio.fantasyit.maid_useful_task.behavior.*; +import studio.fantasyit.maid_useful_task.memory.BlockValidationMemory; +import studio.fantasyit.maid_useful_task.util.MaidUtils; +import studio.fantasyit.maid_useful_task.util.MemoryUtil; import studio.fantasyit.maid_useful_task.util.WrappedMaidFakePlayer; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockDestroyTask, IMaidBlockUpTask { @Override @@ -49,12 +54,22 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD @Override public boolean shouldDestroyBlock(EntityMaid maid, BlockPos pos) { + if (MemoryUtil.getBlockUpContext(maid).hasTarget()) { + if (pos.getY() < maid.getBlockY() && pos.getX() == maid.getBlockX() && pos.getZ() == maid.getBlockZ()) { + return false; + } + } BlockState blockState = maid.level().getBlockState(pos); return blockState.is(BlockTags.LOGS) && isValidNatureTree(maid, pos); } @Override public boolean mayDestroy(EntityMaid maid, BlockPos pos) { + if (MemoryUtil.getBlockUpContext(maid).hasTarget()) { + if (pos.getY() < maid.getBlockY() && pos.getX() == maid.getBlockX() && pos.getZ() == maid.getBlockZ()) { + return false; + } + } BlockState blockState = maid.level().getBlockState(pos); if (blockState.is(BlockTags.LEAVES)) { return true; @@ -133,34 +148,56 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD return IMaidBlockDestroyTask.super.availableToGetDrop(maid, fakePlayer, pos, targetBlockState); } + protected boolean isValidNatureTree(EntityMaid maid, BlockPos startPos) { + return isValidNatureTree(maid, startPos, new HashSet<>()); + } + + protected boolean isValidNatureTree(EntityMaid maid, BlockPos startPos, Set visited) { + BlockValidationMemory validationMemory = MemoryUtil.getBlockValidationMemory(maid); + if (validationMemory.hasRecord(startPos)) + return validationMemory.isValid(startPos, false); + if (visited.contains(startPos)) + return false; + visited.add(startPos); + boolean valid = false; final int[] dv = {0, 1, -1}; for (int dx : dv) { for (int dz : dv) { - for (int dy = 0; dy < 6; dy++) { - BlockState blockState = maid.level().getBlockState(startPos.offset(dx, dy, dz)); + for (int dy : dv) { + BlockPos offset = startPos.offset(dx, dy, dz); + BlockState blockState = maid.level().getBlockState(offset); if (blockState.is(BlockTags.LEAVES) && !blockState.getValue(LeavesBlock.PERSISTENT)) { - return true; + valid = true; + } + if (blockState.is(BlockTags.LOGS) && isValidNatureTree(maid, offset, visited)) { + valid = true; } } } } - return false; + if (valid) + validationMemory.setValid(startPos); + else + validationMemory.setInvalid(startPos); + return valid; } @Override public List>> createBrainTasks(EntityMaid entityMaid) { ArrayList>> list = new ArrayList<>(); - list.add(Pair.of(6, new LoopWithTokenBehavior())); - list.add(Pair.of(5, new DestoryBlockBehavior())); - list.add(Pair.of(4, new DestoryBlockMoveBehavior())); + list.add(Pair.of(1, new DestoryBlockBehavior())); + list.add(Pair.of(1, new DestoryBlockMoveBehavior())); + + list.add(Pair.of(2, new BlockUpScheduleBehavior())); + list.add(Pair.of(2, new BlockUpPlaceBehavior())); + list.add(Pair.of(2, new BlockUpDestroyBehavior())); + list.add(Pair.of(3, new PlaceBlockBehavior())); - list.add(Pair.of(2, new PlaceBlockMoveBehavior())); + list.add(Pair.of(3, new PlaceBlockMoveBehavior())); - list.add(Pair.of(1, new BlockUpScheduleBehavior())); - list.add(Pair.of(0, new BlockUpPlaceBehavior())); - list.add(Pair.of(0, new BlockUpDestroyBehavior())); + list.add(Pair.of(4, new UpdateValidationMemoryBehavior())); return list; } @@ -181,4 +218,27 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD return false; return maid.level().getBlockState(target).is(BlockTags.LOGS) && isValidNatureTree(maid, target); } + + @Override + public boolean tryDestroyBlockUp(EntityMaid maid, BlockPos targetPos) { + return tryDestroyBlock(maid, targetPos); + } + + @Override + public boolean tryPlaceBlock(EntityMaid maid, BlockPos pos) { + if (IMaidBlockPlaceTask.super.tryPlaceBlock(maid, pos)) { + MemoryUtil.getBlockValidationMemory(maid).setValid(pos); + return true; + } + return false; + } + + @Override + public boolean tryDestroyBlock(EntityMaid maid, BlockPos blockPos) { + if (MaidUtils.destroyBlock(maid, blockPos)) { + MemoryUtil.getBlockValidationMemory(maid).remove(blockPos); + return true; + } + return false; + } } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/util/Conditions.java b/src/main/java/studio/fantasyit/maid_useful_task/util/Conditions.java index d8f9eee..9537d98 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/util/Conditions.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/util/Conditions.java @@ -7,6 +7,7 @@ import net.minecraft.world.entity.ai.Brain; import net.minecraft.world.entity.ai.memory.MemoryModuleType; import net.minecraft.world.entity.ai.memory.WalkTarget; import net.minecraft.world.phys.Vec3; +import studio.fantasyit.maid_useful_task.memory.CurrentWork; import studio.fantasyit.maid_useful_task.registry.MemoryModuleRegistry; import java.util.Optional; @@ -24,6 +25,7 @@ public class Conditions { Optional walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET); if (walkTarget.isEmpty() || !walkTarget.get().getTarget().currentPosition().equals(targetV3d)) { brain.eraseMemory(InitEntities.TARGET_POS.get()); + MemoryUtil.setCurrent(maid, CurrentWork.IDLE); } return false; } @@ -41,10 +43,12 @@ public class Conditions { public static boolean isGlobalValidTarget(EntityMaid maid, BlockPos pos, BlockPos targetPos) { if (MemoryUtil.getBlockUpContext(maid).hasTarget()) { - if (targetPos.getY() < maid.getBlockY() && targetPos.getX() == maid.getBlockX() && targetPos.getZ() == maid.getBlockZ()) - return false; return MemoryUtil.getBlockUpContext(maid).isTarget(pos); } return true; } + + public static boolean isCurrent(EntityMaid maid, CurrentWork currentWork) { + return MemoryUtil.getCurrent(maid) == currentWork; + } } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/util/MaidUtils.java b/src/main/java/studio/fantasyit/maid_useful_task/util/MaidUtils.java index ffc07e8..624c04a 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/util/MaidUtils.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/util/MaidUtils.java @@ -37,7 +37,27 @@ public class MaidUtils { } } } - public static boolean destroyBlock(EntityMaid maid, BlockPos blockPos){ + + public static float getDestroyProgressDelta(EntityMaid maid, BlockPos blockPos) { + WrappedMaidFakePlayer fakePlayer = WrappedMaidFakePlayer.get(maid); + BlockState blockState = maid.level().getBlockState(blockPos); + return blockState.getDestroyProgress(fakePlayer, maid.level(), blockPos); + } + + public static BlockPos getMaidRestrictCenter(EntityMaid maid) { + if (MemoryUtil.getBlockUpContext(maid).hasTarget()) { + return MemoryUtil.getBlockUpContext(maid).getTargetPos(); + } + if (maid.hasRestriction()) + return maid.getRestrictCenter(); + return maid.blockPosition(); + } + + public static boolean destroyBlock(EntityMaid maid, BlockPos blockPos) { + WrappedMaidFakePlayer fakePlayer = WrappedMaidFakePlayer.get(maid); + maid.getMainHandItem().hurtAndBreak(1, fakePlayer, (p_186374_) -> { + p_186374_.broadcastBreakEvent(InteractionHand.MAIN_HAND); + }); ServerLevel level = (ServerLevel) maid.level(); BlockState blockState = level.getBlockState(blockPos); if (blockState.isAir()) { @@ -62,7 +82,7 @@ public class MaidUtils { } public static boolean placeBlock(EntityMaid maid, BlockPos pos) { - Player fakePlayer = WrappedMaidFakePlayer.get(maid); + WrappedMaidFakePlayer fakePlayer = WrappedMaidFakePlayer.get(maid); BlockHitResult result = null; ClipContext rayTraceContext = new ClipContext(maid.getPosition(0).add(0, maid.getEyeHeight(), 0), pos.getCenter(), diff --git a/src/main/java/studio/fantasyit/maid_useful_task/util/MemoryUtil.java b/src/main/java/studio/fantasyit/maid_useful_task/util/MemoryUtil.java index 2c24ee0..ae1cba0 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/util/MemoryUtil.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/util/MemoryUtil.java @@ -5,13 +5,12 @@ import com.github.tartaricacid.touhoulittlemaid.init.InitEntities; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ai.Brain; +import net.minecraft.world.entity.ai.behavior.BehaviorUtils; import net.minecraft.world.entity.ai.behavior.BlockPosTracker; import net.minecraft.world.entity.ai.behavior.PositionTracker; import net.minecraft.world.entity.ai.memory.MemoryModuleType; import org.jetbrains.annotations.Nullable; -import studio.fantasyit.maid_useful_task.memory.BlockTargetMemory; -import studio.fantasyit.maid_useful_task.memory.BlockUpContext; -import studio.fantasyit.maid_useful_task.memory.TaskRateLimitToken; +import studio.fantasyit.maid_useful_task.memory.*; import studio.fantasyit.maid_useful_task.registry.MemoryModuleRegistry; import java.util.List; @@ -62,12 +61,23 @@ public class MemoryUtil { } return brain.getMemory(MemoryModuleRegistry.BLOCK_UP_TARGET.get()).get(); } - public static TaskRateLimitToken getRateLimitToken(EntityMaid maid){ + public static BlockValidationMemory getBlockValidationMemory(EntityMaid maid){ Brain brain = maid.getBrain(); - if(!brain.hasMemoryValue(MemoryModuleRegistry.RATE_LIMIT_TOKEN.get())){ - brain.setMemory(MemoryModuleRegistry.RATE_LIMIT_TOKEN.get(), new TaskRateLimitToken()); + if(!brain.hasMemoryValue(MemoryModuleRegistry.BLOCK_VALIDATION.get())){ + brain.setMemory(MemoryModuleRegistry.BLOCK_VALIDATION.get(), new BlockValidationMemory()); } - return brain.getMemory(MemoryModuleRegistry.RATE_LIMIT_TOKEN.get()).get(); + return brain.getMemory(MemoryModuleRegistry.BLOCK_VALIDATION.get()).get(); } + public static void setTarget(EntityMaid maid, BlockPos targetPos,float speed) { + maid.getBrain().setMemory(InitEntities.TARGET_POS.get(), new BlockPosTracker(targetPos)); + BehaviorUtils.setWalkAndLookTargetMemories(maid, targetPos, speed, 0); + } + + public static CurrentWork getCurrent(EntityMaid maid){ + return maid.getBrain().getMemory(MemoryModuleRegistry.CURRENT_WORK.get()).orElse(CurrentWork.IDLE); + } + public static void setCurrent(EntityMaid maid, CurrentWork currentWork){ + maid.getBrain().setMemory(MemoryModuleRegistry.CURRENT_WORK.get(), currentWork); + } } diff --git a/src/main/java/studio/fantasyit/maid_useful_task/util/WrappedMaidFakePlayer.java b/src/main/java/studio/fantasyit/maid_useful_task/util/WrappedMaidFakePlayer.java index 4c5f9bd..d18ff04 100644 --- a/src/main/java/studio/fantasyit/maid_useful_task/util/WrappedMaidFakePlayer.java +++ b/src/main/java/studio/fantasyit/maid_useful_task/util/WrappedMaidFakePlayer.java @@ -3,9 +3,13 @@ package studio.fantasyit.maid_useful_task.util; import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid; import com.mojang.authlib.GameProfile; import net.minecraft.core.BlockPos; +import net.minecraft.nbt.ListTag; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.TagKey; +import net.minecraft.world.Container; import net.minecraft.world.InteractionHand; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.Entity; @@ -13,6 +17,9 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.RelativeMovement; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.StackedContents; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; @@ -20,6 +27,9 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; +import net.minecraftforge.items.wrapper.PlayerInvWrapper; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -27,8 +37,28 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; public class WrappedMaidFakePlayer extends FakePlayer { + public static class WrappedMaidInventory extends Inventory { + private final EntityMaid maid; + + public WrappedMaidInventory(EntityMaid p_35983_, WrappedMaidFakePlayer fakePlayer) { + super(fakePlayer); + this.maid = p_35983_; + } + + @Override + public @NotNull ItemStack getSelected() { + return maid.getMainHandItem(); + } + + @Override + public float getDestroySpeed(BlockState p_36021_) { + return maid.getMainHandItem().getDestroySpeed(p_36021_); + } + } + private static ConcurrentHashMap cache = new ConcurrentHashMap<>(); private final EntityMaid maid; @@ -50,6 +80,7 @@ public class WrappedMaidFakePlayer extends FakePlayer { private WrappedMaidFakePlayer(EntityMaid maid) { super((ServerLevel) maid.level(), new GameProfile(UUID.randomUUID(), maid.getName().getString())); this.maid = maid; + this.inventory = new WrappedMaidInventory(maid, this); } @Override diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 9c4cfcf..a1ddef1 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1 +1,2 @@ -public net.minecraft.world.level.BlockGetter m_151361_(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Ljava/lang/Object;Ljava/util/function/BiFunction;Ljava/util/function/Function;)Ljava/lang/Object; \ No newline at end of file +public net.minecraft.world.level.BlockGetter m_151361_(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Ljava/lang/Object;Ljava/util/function/BiFunction;Ljava/util/function/Function;)Ljava/lang/Object; +public-f net.minecraft.world.entity.player.Player f_36093_ \ No newline at end of file