Class RailPath

java.lang.Object
com.hypixel.hytale.server.npc.movement.controllers.RailPath

public final class RailPath extends Object
Per-entity traversal state for a piecewise-linear path.

Authoritative for the entity's path while traversing: advance(Vector3dc, double, Vector3d) keeps the per-tick translation collinear with the segment direction it commits to. It can chain consecutive segments inside the same tick, but only when the next segment is collinear (same direction, same orientation) with the first segment of the tick. That preserves the dot-against-normal signature the grazing-collision filter in MotionControllerBase.applyRailStep(Ref, Role, Vector3dc, RailStepConfig, RailStepResult, ComponentAccessor) relies on at climb / drop / edge corners. Any unused step distance is banked into carryOverDistance (capped by CARRY_OVER_FACTOR) and consumed next call.

snapY(Vector3d) re-asserts the path's Y profile at the start of each tick so external physics (gravity, character pushback) cannot drift the entity off a CLIMB lip between ticks.

Intended to be owned by a single body-motion component instance.

  • Constructor Details

    • RailPath

      public RailPath()
    • RailPath

      public RailPath(int initialCapacity)
  • Method Details

    • reset

      public void reset()
    • capture

      public void capture(@Nonnull org.joml.Vector3d[] waypoints, int count)
      Replaces the path with the supplied waypoints (using the first count entries), dropping consecutive duplicates within MIN_WAYPOINT_OFFSET_SQ. Intended for callers that pre-process probeMove output (e.g. RailPathSmoother) and feed the result here.
    • capture

      public void capture(@Nonnull org.joml.Vector3d[] waypoints, @Nullable RailPath.SegmentCommitType[] segmentCommitTypes, int count)
      Replaces the path with the supplied waypoints (using the first count entries), dropping consecutive duplicates within MIN_WAYPOINT_OFFSET_SQ. segmentCommitTypes maps segment i -> i+1 to a commitment type and may be null when all segments are non-committed.
    • capture

      public void capture(@Nonnull RailPath source)
    • captureSuffixFromProjection

      public void captureSuffixFromProjection(@Nonnull RailPath source, @Nonnull RailPath.Projection projection)
      Replaces this path with source's suffix starting at projection. The first waypoint is the projected position, followed by the remaining source waypoints.
    • isEmpty

      public boolean isEmpty()
    • isFinished

      public boolean isFinished()
    • getWaypointCount

      public int getWaypointCount()
    • getWaypoint

      @Nonnull public org.joml.Vector3dc getWaypoint(int index)
    • getCursor

      public int getCursor()
    • getSegmentProgress

      public double getSegmentProgress()
    • isOnCommittedSegment

      public boolean isOnCommittedSegment()
    • getCommittedSegmentEndWaypointIndex

      public int getCommittedSegmentEndWaypointIndex()
    • getActiveSegmentCommitType

      @Nonnull public RailPath.SegmentCommitType getActiveSegmentCommitType()
    • getRemainingDistance

      public double getRemainingDistance()
    • projectRemaining

      public boolean projectRemaining(@Nonnull org.joml.Vector3dc position, @Nonnull RailPath.Projection result)
      Projects position onto the untraversed part of this path. The result is useful when deciding whether a newly-computed rail can safely replace the current one.
    • project

      public boolean project(@Nonnull org.joml.Vector3dc position, @Nonnull RailPath.Projection result)
    • remainingEquivalentTo

      public boolean remainingEquivalentTo(@Nonnull RailPath candidate, @Nonnull org.joml.Vector3dc currentPosition, double tolerance)
      Compares the current remaining suffix with a candidate path that starts at currentPosition. Changes behind the current cursor are ignored.
    • advance

      public void advance(@Nonnull org.joml.Vector3dc currentPosition, double stepDistance, @Nonnull org.joml.Vector3d out)
      Walks the path forward by stepDistance starting at the current cursor and writes the world-space offset for this tick into out.

      Behaviour:

      • If the current segment does not finish inside this tick, advances partially along it and updates segmentProgress.
      • If the current segment finishes inside this tick, snaps exactly to its end-waypoint (using currentPosition as the anchor so any accumulated drift from gravity, character pushback, or stopT clamping is absorbed by the snap rather than carried forward).
      • After a snap, may chain into subsequent segments (fully or partially) only while the next segment is collinear and same-orientation with the first segment of this tick (see COLLINEARITY_EPSILON). This preserves the dot(translation, collisionNormal) signature the grazing filter relies on.
      • Any remaining unspent budget is banked into carryOverDistance for the next call, capped at stepDistance * CARRY_OVER_FACTOR.
    • snapY

      public void snapY(@Nonnull org.joml.Vector3d position)
      Re-asserts the path's Y profile on position for the current cursor / segment progress.

      Between ticks the world physics integrator can drag the entity off the path in Y (gravity off a CLIMB lip is the common case). Calling this at the start of a tick, before issuing the next rail step, keeps the body sweep aligned with the path that probeMove already vetted. No-op when the path is finished or the deviation is below NPCPhysicsMath.EPSILON_LENGTH.