BodyMotionPath.java
package com.hypixel.hytale.server.npc.corecomponents.world;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.math.random.RandomExtra;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.universe.world.path.IPath;
import com.hypixel.hytale.server.core.universe.world.path.IPathWaypoint;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import com.hypixel.hytale.server.npc.corecomponents.BodyMotionBase;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderBodyMotionPath;
import com.hypixel.hytale.server.npc.movement.Steering;
import com.hypixel.hytale.server.npc.movement.controllers.MotionController;
import com.hypixel.hytale.server.npc.movement.steeringforces.SteeringForcePursue;
import com.hypixel.hytale.server.npc.movement.steeringforces.SteeringForceRotate;
import com.hypixel.hytale.server.npc.role.Role;
import com.hypixel.hytale.server.npc.role.support.WorldSupport;
import com.hypixel.hytale.server.npc.sensorinfo.IPathProvider;
import com.hypixel.hytale.server.npc.sensorinfo.InfoProvider;
import com.hypixel.hytale.server.npc.util.NPCPhysicsMath;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
it.unimi.dsi.fastutil.ints.IntLists;
java.util.concurrent.ThreadLocalRandom;
java.util.function.Supplier;
javax.annotation.Nonnull;
javax.annotation.Nullable;
{
;
;
Shape shape;
pathWidth;
nodeWidth;
minRelativeSpeed;
maxRelativeSpeed;
minWalkDistance;
maxWalkDistance;
startAtNearestNode;
Direction direction;
minNodeDelay;
maxNodeDelay;
viewSegments;
useNodeViewDirection;
pickRandomAngle;
minDelayScale;
maxDelayScale;
minPercentage;
maxPercentage;
-;
Direction currentDirection;
();
();
();
visitIndex;
();
();
currentSpeed;
();
();
nextPositionValid;
currentNodeDelay;
pendingNodeDelay;
rotatingToView;
nodeViewDirection;
nodeWaitTime;
observationSector;
currentObservationDelay;
rotating;
Vector3d previousSteeringTranslation;
currentViewSegment;
{
(builder);
.previousSteeringTranslation = (Vector3d.MIN);
.shape = builder.getShape(support);
.pathWidth = builder.getPathWidth();
.nodeWidth = builder.getNodeWidth();
.minRelativeSpeed = builder.getMinRelativeSpeed();
.maxRelativeSpeed = builder.getMaxRelativeSpeed();
.minWalkDistance = builder.getMinWalkDistance();
.maxWalkDistance = builder.getMaxWalkDistance();
.startAtNearestNode = builder.isStartAtNearestNode();
.direction = builder.getDirection();
.minNodeDelay = builder.getMinNodeDelay();
.maxNodeDelay = builder.getMaxNodeDelay();
.useNodeViewDirection = builder.isUseNodeViewDirection();
[] delayScaleRange = builder.getDelayScaleRange(support);
.minDelayScale = delayScaleRange[];
.maxDelayScale = delayScaleRange[];
[] delayPercentRange = builder.getPercentDelayRange(support);
.minPercentage = delayPercentRange[];
.maxPercentage = delayPercentRange[];
.pickRandomAngle = builder.isPickRandomAngle();
.viewSegments = builder.getViewSegments(support);
}
{
.reset();
}
{
.invalidateWaypoint();
.reset();
}
{
desiredSteering.clear();
(!role.getActiveMotionController().canAct(ref, componentAccessor)) {
;
} {
(IPathProvider)sensorInfo.getExtraInfo(IPathProvider.class);
(info != && info.hasPath()) {
IPath<?> path = info.getPath();
path.length();
(.visitOrder.size() != numWaypoints) {
.visitOrder.clear();
( ; i < numWaypoints; ++i) {
.visitOrder.add(i);
}
IntLists.shuffle(.visitOrder, ThreadLocalRandom.current());
.visitIndex = ;
.invalidateWaypoint();
}
(TransformComponent)componentAccessor.getComponent(ref, TransformComponent.getComponentType());
transformComponent != ;
transformComponent.getPosition();
(.currentWaypointIndex == -) {
(!.getFirstWaypoint(ref, role, path, position, componentAccessor)) {
;
}
.nextPositionValid = ;
.currentNodeDelay = ;
}
transformComponent.getRotation().getYaw();
(.currentNodeDelay > ) {
.currentNodeDelay -= dt;
(.observationSector != || numWaypoints == ) {
.steeringForceRotate.setHeading(heading);
(.steeringForceRotate.compute(desiredSteering)) {
;
}
desiredSteering.setYaw(heading);
(.tickObservationDelay(dt)) {
;
}
.pickNextObservationAngle();
}
;
} {
role.getActiveMotionController();
activeMotionController.getComponentSelector();
role.getWorldSupport();
.currentPosition.assign(position.getX(), position.getY(), position.getZ());
.currentWaypointIndex;
.lastWaypointPosition.assign(.currentWaypointPosition);
(.closeToPosition(.currentWaypointPosition, activeMotionController)) {
(.nextPositionValid || numWaypoints == ) {
path.get(.currentWaypointIndex);
(wayPoint == ) {
;
}
.nodeViewDirection = wayPoint.getWaypointRotation(componentAccessor).getYaw();
.nodeWaitTime = wayPoint.getPauseTime();
.observationSector = wayPoint.getObservationAngle() / ;
.currentViewSegment = ;
(numWaypoints == ) {
.currentNodeDelay = MathUtil.maxValue(.nodeWaitTime, );
.pickNextObservationAngle();
desiredSteering.setYaw(heading);
;
}
}
.nextPositionValid = ;
(!.nextWayPoint(path, worldSupport, componentAccessor)) {
(worldSupport.hasRequestedNewPath()) {
desiredSteering.setTranslation(.previousSteeringTranslation);
}
;
}
(.currentWaypointIndex == lastIndex) {
;
}
}
(!.nextPositionValid || .closeToPosition(.nextPosition, activeMotionController)) {
(.pathWidth == ) {
.nextPosition.assign(.currentWaypointPosition);
} {
NPCPhysicsMath.dotProduct(.currentWaypointPosition, .lastWaypointPosition, .currentPosition, componentSelector);
Math.min(RandomExtra.randomRange(.minWalkDistance, .maxWalkDistance), maxDistance);
(distance >= maxDistance - .nodeWidth) {
.nextPosition.assign(.currentWaypointPosition);
} {
NPCPhysicsMath.orthoComposition(.lastWaypointPosition, .currentWaypointPosition, distance, Vector3d.UP, RandomExtra.randomRange(-.pathWidth / , .pathWidth / ), .nextPosition);
}
}
.nextPositionValid = ;
.currentSpeed = RandomExtra.randomRange(.minRelativeSpeed, .maxRelativeSpeed);
.steeringForcePursue.setTargetPosition(.nextPosition);
.steeringForcePursue.setDistances(.nodeWidth * , );
.steeringForcePursue.setComponentSelector(componentSelector);
((!.useNodeViewDirection || !(.minNodeDelay > )) && !(.nodeWaitTime > )) {
.steeringForceRotate.setDesiredHeading(NPCPhysicsMath.lookatHeading(.currentPosition, .nextPosition, heading));
.pendingNodeDelay = .minNodeDelay > ;
} {
.pickNextObservationAngle();
.rotatingToView = ;
.pendingNodeDelay = ;
}
.rotating = ;
}
(.rotating) {
.steeringForceRotate.setHeading(heading);
(.useNodeViewDirection && .rotatingToView) {
(.steeringForceRotate.compute(desiredSteering)) {
;
}
desiredSteering.setYaw(heading);
(.tickObservationDelay(dt)) {
;
}
.rotatingToView = ;
.steeringForceRotate.setDesiredHeading(NPCPhysicsMath.lookatHeading(.currentPosition, .nextPosition, heading));
(.minNodeDelay > ) {
.currentNodeDelay = RandomExtra.randomRange(.minNodeDelay, .maxNodeDelay);
}
(.nodeWaitTime > .currentNodeDelay) {
.currentNodeDelay = .nodeWaitTime;
}
(.currentNodeDelay > ) {
.pickNextObservationAngle();
}
;
}
(.steeringForceRotate.compute(desiredSteering)) {
;
}
(.pendingNodeDelay) {
.currentNodeDelay = RandomExtra.randomRange(.minNodeDelay, .maxNodeDelay);
.pendingNodeDelay = ;
;
}
.rotating = ;
}
.steeringForcePursue.setSelfPosition(.currentPosition);
.steeringForcePursue.setComponentSelector(activeMotionController.getComponentSelector());
.nextPositionValid = .steeringForcePursue.compute(desiredSteering);
(desiredSteering.hasTranslation()) {
desiredSteering.scaleTranslation(.currentSpeed);
}
.previousSteeringTranslation.assign(desiredSteering.getTranslation());
;
}
} {
;
}
}
}
{
(.currentObservationDelay > ) {
.currentObservationDelay -= dt;
;
} {
;
}
}
{
(.pickRandomAngle) {
RandomExtra.randomRange(-.observationSector, .observationSector);
.steeringForceRotate.setDesiredHeading(.nodeViewDirection + angle);
} (.viewSegments > ) {
.observationSector * ;
.nodeViewDirection - .observationSector;
fullSector / ()(.viewSegments - );
.currentViewSegment++;
.currentViewSegment %= .viewSegments;
.steeringForceRotate.setDesiredHeading(start + ()thisSegment * segment);
} {
.steeringForceRotate.setDesiredHeading(.nodeViewDirection + .observationSector);
.observationSector *= -;
}
.currentObservationDelay = .nodeWaitTime * RandomExtra.randomRange(.minDelayScale, .maxDelayScale);
.currentObservationDelay += .currentObservationDelay * RandomExtra.randomRange(.minPercentage, .maxPercentage);
}
{
motionController.waypointDistanceSquared(.currentPosition, position) <= .nodeWidth * .nodeWidth;
}
{
.currentWaypointIndex = -;
.currentDirection = ;
}
{
(.currentWaypointIndex == -) {
;
} {
path.length();
(.shape.ordinal()) {
:
:
:
(.direction == BodyMotionPath.Direction.RANDOM || .currentDirection == ) {
.currentDirection = RandomExtra.randomBoolean() ? BodyMotionPath.Direction.FORWARD : BodyMotionPath.Direction.BACKWARD;
}
.currentWaypointIndex += .currentDirection == BodyMotionPath.Direction.FORWARD ? : -;
(.currentWaypointIndex < || .currentWaypointIndex >= numWaypoints) {
(.shape == BodyMotionPath.Shape.LOOP) {
.currentWaypointIndex = (.currentWaypointIndex + numWaypoints) % numWaypoints;
} (.currentWaypointIndex < ) {
(.shape == BodyMotionPath.Shape.CHAIN) {
.currentWaypointIndex = -;
support.requestNewPath();
;
}
.currentWaypointIndex = ;
.currentDirection = BodyMotionPath.Direction.FORWARD;
} (.currentWaypointIndex >= numWaypoints) {
(.shape == BodyMotionPath.Shape.CHAIN) {
.currentWaypointIndex = -;
support.requestNewPath();
;
}
.currentWaypointIndex = numWaypoints - ;
.currentDirection = BodyMotionPath.Direction.BACKWARD;
}
}
;
:
(.direction == BodyMotionPath.Direction.RANDOM) {
RandomExtra.randomRange(numWaypoints);
(index == .currentWaypointIndex) {
index = (index + RandomExtra.randomRange() * - + numWaypoints) % numWaypoints;
}
.currentWaypointIndex = index;
} {
++.visitIndex;
(.visitIndex >= .visitOrder.size()) {
.visitIndex = ;
IntLists.shuffle(.visitOrder, ThreadLocalRandom.current());
}
(.visitOrder.getInt(.visitIndex) == .currentWaypointIndex) {
++.visitIndex;
}
.currentWaypointIndex = .visitOrder.getInt(.visitIndex);
}
.currentDirection = BodyMotionPath.Direction.FORWARD;
}
.waypointIndexUpdated(path, componentAccessor);
;
}
}
{
.invalidateWaypoint();
(path != && path.length() != ) {
.initializeCurrentDirection();
(.startAtNearestNode) {
;
(TransformComponent)componentAccessor.getComponent(ref, TransformComponent.getComponentType());
transformComponent != ;
transformComponent.getPosition();
role.getActiveMotionController();
( ; i < path.length(); ++i) {
path.get(i);
(pathWaypoint == ) {
;
}
activeMotionController.waypointDistanceSquared(pos, pathWaypoint.getWaypointPosition(componentAccessor));
(distance < distanceSquared) {
.currentWaypointIndex = i;
distanceSquared = distance;
}
}
(.shape.ordinal()) {
:
:
(.currentWaypointIndex == ) {
.currentDirection = BodyMotionPath.Direction.FORWARD;
} (.currentWaypointIndex == path.length() - ) {
.currentDirection = BodyMotionPath.Direction.BACKWARD;
}
:
:
;
:
(.direction != BodyMotionPath.Direction.RANDOM) {
IntLists.shuffle(.visitOrder, ThreadLocalRandom.current());
.visitIndex = .visitOrder.indexOf(.currentWaypointIndex);
}
}
} {
(.shape.ordinal()) {
:
:
.currentWaypointIndex = .currentDirection == BodyMotionPath.Direction.FORWARD ? : path.length() - ;
;
:
.currentWaypointIndex = ;
;
:
(.direction != BodyMotionPath.Direction.RANDOM) {
IntLists.shuffle(.visitOrder, ThreadLocalRandom.current());
.visitIndex = ;
.currentWaypointIndex = .visitOrder.getInt(.visitIndex);
} {
.currentWaypointIndex = RandomExtra.randomRange(path.length());
}
}
}
.waypointIndexUpdated(path, componentAccessor);
.lastWaypointPosition.assign(lastPos.getX(), lastPos.getY(), lastPos.getZ());
;
} {
;
}
}
{
path.get(.currentWaypointIndex);
(pathWaypoint != ) {
pathWaypoint.getWaypointPosition(componentAccessor);
.currentWaypointPosition.assign(pathWaypointPosition);
}
}
{
(.direction != BodyMotionPath.Direction.RANDOM && .direction != BodyMotionPath.Direction.ANY) {
.currentDirection = .direction;
} {
.currentDirection = RandomExtra.randomBoolean() ? BodyMotionPath.Direction.FORWARD : BodyMotionPath.Direction.BACKWARD;
}
}
{
.pendingNodeDelay = ;
.currentNodeDelay = ;
.nextPositionValid = ;
.currentViewSegment = ;
.nodeWaitTime = ;
.rotating = ;
}
<String> {
FORWARD(),
BACKWARD(),
RANDOM(),
ANY();
String description;
{
.description = description;
}
String {
.description;
}
}
<String> {
LINE(),
LOOP(),
POINTS(),
CHAIN();
String description;
{
.description = description;
}
String {
.description;
}
}
}