Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Prevent movement to origin after spawning #105

Merged
merged 3 commits into from
Apr 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,15 @@ public void construct(Actor actor) {

MinionMoveComponent minionMoveComponent = actor.getComponent(MinionMoveComponent.class);
Vector3ic start = Blocks.toBlockPos(actor.getComponent(LocationComponent.class).getWorldPosition(new Vector3f()));
Vector3ic goal = actor.getComponent(MinionMoveComponent.class).getPathGoal();
Vector3ic goal = minionMoveComponent.getPathGoal();

if (goal == null) {
// Special case to prevent pathfinding computation to (0,0,0) when the entity was just spawned.
// Returning early causes this action to terminate with BehaviorState.FAILURE on first execution
// of '#modify(Actor, BehaviorState)' as no pathfinding is running and the 'path' should still
// be empty.
return;
}

JPSConfig config = new JPSConfig(start, goal);
config.useLineOfSight = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,14 @@ public final class MinionMoveComponent implements Component<MinionMoveComponent>
*/
public float targetTolerance = 0.1f;

// last known goal position
private Vector3i goalPosition = new Vector3i();
/**
* The last known goal position.
* <p>
* Initialized with 'null' to avoid entities trying to reach the origin block (0,0,0) right after spawning.
* <p>
* To ensure only a single vector instance is used, all writing access should go through {@link #setGoalPosition(Vector3i)}.
*/
private Vector3i goalPosition = null;

// an entity to take the goal position from
//TODO(skaldarnar): What's the difference between MinionMoveComponent#pathGoalEntity and FollowComponent#entityToFollow?
Expand All @@ -53,8 +59,9 @@ public final class MinionMoveComponent implements Component<MinionMoveComponent>

/**
* The path of reachable waypoints to the {@link #goalPosition}.
*
* <p>
* If empty no path to the target exists, or it was not computed yet.
* <p>
* If the {@link #goalPosition} is reachable, the path will contain at least that position as last element.
*/
private List<Vector3i> path = Lists.newArrayList();
Expand Down Expand Up @@ -98,26 +105,40 @@ public void setPathGoal(EntityRef entity) {
* @param pos the final movement goal position
*/
public void setPathGoal(Vector3i pos) {
goalPosition.set(pos);
setGoalPosition(pos);
pathGoalEntity = null;
resetPath();
}

/**
* Retrieve the final movement goal position.
* Set the last known goal position to the given position {@code pos}.
* <p>
* Ensures lazy initialization of {@link #goalPosition} on first write.
*
* If the {@link #pathGoalEntity} is set, the goal position is derived from the entity's location.
* Otherwise, the goal position is {@link #goalPosition}.
* @param pos the new goal position this actor is moving towards
*/
private void setGoalPosition(Vector3i pos) {
if (goalPosition == null) {
goalPosition = new Vector3i();
}
goalPosition.set(pos);
}

/**
* Retrieve the final movement goal position.
* <p>
* If the {@link #pathGoalEntity} is set, the goal position is derived from the entity's location. Otherwise, the goal position is
* {@link #goalPosition}.
*
* @return the current goal position
* @return the current goal position, or 'null' if no goal position is known.
*/
public Vector3i getPathGoal() {
//TODO: this is logic on component, doing a lookup on a different entity.
// this is definitely not the recommended way to handle components and dependencies between entities.
if (pathGoalEntity != null && pathGoalEntity.getComponent(LocationComponent.class) != null) {
Vector3f worldPosition = pathGoalEntity.getComponent(LocationComponent.class).getWorldPosition(new Vector3f());
Vector3i pos = Blocks.toBlockPos(worldPosition);
goalPosition.set(pos);
setGoalPosition(pos);
}
return goalPosition;
}
Expand Down Expand Up @@ -181,7 +202,9 @@ public void copyFrom(MinionMoveComponent other) {
target.set(other.target);
targetTolerance = other.targetTolerance;
pathGoalEntity = other.pathGoalEntity;
goalPosition.set(other.goalPosition);
if (other.goalPosition != null) {
setGoalPosition(other.goalPosition);
}
goalTolerance = other.goalTolerance;
path = other.path;
pathIndex = other.pathIndex; //TODO change me when migrate JOML
Expand Down