支持blockup寻路
This commit is contained in:
@@ -167,6 +167,7 @@ dependencies {
|
||||
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
|
||||
compileOnly fg.deobf("curse.maven:touhou-little-maid-355044:6440955")
|
||||
runtimeOnly fg.deobf("curse.maven:touhou-little-maid-355044:6440955")
|
||||
runtimeOnly fg.deobf("curse.maven:maid-storage-manager-1210244:6455832")
|
||||
}
|
||||
|
||||
// This block of code expands all declared replace properties in the specified resource targets.
|
||||
|
||||
@@ -42,7 +42,7 @@ mod_name=maid useful task
|
||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||
mod_license=MIT
|
||||
# The mod version. See https://semver.org/
|
||||
mod_version=1.0.0
|
||||
mod_version=1.0.1
|
||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||
# This should match the base package used for the mod sources.
|
||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
|
||||
@@ -26,7 +26,9 @@ public class UsefulTaskExtension implements ILittleMaid {
|
||||
public List<MemoryModuleType<?>> getExtraMemoryTypes() {
|
||||
return List.of(
|
||||
MemoryModuleRegistry.DESTROY_TARGET.get(),
|
||||
MemoryModuleRegistry.PLACE_TARGET.get()
|
||||
MemoryModuleRegistry.PLACE_TARGET.get(),
|
||||
MemoryModuleRegistry.BLOCK_UP_TARGET.get(),
|
||||
MemoryModuleRegistry.RATE_LIMIT_TOKEN.get()
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package studio.fantasyit.maid_useful_task.behavior;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import net.minecraft.core.BlockPos;
|
||||
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.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.task.IMaidBlockUpTask;
|
||||
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;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BlockUpDestroyBehavior extends Behavior<EntityMaid> {
|
||||
private BlockUpContext context;
|
||||
private IMaidBlockUpTask task;
|
||||
|
||||
WrappedMaidFakePlayer fakePlayer;
|
||||
|
||||
public BlockUpDestroyBehavior(Map<MemoryModuleType<?>, MemoryStatus> p_22528_) {
|
||||
super(p_22528_);
|
||||
}
|
||||
|
||||
public BlockUpDestroyBehavior() {
|
||||
super(Map.of(),200);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid p_22539_) {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canStillUse(ServerLevel p_22545_, EntityMaid maid, long p_22547_) {
|
||||
if (MemoryUtil.getBlockUpContext(maid).getStatus() != BlockUpContext.STATUS.DOWN) return false;
|
||||
return MemoryUtil.getBlockUpContext(maid).isOnLine(maid.blockPosition()) && !maid.blockPosition().equals(context.getStartPos());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void start(ServerLevel p_22540_, EntityMaid maid, long p_22542_) {
|
||||
context = MemoryUtil.getBlockUpContext(maid);
|
||||
task = (IMaidBlockUpTask) maid.getTask();
|
||||
fakePlayer = WrappedMaidFakePlayer.get(maid);
|
||||
}
|
||||
|
||||
float progress = 0;
|
||||
|
||||
@Override
|
||||
protected void tick(ServerLevel level, EntityMaid maid, long p_22553_) {
|
||||
if (!maid.onGround()) {
|
||||
progress = 0;
|
||||
} else {
|
||||
task.swapValidToolToHand(maid);
|
||||
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;
|
||||
progress += speed;
|
||||
if (progress >= 1f) {
|
||||
MaidUtils.destroyBlock(maid, targetPos);
|
||||
progress = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void stop(ServerLevel p_22548_, EntityMaid maid, long p_22550_) {
|
||||
super.stop(p_22548_, maid, p_22550_);
|
||||
context.setStatus(BlockUpContext.STATUS.IDLE);
|
||||
MemoryUtil.clearTarget(maid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package studio.fantasyit.maid_useful_task.behavior;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import net.minecraft.core.BlockPos;
|
||||
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.MemoryModuleType;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus;
|
||||
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.task.IMaidBlockUpTask;
|
||||
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 java.util.Map;
|
||||
|
||||
public class BlockUpPlaceBehavior extends Behavior<EntityMaid> {
|
||||
private BlockUpContext context;
|
||||
private IMaidBlockUpTask task;
|
||||
private int tickCount;
|
||||
|
||||
|
||||
public BlockUpPlaceBehavior(Map<MemoryModuleType<?>, MemoryStatus> p_22528_) {
|
||||
super(p_22528_);
|
||||
}
|
||||
|
||||
public BlockUpPlaceBehavior() {
|
||||
super(Map.of(), 200);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid p_22539_) {
|
||||
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);
|
||||
}
|
||||
|
||||
@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;
|
||||
return !(maid.blockPosition().equals(context.getTargetPos()) && maid.onGround());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void start(ServerLevel p_22540_, EntityMaid maid, long p_22542_) {
|
||||
context = MemoryUtil.getBlockUpContext(maid);
|
||||
task = (IMaidBlockUpTask) maid.getTask();
|
||||
tickCount = 0;
|
||||
}
|
||||
|
||||
protected boolean alignOrTryMove(ServerLevel level, EntityMaid maid) {
|
||||
AABB boundingBox = maid.getBoundingBox();
|
||||
BlockPos startPos = context.getStartPos();
|
||||
Vec3 move = maid.getDeltaMovement();
|
||||
if (boundingBox.maxX <= startPos.getX() + 1 && boundingBox.maxZ <= startPos.getZ() + 1
|
||||
&& boundingBox.minX >= startPos.getX() && boundingBox.minZ >= startPos.getZ()
|
||||
) {
|
||||
maid.setDeltaMovement(0, move.y, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
Vec3 dv = startPos.getCenter().subtract(boundingBox.getCenter()).normalize().scale(0.02);
|
||||
maid.setDeltaMovement(dv.x, move.y, dv.z);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tick(ServerLevel level, EntityMaid maid, long p_22553_) {
|
||||
if (!alignOrTryMove(level, maid)) return;
|
||||
tickCount += 1;
|
||||
if (!maid.onGround()) {
|
||||
task.swapValidItemToHand(maid);
|
||||
BlockPos pos = maid.blockPosition();
|
||||
BlockPos below = pos.below();
|
||||
if (context.isOnLine(pos))
|
||||
if (below.equals(context.getTargetPos()))
|
||||
return;
|
||||
if (level.getBlockState(below).canBeReplaced() && level.getBlockState(pos).canBeReplaced()) {
|
||||
maid.swing(InteractionHand.MAIN_HAND);
|
||||
MaidUtils.placeBlock(maid, below);
|
||||
}
|
||||
} else {
|
||||
maid.getJumpControl().jump();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean timedOut(long p_22537_) {
|
||||
return tickCount > 240;
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
MemoryUtil.clearTarget(maid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
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;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.ai.behavior.Behavior;
|
||||
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 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.task.IMaidBlockUpTask;
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid p_22539_) {
|
||||
if (MemoryUtil.getRateLimitToken(p_22539_).isFor(TaskRateLimitToken.Level.L3)) {
|
||||
return false;
|
||||
}
|
||||
return super.checkExtraStartConditions(p_22538_, p_22539_);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start(ServerLevel p_22540_, EntityMaid maid, long p_22542_) {
|
||||
BlockUpContext context = MemoryUtil.getBlockUpContext(maid);
|
||||
IMaidBlockUpTask task = (IMaidBlockUpTask) maid.getTask();
|
||||
if (context.hasTarget()) {
|
||||
if (context.getStatus() != BlockUpContext.STATUS.IDLE && MemoryUtil.getTargetPos(maid) == null) {
|
||||
context.clearStartTarget();
|
||||
} 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());
|
||||
} 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);
|
||||
}
|
||||
} else {
|
||||
Pair<BlockPos, BlockPos> targetPosBlockUp = task.findTargetPosBlockUp(maid, maid.blockPosition());
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import studio.fantasyit.maid_useful_task.util.Conditions;
|
||||
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
|
||||
import studio.fantasyit.maid_useful_task.util.WrappedMaidFakePlayer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -47,7 +48,7 @@ public class DestoryBlockBehavior extends Behavior<EntityMaid> {
|
||||
super.start(p_22540_, maid, p_22542_);
|
||||
BlockTargetMemory blockTargetMemory = MemoryUtil.getDestroyTargetMemory(maid);
|
||||
if (blockTargetMemory != null) {
|
||||
blockPosSet = blockTargetMemory.getBlockPosSet();
|
||||
blockPosSet =new ArrayList<>(blockTargetMemory.getBlockPosSet());
|
||||
blockPosSet.sort((o1, o2) -> (int) (o1.distSqr(maid.blockPosition()) - o2.distSqr(maid.blockPosition())));
|
||||
}
|
||||
index = 0;
|
||||
|
||||
@@ -7,19 +7,30 @@ 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.task.IMaidBlockDestroyTask;
|
||||
import studio.fantasyit.maid_useful_task.util.Conditions;
|
||||
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DestoryBlockMoveBehavior extends MaidMoveToBlockTask {
|
||||
public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask {
|
||||
private IMaidBlockDestroyTask task;
|
||||
private MaidPathFindingBFS pathfindingBFS;
|
||||
private BlockPos targetPos;
|
||||
List<BlockPos> blockPosSet;
|
||||
|
||||
public DestoryBlockMoveBehavior() {
|
||||
super(0.5f, 4);
|
||||
super(0.5f, 7, 8);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid p_22539_) {
|
||||
if (MemoryUtil.getRateLimitToken(p_22539_).isFor(TaskRateLimitToken.Level.L1)) {
|
||||
return false;
|
||||
}
|
||||
return super.checkExtraStartConditions(p_22538_, p_22539_);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -34,7 +45,6 @@ public class DestoryBlockMoveBehavior extends MaidMoveToBlockTask {
|
||||
MemoryUtil.setDestroyTargetMemory(maid, blockPosSet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldMoveTo(@NotNull ServerLevel serverLevel, @NotNull EntityMaid entityMaid, @NotNull BlockPos blockPos) {
|
||||
if (!task.shouldDestroyBlock(entityMaid, blockPos)) return false;
|
||||
@@ -44,6 +54,8 @@ public class DestoryBlockMoveBehavior extends MaidMoveToBlockTask {
|
||||
for (int dy = 0; dy < task.reachDistance(); dy = dy <= 0 ? 1 - dy : -dy) {
|
||||
for (int dz = 0; dz < task.reachDistance(); dz = dz <= 0 ? 1 - dz : -dz) {
|
||||
BlockPos pos = mb.offset(dx, dy, dz);
|
||||
if (!Conditions.isGlobalValidTarget(entityMaid, pos, targetPos)) continue;
|
||||
if (pos.distSqr(targetPos) > task.reachDistance() * task.reachDistance()) continue;
|
||||
if (entityMaid.isWithinRestriction(pos) && pathfindingBFS.canPathReach(pos)) {
|
||||
blockPosSet = task.toDestroyFromStanding(entityMaid, targetPos, pos);
|
||||
if (blockPosSet != null) {
|
||||
@@ -59,9 +71,17 @@ public class DestoryBlockMoveBehavior extends MaidMoveToBlockTask {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected @NotNull MaidPathFindingBFS getOrCreateArrivalMap(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) {
|
||||
this.pathfindingBFS = super.getOrCreateArrivalMap(worldIn, maid);
|
||||
if (this.pathfindingBFS == null)
|
||||
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 14);
|
||||
return this.pathfindingBFS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearCurrentArrivalMap(MaidPathFindingBFS pathFinding) {
|
||||
super.clearCurrentArrivalMap(pathFinding);
|
||||
this.pathfindingBFS = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package studio.fantasyit.maid_useful_task.behavior;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.ai.behavior.Behavior;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus;
|
||||
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class LoopWithTokenBehavior extends Behavior<EntityMaid> {
|
||||
public LoopWithTokenBehavior() {
|
||||
super(Map.of());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start(ServerLevel p_22540_, EntityMaid p_22541_, long p_22542_) {
|
||||
MemoryUtil.getRateLimitToken(p_22541_).tick(p_22541_);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
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.entity.passive.MaidPathFindingBFS;
|
||||
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.ai.behavior.Behavior;
|
||||
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;
|
||||
|
||||
/**
|
||||
* From https://github.com/TartaricAcid/TouhouLittleMaid
|
||||
* 为了重载getWorkSearchPos而写的
|
||||
*/
|
||||
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;
|
||||
protected int verticalSearchStart;
|
||||
|
||||
public MaidCenterMoveToBlockTask(float movementSpeed) {
|
||||
this(movementSpeed, 1);
|
||||
}
|
||||
|
||||
public MaidCenterMoveToBlockTask(float movementSpeed, int verticalSearchRange) {
|
||||
this(movementSpeed, verticalSearchRange, 7);
|
||||
}
|
||||
public MaidCenterMoveToBlockTask(float movementSpeed, int verticalSearchRange,int searchRange) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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)) {
|
||||
BehaviorUtils.setWalkAndLookTargetMemories(maid, mutableBlockPos, this.movementSpeed, 0);
|
||||
maid.getBrain().setMemory((MemoryModuleType)InitEntities.TARGET_POS.get(), new BlockPosTracker(mutableBlockPos));
|
||||
this.clearCurrentArrivalMap(pathFinding);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.clearCurrentArrivalMap(pathFinding);
|
||||
}
|
||||
|
||||
protected void clearCurrentArrivalMap(MaidPathFindingBFS pathFinding) {
|
||||
pathFinding.finish();
|
||||
}
|
||||
|
||||
protected MaidPathFindingBFS getOrCreateArrivalMap(ServerLevel worldIn, EntityMaid maid) {
|
||||
return new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid);
|
||||
}
|
||||
|
||||
private BlockPos getWorkSearchPos(EntityMaid maid) {
|
||||
return maid.blockPosition();
|
||||
}
|
||||
|
||||
private boolean checkOwnerPos(EntityMaid maid, BlockPos mutableBlockPos) {
|
||||
if (maid.isHomeModeEnable()) {
|
||||
return true;
|
||||
} else {
|
||||
return maid.getOwner() != null && mutableBlockPos.closerToCenterThan(maid.getOwner().position(), 8.0);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean shouldMoveTo(ServerLevel var1, EntityMaid var2, BlockPos var3);
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated(
|
||||
forRemoval = true
|
||||
)
|
||||
protected boolean checkPathReach(EntityMaid maid, BlockPos pos) {
|
||||
return maid.canPathReach(pos);
|
||||
}
|
||||
|
||||
protected boolean checkPathReach(EntityMaid maid, MaidPathFindingBFS pathFinding, BlockPos pos) {
|
||||
return pathFinding.canPathReach(pos);
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class PlaceBlockBehavior extends Behavior<EntityMaid> {
|
||||
IMaidBlockPlaceTask task = (IMaidBlockPlaceTask) maid.getTask();
|
||||
if (task.shouldPlacePos(maid, maid.getMainHandItem(), target)) {
|
||||
maid.swing(InteractionHand.MAIN_HAND);
|
||||
task.tryPlaceBlock(maid, maid.getMainHandItem(), target);
|
||||
task.tryPlaceBlock(maid, target);
|
||||
}
|
||||
target = null;
|
||||
}
|
||||
|
||||
@@ -10,13 +10,15 @@ 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.task.IMaidBlockPlaceTask;
|
||||
import studio.fantasyit.maid_useful_task.util.Conditions;
|
||||
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PlaceBlockMoveBehavior extends MaidMoveToBlockTask {
|
||||
public class PlaceBlockMoveBehavior extends MaidCenterMoveToBlockTask {
|
||||
private IMaidBlockPlaceTask task;
|
||||
private MaidPathFindingBFS pathfindingBFS;
|
||||
private BlockPos targetPos;
|
||||
@@ -26,6 +28,15 @@ public class PlaceBlockMoveBehavior extends MaidMoveToBlockTask {
|
||||
super(0.5f, 4);
|
||||
}
|
||||
|
||||
|
||||
@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_);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start(ServerLevel p_22540_, EntityMaid maid, long p_22542_) {
|
||||
super.start(p_22540_, maid, p_22542_);
|
||||
@@ -59,6 +70,7 @@ public class PlaceBlockMoveBehavior extends MaidMoveToBlockTask {
|
||||
for (int dy : dv) {
|
||||
for (int dz : dv) {
|
||||
BlockPos pos = mb.offset(dx, dy, dz);
|
||||
if (!Conditions.isGlobalValidTarget(entityMaid, pos, targetPos)) continue;
|
||||
if (entityMaid.isWithinRestriction(pos) && pathfindingBFS.canPathReach(pos)) {
|
||||
mb.set(pos);
|
||||
return true;
|
||||
@@ -74,7 +86,14 @@ public class PlaceBlockMoveBehavior extends MaidMoveToBlockTask {
|
||||
|
||||
@Override
|
||||
protected @NotNull MaidPathFindingBFS getOrCreateArrivalMap(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) {
|
||||
this.pathfindingBFS = super.getOrCreateArrivalMap(worldIn, maid);
|
||||
if (this.pathfindingBFS == null)
|
||||
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 10);
|
||||
return this.pathfindingBFS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearCurrentArrivalMap(MaidPathFindingBFS pathFinding) {
|
||||
super.clearCurrentArrivalMap(pathFinding);
|
||||
this.pathfindingBFS = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
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.Optional;
|
||||
|
||||
public class BlockUpContext {
|
||||
public static final Codec<BlockUpContext> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
BlockPos.CODEC.optionalFieldOf("startPos").forGetter(BlockUpContext::getOptionalStartPos),
|
||||
BlockPos.CODEC.optionalFieldOf("targetPos").forGetter(BlockUpContext::getOptionalTargetPos)
|
||||
)
|
||||
.apply(instance, BlockUpContext::new)
|
||||
);
|
||||
|
||||
public enum STATUS {
|
||||
IDLE,
|
||||
DOWN,
|
||||
UP
|
||||
}
|
||||
|
||||
boolean isGoingDown = false;
|
||||
/**
|
||||
* 结束位置(女仆所在位置,实际方块为target-1)
|
||||
*/
|
||||
BlockPos targetPos;
|
||||
BlockPos startPos;
|
||||
|
||||
public BlockUpContext() {
|
||||
this(Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
public BlockUpContext(BlockPos startPos, BlockPos targetPos) {
|
||||
this.startPos = startPos;
|
||||
this.targetPos = targetPos;
|
||||
}
|
||||
|
||||
public BlockUpContext(Optional<BlockPos> startPos, Optional<BlockPos> targetPos) {
|
||||
this.startPos = startPos.orElse(null);
|
||||
this.targetPos = targetPos.orElse(null);
|
||||
}
|
||||
|
||||
public BlockPos getStartPos() {
|
||||
return startPos;
|
||||
}
|
||||
|
||||
public BlockPos getTargetPos() {
|
||||
return targetPos;
|
||||
}
|
||||
|
||||
public Optional<BlockPos> getOptionalStartPos() {
|
||||
return Optional.ofNullable(startPos);
|
||||
}
|
||||
|
||||
public Optional<BlockPos> getOptionalTargetPos() {
|
||||
return Optional.ofNullable(targetPos);
|
||||
}
|
||||
|
||||
|
||||
public boolean isOnLine(BlockPos pos) {
|
||||
return pos.getX() == startPos.getX() && pos.getZ() == startPos.getZ() && pos.getY() >= startPos.getY() && pos.getY() <= targetPos.getY();
|
||||
}
|
||||
|
||||
public void setStartTarget(BlockPos startPos, BlockPos targetPos) {
|
||||
this.startPos = startPos;
|
||||
this.targetPos = targetPos;
|
||||
setStatus(STATUS.IDLE);
|
||||
}
|
||||
|
||||
public void clearStartTarget() {
|
||||
this.startPos = null;
|
||||
this.targetPos = null;
|
||||
setStatus(STATUS.IDLE);
|
||||
}
|
||||
|
||||
public boolean hasTarget() {
|
||||
return startPos != null && targetPos != null;
|
||||
}
|
||||
|
||||
public boolean isTarget(BlockPos pos) {
|
||||
return pos.equals(targetPos);
|
||||
}
|
||||
|
||||
private STATUS status = STATUS.IDLE;
|
||||
|
||||
public STATUS getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(STATUS status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package studio.fantasyit.maid_useful_task.memory;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
|
||||
|
||||
public class TaskRateLimitToken {
|
||||
public enum Level {
|
||||
|
||||
IDLE(0),
|
||||
L1(1),
|
||||
L2(2),
|
||||
L3(3),
|
||||
L4(4),
|
||||
L5(5);
|
||||
private final int level;
|
||||
|
||||
Level(int level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
||||
int currentLevel = 0;
|
||||
int cooldown = 100;
|
||||
|
||||
public void tick(EntityMaid maid) {
|
||||
if (MemoryUtil.getTargetPos(maid) != null) {
|
||||
currentLevel = 0;
|
||||
cooldown = 20;
|
||||
return;
|
||||
}
|
||||
if (cooldown > 0) {
|
||||
cooldown--;
|
||||
return;
|
||||
}
|
||||
|
||||
currentLevel++;
|
||||
if (currentLevel > 5) {
|
||||
currentLevel = 0;
|
||||
cooldown = 100;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFor(Level level) {
|
||||
return currentLevel == level.getLevel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package studio.fantasyit.maid_useful_task.mixin;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
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.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()) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package studio.fantasyit.maid_useful_task.mixin;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.ai.control.MaidMoveControl;
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
|
||||
|
||||
@Mixin(MaidMoveControl.class)
|
||||
abstract public class MaidMoveControlMixin {
|
||||
@Shadow(remap = false)
|
||||
@Final
|
||||
private EntityMaid maid;
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"), remap = false, cancellable = true)
|
||||
public void tick(CallbackInfo ci) {
|
||||
if (MemoryUtil.getBlockUpContext(this.maid).hasTarget()) {
|
||||
if (MemoryUtil.getBlockUpContext(this.maid).isOnLine(this.maid.blockPosition())) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,9 @@ 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)
|
||||
@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)
|
||||
if (MemoryUtil.getDestroyTargetMemory(maid) != null || MemoryUtil.getPlaceTarget(maid) != null || MemoryUtil.getBlockUpContext(maid).hasTarget())
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ 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 java.util.Optional;
|
||||
|
||||
@@ -18,6 +20,10 @@ public class MemoryModuleRegistry {
|
||||
= REGISTER.register("block_targets", () -> new MemoryModuleType<>(Optional.of(BlockTargetMemory.CODEC)));
|
||||
public static final RegistryObject<MemoryModuleType<BlockPos>> PLACE_TARGET
|
||||
= 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 void register(IEventBus eventBus) {
|
||||
REGISTER.register(eventBus);
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import studio.fantasyit.maid_useful_task.behavior.DestoryBlockBehavior;
|
||||
import studio.fantasyit.maid_useful_task.behavior.DestoryBlockMoveBehavior;
|
||||
import studio.fantasyit.maid_useful_task.util.MaidUtils;
|
||||
import studio.fantasyit.maid_useful_task.util.WrappedMaidFakePlayer;
|
||||
|
||||
import java.util.*;
|
||||
@@ -27,6 +28,9 @@ public interface IMaidBlockDestroyTask {
|
||||
List<BlockPos> list = new ArrayList<>();
|
||||
Vec3 eyePos = standPos.getCenter().add(0, maid.getEyeHeight() - 0.5, 0);
|
||||
Boolean available = BlockGetter.traverseBlocks(eyePos, targetPos.getCenter(), maid.level(), (level, pos) -> {
|
||||
if (pos.distSqr(standPos) > reachDistance() * reachDistance()) {
|
||||
return false;
|
||||
}
|
||||
BlockState state = level.getBlockState(pos);
|
||||
if (state.isAir()) {
|
||||
return null;
|
||||
@@ -108,7 +112,8 @@ public interface IMaidBlockDestroyTask {
|
||||
* @return 是否可以破坏
|
||||
*/
|
||||
default boolean canDestroyBlock(EntityMaid maid, BlockPos pos) {
|
||||
if (maid.distanceToSqr(pos.getCenter()) > Math.pow(reachDistance(), 2)) {
|
||||
//女仆可能少走一格,所以判断时给予补偿
|
||||
if (maid.distanceToSqr(pos.getCenter()) > Math.pow(reachDistance() + 1, 2)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -117,32 +122,12 @@ public interface IMaidBlockDestroyTask {
|
||||
/**
|
||||
* 尝试破坏方块
|
||||
*
|
||||
* @param maid 女仆
|
||||
* @param blockPos 位置
|
||||
* @param maid 女仆
|
||||
* @param blockPos 位置
|
||||
* @return
|
||||
*/
|
||||
default boolean tryDestroyBlock(EntityMaid maid, BlockPos blockPos) {
|
||||
ServerLevel level = (ServerLevel) maid.level();
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
if (blockState.isAir()) {
|
||||
return false;
|
||||
} else {
|
||||
FluidState fluidState = level.getFluidState(blockPos);
|
||||
if (!(blockState.getBlock() instanceof BaseFireBlock)) {
|
||||
level.levelEvent(2001, blockPos, Block.getId(blockState));
|
||||
}
|
||||
|
||||
BlockEntity blockEntity = blockState.hasBlockEntity() ? level.getBlockEntity(blockPos) : null;
|
||||
//改用MainHandItem来roll loot
|
||||
maid.dropResourcesToMaidInv(blockState, level, blockPos, blockEntity, maid, maid.getMainHandItem());
|
||||
|
||||
boolean setResult = level.setBlock(blockPos, fluidState.createLegacyBlock(), 3);
|
||||
if (setResult) {
|
||||
level.gameEvent(GameEvent.BLOCK_DESTROY, blockPos, GameEvent.Context.of(maid, blockState));
|
||||
}
|
||||
|
||||
return setResult;
|
||||
}
|
||||
return MaidUtils.destroyBlock(maid, blockPos);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +147,7 @@ public interface IMaidBlockDestroyTask {
|
||||
}
|
||||
|
||||
default int reachDistance() {
|
||||
return 6;
|
||||
return 7;
|
||||
}
|
||||
|
||||
default @NotNull List<Pair<Integer, BehaviorControl<? super EntityMaid>>> createBrainTasks(@NotNull EntityMaid entityMaid) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import net.minecraft.world.phys.BlockHitResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import studio.fantasyit.maid_useful_task.behavior.DestoryBlockBehavior;
|
||||
import studio.fantasyit.maid_useful_task.behavior.DestoryBlockMoveBehavior;
|
||||
import studio.fantasyit.maid_useful_task.util.MaidUtils;
|
||||
import studio.fantasyit.maid_useful_task.util.WrappedMaidFakePlayer;
|
||||
|
||||
import java.util.List;
|
||||
@@ -23,24 +24,8 @@ public interface IMaidBlockPlaceTask {
|
||||
|
||||
boolean shouldPlacePos(EntityMaid maid, ItemStack itemStack, BlockPos pos);
|
||||
|
||||
default boolean tryPlaceBlock(EntityMaid maid, ItemStack itemStack, BlockPos pos){
|
||||
Player fakePlayer = WrappedMaidFakePlayer.get(maid);
|
||||
BlockHitResult result = null;
|
||||
ClipContext rayTraceContext = new ClipContext(maid.getPosition(0).add(0, maid.getEyeHeight(), 0),
|
||||
pos.getCenter(),
|
||||
ClipContext.Block.OUTLINE,
|
||||
ClipContext.Fluid.NONE,
|
||||
fakePlayer);
|
||||
result = maid.level().clip(rayTraceContext);
|
||||
UseOnContext useContext = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, result);
|
||||
InteractionResult actionresult = fakePlayer.getItemInHand(InteractionHand.MAIN_HAND).onItemUseFirst(useContext);
|
||||
if (actionresult == InteractionResult.PASS) {
|
||||
InteractionResult interactionResult = fakePlayer.getItemInHand(InteractionHand.MAIN_HAND).useOn(useContext);
|
||||
if (interactionResult.consumesAction()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
default boolean tryPlaceBlock(EntityMaid maid, BlockPos pos){
|
||||
return MaidUtils.placeBlock(maid,pos);
|
||||
}
|
||||
default @NotNull List<Pair<Integer, BehaviorControl<? super EntityMaid>>> createBrainTasks(@NotNull EntityMaid entityMaid) {
|
||||
return List.of(
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
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 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.PosUtils;
|
||||
|
||||
public interface IMaidBlockUpTask {
|
||||
default boolean isFindingBlock(EntityMaid maid, BlockPos target, BlockPos standPos) {
|
||||
if (target.distSqr(standPos) > touchLimit() * touchLimit())
|
||||
return false;
|
||||
IMaidTask task = maid.getTask();
|
||||
if (task instanceof IMaidBlockDestroyTask destroyTask) {
|
||||
return destroyTask.shouldDestroyBlock(maid, target);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean stillValid(EntityMaid maid, BlockPos startPos) {
|
||||
for (int dx = 0; dx < touchLimit(); dx = dx <= 0 ? 1 - dx : -dx) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default Pair<BlockPos, BlockPos> findTargetPosBlockUp(EntityMaid maid, BlockPos center) {
|
||||
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;
|
||||
boolean valid = true;
|
||||
for (int dy = 0; dy < verticalOffset(); dy++) {
|
||||
BlockPos targetPos = center.offset(dx, dy, dz);
|
||||
if (!level.getBlockState(targetPos).canBeReplaced()) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int dy = verticalDistance(); dy < verticalDistance() + 2; dy++) {
|
||||
BlockPos targetPos = center.offset(dx, dy, dz);
|
||||
if (!level.getBlockState(targetPos).isAir()) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!valid)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
default int countMaxUsableBlockItems(EntityMaid maid) {
|
||||
CombinedInvWrapper inv = maid.getAvailableInv(true);
|
||||
int count = 0;
|
||||
for (int i = 0; i < inv.getSlots(); i++) {
|
||||
ItemStack stack = inv.getStackInSlot(i);
|
||||
if (isValidItemStack(maid, stack)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
default boolean swapValidItemToHand(EntityMaid maid) {
|
||||
CombinedInvWrapper inv = maid.getAvailableInv(true);
|
||||
for (int i = 0; i < inv.getSlots(); i++) {
|
||||
ItemStack stack = inv.getStackInSlot(i);
|
||||
if (isValidItemStack(maid, stack)) {
|
||||
inv.setStackInSlot(i, maid.getMainHandItem());
|
||||
maid.setItemInHand(InteractionHand.MAIN_HAND, stack);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean swapValidToolToHand(EntityMaid maid) {
|
||||
CombinedInvWrapper inv = maid.getAvailableInv(true);
|
||||
for (int i = 0; i < inv.getSlots(); i++) {
|
||||
ItemStack stack = inv.getStackInSlot(i);
|
||||
if (isDestroyTool(maid, stack)) {
|
||||
inv.setStackInSlot(i, maid.getMainHandItem());
|
||||
maid.setItemInHand(InteractionHand.MAIN_HAND, stack);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isValidItemStack(EntityMaid maid, ItemStack stack);
|
||||
|
||||
boolean isDestroyTool(EntityMaid maid, ItemStack stack);
|
||||
|
||||
default int verticalOffset() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
default int verticalDistance() {
|
||||
return 15;
|
||||
}
|
||||
|
||||
default int scanRange() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
default int touchLimit() {
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
@@ -19,16 +19,13 @@ import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import studio.fantasyit.maid_useful_task.MaidUsefulTask;
|
||||
import studio.fantasyit.maid_useful_task.behavior.DestoryBlockBehavior;
|
||||
import studio.fantasyit.maid_useful_task.behavior.DestoryBlockMoveBehavior;
|
||||
import studio.fantasyit.maid_useful_task.behavior.PlaceBlockBehavior;
|
||||
import studio.fantasyit.maid_useful_task.behavior.PlaceBlockMoveBehavior;
|
||||
import studio.fantasyit.maid_useful_task.behavior.*;
|
||||
import studio.fantasyit.maid_useful_task.util.WrappedMaidFakePlayer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockDestroyTask {
|
||||
public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockDestroyTask, IMaidBlockUpTask {
|
||||
@Override
|
||||
public ResourceLocation getUid() {
|
||||
return new ResourceLocation(MaidUsefulTask.MODID, "maid_tree");
|
||||
@@ -73,7 +70,7 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD
|
||||
@Override
|
||||
public boolean shouldPlacePos(EntityMaid maid, ItemStack itemStack, BlockPos pos) {
|
||||
ServerLevel level = (ServerLevel) maid.level();
|
||||
if(!level.getBlockState(pos.below()).is(BlockTags.DIRT)) return false;
|
||||
if (!level.getBlockState(pos.below()).is(BlockTags.DIRT)) return false;
|
||||
if (!level.getBlockState(pos).canBeReplaced()) return false;
|
||||
final int[] dv = {0, 1, -1, 2, -2};
|
||||
for (int dx : dv) {
|
||||
@@ -154,12 +151,34 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD
|
||||
@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(3, new PlaceBlockBehavior()));
|
||||
list.add(Pair.of(2, new PlaceBlockMoveBehavior()));
|
||||
|
||||
list.add(Pair.of(1, new BlockUpScheduleBehavior()));
|
||||
list.add(Pair.of(0, new BlockUpPlaceBehavior()));
|
||||
list.add(Pair.of(0, new BlockUpDestroyBehavior()));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidItemStack(EntityMaid maid, ItemStack stack) {
|
||||
return stack.is(ItemTags.LOGS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDestroyTool(EntityMaid maid, ItemStack stack) {
|
||||
return stack.is(ItemTags.AXES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFindingBlock(EntityMaid maid, BlockPos target, BlockPos standPos) {
|
||||
if (target.distSqr(standPos) > touchLimit() * touchLimit())
|
||||
return false;
|
||||
return maid.level().getBlockState(target).is(BlockTags.LOGS) && isValidNatureTree(maid, target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,20 @@ package studio.fantasyit.maid_useful_task.util;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;
|
||||
import net.minecraft.core.BlockPos;
|
||||
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.registry.MemoryModuleRegistry;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class Conditions {
|
||||
public static boolean hasReachedValidTargetOrReset(EntityMaid maid){
|
||||
public static boolean hasReachedValidTargetOrReset(EntityMaid maid) {
|
||||
return hasReachedValidTargetOrReset(maid, 2);
|
||||
}
|
||||
|
||||
public static boolean hasReachedValidTargetOrReset(EntityMaid maid, float closeEnough) {
|
||||
Brain<EntityMaid> brain = maid.getBrain();
|
||||
return brain.getMemory(InitEntities.TARGET_POS.get()).map(targetPos -> {
|
||||
@@ -35,4 +38,13 @@ public class Conditions {
|
||||
}
|
||||
return maid.getDeltaMovement().length() < 0.2;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,21 @@ 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.server.level.ServerLevel;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.block.BaseFireBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
import net.minecraftforge.common.util.FakePlayerFactory;
|
||||
import net.minecraftforge.items.wrapper.RangedWrapper;
|
||||
@@ -25,4 +37,47 @@ public class MaidUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
public static boolean destroyBlock(EntityMaid maid, BlockPos blockPos){
|
||||
ServerLevel level = (ServerLevel) maid.level();
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
if (blockState.isAir()) {
|
||||
return false;
|
||||
} else {
|
||||
FluidState fluidState = level.getFluidState(blockPos);
|
||||
if (!(blockState.getBlock() instanceof BaseFireBlock)) {
|
||||
level.levelEvent(2001, blockPos, Block.getId(blockState));
|
||||
}
|
||||
|
||||
BlockEntity blockEntity = blockState.hasBlockEntity() ? level.getBlockEntity(blockPos) : null;
|
||||
//改用MainHandItem来roll loot
|
||||
maid.dropResourcesToMaidInv(blockState, level, blockPos, blockEntity, maid, maid.getMainHandItem());
|
||||
|
||||
boolean setResult = level.setBlock(blockPos, fluidState.createLegacyBlock(), 3);
|
||||
if (setResult) {
|
||||
level.gameEvent(GameEvent.BLOCK_DESTROY, blockPos, GameEvent.Context.of(maid, blockState));
|
||||
}
|
||||
|
||||
return setResult;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean placeBlock(EntityMaid maid, BlockPos pos) {
|
||||
Player fakePlayer = WrappedMaidFakePlayer.get(maid);
|
||||
BlockHitResult result = null;
|
||||
ClipContext rayTraceContext = new ClipContext(maid.getPosition(0).add(0, maid.getEyeHeight(), 0),
|
||||
pos.getCenter(),
|
||||
ClipContext.Block.OUTLINE,
|
||||
ClipContext.Fluid.NONE,
|
||||
fakePlayer);
|
||||
result = maid.level().clip(rayTraceContext);
|
||||
UseOnContext useContext = new UseOnContext(fakePlayer, InteractionHand.MAIN_HAND, result);
|
||||
InteractionResult actionresult = fakePlayer.getMainHandItem().onItemUseFirst(useContext);
|
||||
if (actionresult == InteractionResult.PASS) {
|
||||
InteractionResult interactionResult = fakePlayer.getMainHandItem().useOn(useContext);
|
||||
if (interactionResult.consumesAction()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,15 @@ package studio.fantasyit.maid_useful_task.util;
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
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.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.registry.MemoryModuleRegistry;
|
||||
|
||||
import java.util.List;
|
||||
@@ -50,4 +54,20 @@ public class MemoryUtil {
|
||||
public static void setLookAt(EntityMaid maid, BlockPos pos) {
|
||||
maid.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new BlockPosTracker(pos));
|
||||
}
|
||||
|
||||
public static BlockUpContext getBlockUpContext(EntityMaid maid){
|
||||
Brain<EntityMaid> brain = maid.getBrain();
|
||||
if(!brain.hasMemoryValue(MemoryModuleRegistry.BLOCK_UP_TARGET.get())){
|
||||
brain.setMemory(MemoryModuleRegistry.BLOCK_UP_TARGET.get(), new BlockUpContext());
|
||||
}
|
||||
return brain.getMemory(MemoryModuleRegistry.BLOCK_UP_TARGET.get()).get();
|
||||
}
|
||||
public static TaskRateLimitToken getRateLimitToken(EntityMaid maid){
|
||||
Brain<EntityMaid> brain = maid.getBrain();
|
||||
if(!brain.hasMemoryValue(MemoryModuleRegistry.RATE_LIMIT_TOKEN.get())){
|
||||
brain.setMemory(MemoryModuleRegistry.RATE_LIMIT_TOKEN.get(), new TaskRateLimitToken());
|
||||
}
|
||||
return brain.getMemory(MemoryModuleRegistry.RATE_LIMIT_TOKEN.get()).get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package studio.fantasyit.maid_useful_task.util;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
|
||||
public class PosUtils {
|
||||
public static boolean isFourSideAir(BlockGetter level, BlockPos pos) {
|
||||
return level.getBlockState(pos).isAir() &&
|
||||
level.getBlockState(pos.north()).isAir() &&
|
||||
level.getBlockState(pos.south()).isAir() &&
|
||||
level.getBlockState(pos.east()).isAir() &&
|
||||
level.getBlockState(pos.west()).isAir();
|
||||
}
|
||||
}
|
||||
@@ -34,12 +34,17 @@ public class WrappedMaidFakePlayer extends FakePlayer {
|
||||
|
||||
public static WrappedMaidFakePlayer get(EntityMaid maid) {
|
||||
if (cache.containsKey(maid.getUUID())) {
|
||||
return cache.get(maid.getUUID());
|
||||
} else {
|
||||
WrappedMaidFakePlayer fakePlayer = new WrappedMaidFakePlayer(maid);
|
||||
cache.put(maid.getUUID(), fakePlayer);
|
||||
return fakePlayer;
|
||||
WrappedMaidFakePlayer wrappedMaidFakePlayer = cache.get(maid.getUUID());
|
||||
if (!wrappedMaidFakePlayer.maid.isAlive()) {
|
||||
cache.remove(maid.getUUID());
|
||||
} else {
|
||||
return wrappedMaidFakePlayer;
|
||||
}
|
||||
}
|
||||
WrappedMaidFakePlayer fakePlayer = new WrappedMaidFakePlayer(maid);
|
||||
cache.put(maid.getUUID(), fakePlayer);
|
||||
return fakePlayer;
|
||||
|
||||
}
|
||||
|
||||
private WrappedMaidFakePlayer(EntityMaid maid) {
|
||||
@@ -49,27 +54,32 @@ public class WrappedMaidFakePlayer extends FakePlayer {
|
||||
|
||||
@Override
|
||||
public boolean removeEffect(MobEffect p_21196_) {
|
||||
if (maid == null) return false;
|
||||
return maid.removeEffect(p_21196_);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MobEffectInstance removeEffectNoUpdate(@Nullable MobEffect p_21164_) {
|
||||
if (maid == null) return super.removeEffectNoUpdate(p_21164_);
|
||||
return maid.removeEffectNoUpdate(p_21164_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAllEffects() {
|
||||
if (maid == null) return false;
|
||||
return maid.removeAllEffects();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addEffect(MobEffectInstance p_147208_, @Nullable Entity p_147209_) {
|
||||
if (maid == null) return super.addEffect(p_147208_, p_147209_);
|
||||
return maid.addEffect(p_147208_, p_147209_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeAffected(MobEffectInstance p_21197_) {
|
||||
if (maid == null) return super.canBeAffected(p_21197_);
|
||||
return maid.canBeAffected(p_21197_);
|
||||
}
|
||||
|
||||
@@ -81,21 +91,25 @@ public class WrappedMaidFakePlayer extends FakePlayer {
|
||||
@Nullable
|
||||
@Override
|
||||
public MobEffectInstance getEffect(MobEffect p_21125_) {
|
||||
if (maid == null) return super.getEffect(p_21125_);
|
||||
return maid.getEffect(p_21125_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MobEffectInstance> getActiveEffects() {
|
||||
if (maid == null) return super.getActiveEffects();
|
||||
return maid.getActiveEffects();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<MobEffect, MobEffectInstance> getActiveEffectsMap() {
|
||||
if (maid == null) return super.getActiveEffectsMap();
|
||||
return maid.getActiveEffectsMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEffect(MobEffect p_21024_) {
|
||||
if (maid == null) return super.hasEffect(p_21024_);
|
||||
return maid.hasEffect(p_21024_);
|
||||
}
|
||||
|
||||
@@ -105,13 +119,21 @@ public class WrappedMaidFakePlayer extends FakePlayer {
|
||||
return maid.getMainHandItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInHand(InteractionHand p_21121_) {
|
||||
if (maid == null) return super.getItemInHand(p_21121_);
|
||||
return maid.getItemInHand(p_21121_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInHand(InteractionHand p_21009_, ItemStack p_21010_) {
|
||||
if (maid == null) return;
|
||||
maid.setItemInHand(p_21009_, p_21010_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemSlot(EquipmentSlot p_36161_, ItemStack p_36162_) {
|
||||
if (maid == null) return;
|
||||
maid.setItemSlot(p_36161_, p_36162_);
|
||||
}
|
||||
|
||||
@@ -123,11 +145,13 @@ public class WrappedMaidFakePlayer extends FakePlayer {
|
||||
|
||||
@Override
|
||||
public boolean isEyeInFluid(TagKey<Fluid> p_204030_) {
|
||||
if (maid == null) return false;
|
||||
return maid.isEyeInFluid(p_204030_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onGround() {
|
||||
if (maid == null) return false;
|
||||
return maid.onGround();
|
||||
}
|
||||
|
||||
@@ -169,6 +193,7 @@ public class WrappedMaidFakePlayer extends FakePlayer {
|
||||
|
||||
@Override
|
||||
public void teleportRelative(double p_251611_, double p_248861_, double p_252266_) {
|
||||
if (maid == null) return;
|
||||
maid.teleportRelative(p_251611_, p_248861_, p_252266_);
|
||||
}
|
||||
|
||||
@@ -180,6 +205,7 @@ public class WrappedMaidFakePlayer extends FakePlayer {
|
||||
|
||||
@Override
|
||||
public ChunkPos chunkPosition() {
|
||||
if (maid == null) return new ChunkPos(0, 0);
|
||||
return maid.chunkPosition();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"refmap": "maid_useful_task.refmap.json",
|
||||
"mixins": [
|
||||
"MaidCheckPickupItem",
|
||||
"MaidMoveControlMixin",
|
||||
"MaidRunOneMixin"
|
||||
],
|
||||
"client": [
|
||||
|
||||
Reference in New Issue
Block a user