优化寻路

优化砍罚目标选择
优化行为顺序
This commit is contained in:
xypp
2025-04-27 22:57:56 +08:00
parent 0aa91679e3
commit 5eaf45a113
23 changed files with 443 additions and 130 deletions

View File

@@ -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()
);
}
});

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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
)

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,10 @@
package studio.fantasyit.maid_useful_task.memory;
public enum CurrentWork {
IDLE,
PLACE,
DESTROY,
BLOCKUP_UP,
BLOCKUP_DOWN,
BLOCKUP_DESTROY
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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(),

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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_