Fix crouch timer, bed collision on sleep, and pathfinding: better node evaluator maluses, path-aware door opening

This commit is contained in:
2026-06-14 01:57:58 +03:00
parent a43adb0de2
commit ff6046e89c
3 changed files with 58 additions and 13 deletions
@@ -3,6 +3,7 @@ package me.sashegdev.fabled_hearts.ai;
import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; import net.minecraft.world.entity.ai.navigation.GroundPathNavigation;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.pathfinder.BlockPathTypes;
import net.minecraft.world.level.pathfinder.PathFinder; import net.minecraft.world.level.pathfinder.PathFinder;
public class ElliePathNavigation extends GroundPathNavigation { public class ElliePathNavigation extends GroundPathNavigation {
@@ -13,8 +14,18 @@ public class ElliePathNavigation extends GroundPathNavigation {
@Override @Override
protected PathFinder createPathFinder(int maxVisitedNodes) { protected PathFinder createPathFinder(int maxVisitedNodes) {
mob.setPathfindingMalus(BlockPathTypes.DOOR_WOOD_CLOSED, 2.0F);
mob.setPathfindingMalus(BlockPathTypes.DOOR_IRON_CLOSED, 5.0F);
mob.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F);
mob.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0F);
mob.setPathfindingMalus(BlockPathTypes.LAVA, -1.0F);
mob.setPathfindingMalus(BlockPathTypes.WATER, 3.0F);
mob.setPathfindingMalus(BlockPathTypes.WATER_BORDER, 1.0F);
mob.setPathfindingMalus(BlockPathTypes.FENCE, -1.0F);
EllieNodeEvaluator evaluator = new EllieNodeEvaluator(); EllieNodeEvaluator evaluator = new EllieNodeEvaluator();
evaluator.setCanPassDoors(true); evaluator.setCanPassDoors(true);
evaluator.setCanOpenDoors(true);
this.nodeEvaluator = evaluator; this.nodeEvaluator = evaluator;
return new PathFinder(evaluator, maxVisitedNodes); return new PathFinder(evaluator, maxVisitedNodes);
} }
@@ -6,6 +6,8 @@ import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.level.block.BedBlock; import net.minecraft.world.level.block.BedBlock;
import net.minecraft.world.level.block.DoorBlock; import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.Node;
import net.minecraft.world.level.pathfinder.Path;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import java.util.EnumSet; import java.util.EnumSet;
@@ -86,8 +88,24 @@ public class EllieSleepGoal extends Goal {
} }
private void tryOpenDoor() { private void tryOpenDoor() {
Path path = ellie.getNavigation().getPath();
BlockPos entityPos = ellie.blockPosition();
if (path != null) {
for (int i = 0; i < Math.min(4, path.getNodeCount()); i++) {
Node node = path.getNode(i);
BlockPos checkPos = new BlockPos(node.x, node.y, node.z);
if (checkPos.distSqr(entityPos) > 9) break;
BlockState state = ellie.level().getBlockState(checkPos);
if (state.getBlock() instanceof DoorBlock) {
if (!state.getValue(DoorBlock.OPEN)) {
ellie.level().setBlock(checkPos, state.setValue(DoorBlock.OPEN, true), 3);
}
return;
}
}
}
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
BlockPos checkPos = ellie.blockPosition().relative(ellie.getDirection(), i); BlockPos checkPos = entityPos.relative(ellie.getDirection(), i);
BlockState state = ellie.level().getBlockState(checkPos); BlockState state = ellie.level().getBlockState(checkPos);
if (state.getBlock() instanceof DoorBlock) { if (state.getBlock() instanceof DoorBlock) {
if (!state.getValue(DoorBlock.OPEN)) { if (!state.getValue(DoorBlock.OPEN)) {
@@ -32,6 +32,7 @@ import net.minecraft.world.level.block.state.properties.BedPart;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.pathfinder.Node; import net.minecraft.world.level.pathfinder.Node;
import net.minecraft.world.level.pathfinder.Path; import net.minecraft.world.level.pathfinder.Path;
import net.minecraft.world.level.pathfinder.BlockPathTypes;
import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import me.sashegdev.fabled_hearts.network.DebugSyncPacket; import me.sashegdev.fabled_hearts.network.DebugSyncPacket;
import me.sashegdev.fabled_hearts.network.ModNetworking; import me.sashegdev.fabled_hearts.network.ModNetworking;
@@ -189,7 +190,10 @@ public class EllieEntity extends Animal implements GeoEntity {
} }
boolean wasCrouching = getPose() == Pose.CROUCHING; boolean wasCrouching = getPose() == Pose.CROUCHING;
if (wasCrouching) {
if (lowCeiling) {
crouchTimer = Math.max(crouchTimer, 20);
} else if (wasCrouching) {
crouchTimer = Math.max(0, crouchTimer - 1); crouchTimer = Math.max(0, crouchTimer - 1);
} }
@@ -199,7 +203,6 @@ public class EllieEntity extends Animal implements GeoEntity {
} else if (lowCeiling) { } else if (lowCeiling) {
if (onGround() || wasCrouching) { if (onGround() || wasCrouching) {
setPose(Pose.CROUCHING); setPose(Pose.CROUCHING);
crouchTimer = 20;
} }
} else if (wasCrouching && crouchTimer > 0) { } else if (wasCrouching && crouchTimer > 0) {
setPose(Pose.CROUCHING); setPose(Pose.CROUCHING);
@@ -280,13 +283,8 @@ public class EllieEntity extends Animal implements GeoEntity {
if (isSpaceLow(pos)) return true; if (isSpaceLow(pos)) return true;
if (isMoving() && navigation.isInProgress()) { if (isMoving() && navigation.isInProgress()) {
Direction dir = getDirection(); Direction dir = getDirection();
Direction left = dir.getCounterClockWise(); for (int i = 1; i <= 2; i++) {
Direction right = dir.getClockWise(); if (isSpaceLow(pos.relative(dir, i))) return true;
for (int i = 1; i <= 3; i++) {
BlockPos ahead = pos.relative(dir, i);
if (isSpaceLow(ahead)) return true;
if (isSpaceLow(ahead.relative(left, 1))) return true;
if (isSpaceLow(ahead.relative(right, 1))) return true;
} }
} }
return false; return false;
@@ -371,13 +369,13 @@ public class EllieEntity extends Animal implements GeoEntity {
? pos ? pos
: pos.relative(facing); : pos.relative(facing);
float yRot = facing.getOpposite().toYRot(); setPose(Pose.SLEEPING);
setPos(headPos.getX() + 0.5, headPos.getY() + 0.5625, headPos.getZ() + 0.5); setPos(headPos.getX() + 0.5, headPos.getY() + 0.5625, headPos.getZ() + 0.5);
float yRot = facing.getOpposite().toYRot();
setYRot(yRot); setYRot(yRot);
yRotO = yRot; yRotO = yRot;
setYHeadRot(yRot); setYHeadRot(yRot);
setSleeping(true); setSleeping(true);
setPose(Pose.SLEEPING);
} }
public void wakeUp() { public void wakeUp() {
@@ -390,8 +388,26 @@ public class EllieEntity extends Animal implements GeoEntity {
} }
public void openDoorInFront() { public void openDoorInFront() {
Path path = navigation.getPath();
BlockPos entityPos = blockPosition();
if (path != null) {
for (int i = 0; i < Math.min(4, path.getNodeCount()); i++) {
Node node = path.getNode(i);
BlockPos checkPos = new BlockPos(node.x, node.y, node.z);
if (checkPos.distSqr(entityPos) > 9) break;
BlockState state = level().getBlockState(checkPos);
if (state.getBlock() instanceof DoorBlock) {
if (!state.getValue(DoorBlock.OPEN)) {
level().setBlock(checkPos, state.setValue(DoorBlock.OPEN, true), 3);
lastOpenedDoor = checkPos;
doorCloseTimer = 0;
}
return;
}
}
}
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
BlockPos checkPos = blockPosition().relative(getDirection(), 2 + i); BlockPos checkPos = entityPos.relative(getDirection(), 2 + i);
BlockState state = level().getBlockState(checkPos); BlockState state = level().getBlockState(checkPos);
if (state.getBlock() instanceof DoorBlock) { if (state.getBlock() instanceof DoorBlock) {
if (!state.getValue(DoorBlock.OPEN)) { if (!state.getValue(DoorBlock.OPEN)) {