优化寻路
优化砍罚目标选择 优化行为顺序
This commit is contained in:
@@ -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()
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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<EntityMaid> {
|
||||
}
|
||||
|
||||
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<EntityMaid> {
|
||||
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<EntityMaid> {
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<EntityMaid> {
|
||||
|
||||
@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<EntityMaid> {
|
||||
@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<EntityMaid> {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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<EntityMaid> {
|
||||
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<EntityMaid> {
|
||||
|
||||
@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<EntityMaid> {
|
||||
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<BlockPos, BlockPos> targetPosBlockUp = task.findTargetPosBlockUp(maid, maid.blockPosition());
|
||||
Pair<BlockPos, BlockPos> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<EntityMaid> {
|
||||
|
||||
@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<EntityMaid> {
|
||||
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<EntityMaid> {
|
||||
}
|
||||
|
||||
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<EntityMaid> {
|
||||
super.stop(p_22548_, p_22549_, p_22550_);
|
||||
MemoryUtil.clearDestroyTargetMemory(p_22549_);
|
||||
MemoryUtil.clearTarget(p_22549_);
|
||||
MemoryUtil.setCurrent(p_22549_, CurrentWork.IDLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<EntityMaid> {
|
||||
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<EntityMaid> {
|
||||
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<EntityMaid> {
|
||||
}
|
||||
|
||||
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<EntityMaid> {
|
||||
|
||||
protected abstract boolean shouldMoveTo(ServerLevel var1, EntityMaid var2, BlockPos var3);
|
||||
|
||||
/** @deprecated */
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated(
|
||||
forRemoval = true
|
||||
)
|
||||
|
||||
@@ -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<EntityMaid> {
|
||||
}
|
||||
|
||||
@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<EntityMaid> {
|
||||
super.stop(p_22548_, p_22549_, p_22550_);
|
||||
MemoryUtil.clearPlaceTarget(p_22549_);
|
||||
MemoryUtil.clearTarget(p_22549_);
|
||||
MemoryUtil.setCurrent(p_22549_, CurrentWork.IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ItemStack> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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<BlockValidationMemory> 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<BlockPos> validSet = new HashSet<>();
|
||||
private final Set<BlockPos> invalidSet = new HashSet<>();
|
||||
|
||||
public BlockValidationMemory() {
|
||||
}
|
||||
|
||||
public BlockValidationMemory(List<BlockPos> validList, List<BlockPos> invalidList) {
|
||||
validSet.addAll(validList);
|
||||
invalidSet.addAll(invalidList);
|
||||
}
|
||||
|
||||
public List<BlockPos> getValidList() {
|
||||
return List.copyOf(validSet);
|
||||
}
|
||||
|
||||
public List<BlockPos> 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<BlockPos> o) {
|
||||
validSet.removeIf(o);
|
||||
invalidSet.removeIf(o);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package studio.fantasyit.maid_useful_task.memory;
|
||||
|
||||
public enum CurrentWork {
|
||||
IDLE,
|
||||
PLACE,
|
||||
DESTROY,
|
||||
BLOCKUP_UP,
|
||||
BLOCKUP_DOWN,
|
||||
BLOCKUP_DESTROY
|
||||
}
|
||||
@@ -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<Boolean> cir) {
|
||||
if (MemoryUtil.getBlockUpContext((EntityMaid) (Object) this).hasTarget()) {
|
||||
if (!Conditions.isCurrent((EntityMaid) (Object) this, CurrentWork.IDLE)) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Boolean> cir) {
|
||||
if (MemoryUtil.getDestroyTargetMemory(maid) != null || MemoryUtil.getPlaceTarget(maid) != null || MemoryUtil.getBlockUpContext(maid).hasTarget())
|
||||
if (!Conditions.isCurrent(maid, CurrentWork.IDLE)) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<MemoryModuleType<BlockUpContext>> BLOCK_UP_TARGET
|
||||
= REGISTER.register("block_up", () -> new MemoryModuleType<>(Optional.of(BlockUpContext.CODEC)));
|
||||
public static final RegistryObject<MemoryModuleType<TaskRateLimitToken>> RATE_LIMIT_TOKEN
|
||||
= REGISTER.register("task_rate_limit", () -> new MemoryModuleType<>(Optional.empty()));
|
||||
public static final RegistryObject<MemoryModuleType<BlockValidationMemory>> BLOCK_VALIDATION
|
||||
= REGISTER.register("block_validation", () -> new MemoryModuleType<>(Optional.of(BlockValidationMemory.CODEC)));
|
||||
public static final RegistryObject<MemoryModuleType<CurrentWork>> CURRENT_WORK = REGISTER.register("current_work", () -> new MemoryModuleType<>(Optional.empty()));
|
||||
|
||||
public static void register(IEventBus eventBus) {
|
||||
REGISTER.register(eventBus);
|
||||
|
||||
@@ -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<BlockPos, BlockPos> findTargetPosBlockUp(EntityMaid maid, BlockPos center) {
|
||||
default Pair<BlockPos, BlockPos> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<BlockPos> 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<Pair<Integer, BehaviorControl<? super EntityMaid>>> createBrainTasks(EntityMaid entityMaid) {
|
||||
ArrayList<Pair<Integer, BehaviorControl<? super EntityMaid>>> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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<EntityMaid> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<UUID, WrappedMaidFakePlayer> 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
|
||||
|
||||
@@ -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;
|
||||
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_
|
||||
Reference in New Issue
Block a user