@hology/core 0.0.264 → 0.0.266

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/effects/sequence/sequence-player.js +1 -1
  2. package/dist/effects/vfx/gpu-material-uniforms.d.ts +23 -0
  3. package/dist/effects/vfx/gpu-material-uniforms.js +4 -0
  4. package/dist/effects/vfx/gpu-sprite-runtime.js +1 -1
  5. package/dist/effects/vfx/vfx-actor.d.ts +6 -0
  6. package/dist/effects/vfx/vfx-actor.js +1 -1
  7. package/dist/effects/vfx/vfx-materializer.d.ts +1 -0
  8. package/dist/effects/vfx/vfx-materializer.js +1 -1
  9. package/dist/effects/vfx/vfx-param.js +1 -1
  10. package/dist/effects/vfx/vfx-render-preparation.d.ts +8 -0
  11. package/dist/effects/vfx/vfx-render-preparation.js +4 -0
  12. package/dist/gameplay/actors/builtin/components/character/character-animation.d.ts +53 -0
  13. package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
  14. package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
  15. package/dist/gameplay/ai/behavior-tree/behavior-tree.d.ts +33 -0
  16. package/dist/gameplay/ai/behavior-tree/behavior-tree.js +4 -0
  17. package/dist/gameplay/ai/behavior-tree/behavior-tree.test.d.ts +2 -0
  18. package/dist/gameplay/ai/behavior-tree/behavior-tree.test.js +4 -0
  19. package/dist/gameplay/ai/behavior-tree/bt.d.ts +92 -70
  20. package/dist/gameplay/ai/behavior-tree/bt.js +1 -1
  21. package/dist/gameplay/ai/behavior-tree/bt.test.d.ts +2 -0
  22. package/dist/gameplay/ai/behavior-tree/bt.test.js +4 -0
  23. package/dist/gameplay/ai/behavior-tree/move.d.ts +1 -0
  24. package/dist/gameplay/ai/behavior-tree/move.js +1 -1
  25. package/dist/gameplay/ai/index.d.ts +1 -0
  26. package/dist/gameplay/ai/index.js +1 -1
  27. package/dist/gameplay/animation/foot-contact-baker.d.ts +23 -0
  28. package/dist/gameplay/animation/foot-contact-baker.js +4 -0
  29. package/dist/gameplay/animation/foot-contact.d.ts +27 -0
  30. package/dist/gameplay/animation/foot-contact.js +4 -0
  31. package/dist/gameplay/animation/locomotion-body.d.ts +62 -0
  32. package/dist/gameplay/animation/locomotion-body.js +4 -0
  33. package/dist/gameplay/animation/pose-inertialization.d.ts +46 -0
  34. package/dist/gameplay/animation/pose-inertialization.js +4 -0
  35. package/dist/gameplay/animation/root-motion.js +1 -1
  36. package/dist/gameplay/index.d.ts +4 -0
  37. package/dist/gameplay/index.js +1 -1
  38. package/dist/gameplay/initiate.js +1 -1
  39. package/dist/gameplay/input/input-service.d.ts +4 -0
  40. package/dist/gameplay/input/input-service.js +1 -1
  41. package/dist/gameplay/rendering-host.d.ts +2 -1
  42. package/dist/gameplay/rendering-host.js +1 -1
  43. package/dist/gameplay/services/physics/physics-system.d.ts +7 -0
  44. package/dist/gameplay/services/physics/physics-system.js +1 -1
  45. package/dist/gameplay/services/render.d.ts +2 -0
  46. package/dist/gameplay/services/render.js +1 -1
  47. package/dist/rendering/webgpu-experimental-backend.d.ts +1 -1
  48. package/dist/rendering/webgpu-experimental-backend.js +1 -1
  49. package/dist/rendering.d.ts +4 -2
  50. package/dist/rendering.js +1 -1
  51. package/dist/scene/animation-binary.d.ts +6 -0
  52. package/dist/scene/animation-binary.js +4 -0
  53. package/dist/scene/asset-resource-loader.d.ts +3 -1
  54. package/dist/scene/asset-resource-loader.js +1 -1
  55. package/dist/scene/landscape/landscape-manager.d.ts +4 -1
  56. package/dist/scene/landscape/landscape-manager.js +1 -1
  57. package/dist/scene/landscape/landscape-static-draw-sets.d.ts +18 -0
  58. package/dist/scene/landscape/landscape-static-draw-sets.js +4 -0
  59. package/dist/scene/materializer.d.ts +2 -0
  60. package/dist/scene/materializer.js +1 -1
  61. package/dist/shader/shader.d.ts +8 -0
  62. package/dist/test/animation-binary.test.d.ts +2 -0
  63. package/dist/test/animation-binary.test.js +4 -0
  64. package/dist/test/character-foot-contact.test.d.ts +2 -0
  65. package/dist/test/character-foot-contact.test.js +4 -0
  66. package/dist/test/character-inertialization.test.d.ts +2 -0
  67. package/dist/test/character-inertialization.test.js +4 -0
  68. package/dist/test/character-movement-solve.test.d.ts +2 -0
  69. package/dist/test/character-movement-solve.test.js +4 -0
  70. package/dist/test/foot-contact.test.d.ts +2 -0
  71. package/dist/test/foot-contact.test.js +4 -0
  72. package/dist/test/gpu-material-uniforms.test.d.ts +2 -0
  73. package/dist/test/gpu-material-uniforms.test.js +4 -0
  74. package/dist/test/gpu-sprite-pipeline-cache.test.d.ts +2 -0
  75. package/dist/test/gpu-sprite-pipeline-cache.test.js +4 -0
  76. package/dist/test/input.test.js +1 -1
  77. package/dist/test/landscape-static-draw-sets.test.d.ts +2 -0
  78. package/dist/test/landscape-static-draw-sets.test.js +4 -0
  79. package/dist/test/locomotion-body.test.d.ts +2 -0
  80. package/dist/test/locomotion-body.test.js +4 -0
  81. package/dist/test/physics-ray-object.test.d.ts +2 -0
  82. package/dist/test/physics-ray-object.test.js +4 -0
  83. package/dist/test/pose-inertialization.test.d.ts +2 -0
  84. package/dist/test/pose-inertialization.test.js +4 -0
  85. package/dist/test/renderer-loading.test.d.ts +2 -0
  86. package/dist/test/renderer-loading.test.js +4 -0
  87. package/dist/test/rendering-host.test.js +1 -1
  88. package/dist/test/sequence-property-parameters.test.js +1 -1
  89. package/dist/test/sequence-vfx.test.js +1 -1
  90. package/dist/test/vfx-render-preparation.test.d.ts +2 -0
  91. package/dist/test/vfx-render-preparation.test.js +4 -0
  92. package/dist/utils/structs.d.ts +4 -0
  93. package/dist/utils/structs.js +4 -0
  94. package/package.json +4 -2
  95. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import i from"@dimforge/rapier3d-simd-compat";import{takeUntil as o}from"rxjs";import*as s from"three";import{ArrowHelper as n,MathUtils as r,Quaternion as a,Vector3 as h}from"three";import{RootMotionClip as l}from"../../../../animation/root-motion.js";import{inject as c}from"../../../../inject.js";import{ActionInput as d,AxisInput as u,RotationInput as p}from"../../../../input/index.js";import{NetRole as m}from"../../../../net/service/net-actor-role.js";import{RunOnClient as y,RunOnNotOwner as v,RunOnServer as g}from"../../../../net/service/rpc-decorator.js";import{NetService as S}from"../../../../net/service/net-service.js";import{PhysicsSystem as M,RayTestResult as f}from"../../../../services/physics/physics-system.js";import{CapsuleCollisionShape as x}from"../../../../../scene/collision/collision-shape.js";import{Parameter as T}from"../../../../../shader/parameter.js";import{PhysicsBodyType as C}from"../../../../services/physics/physics-system.js";import{ActorComponent as w,Component as R}from"../../../component.js";import{CharacterMovementMode as A}from"./modes.js";import{calculateRootMotionTargetApproachCorrection as D,constrainRootMotionTargetApproach as q,warpRootMotionTargetApproach as b}from"./root-motion-constraint.js";import{DEFAULT_MAX_CLIENT_TIME_AHEAD as z,DEFAULT_LARGE_CORRECTION_THRESHOLD as k,DEFAULT_MAX_COMBINED_MOVE_DELTA_TIME as P,DEFAULT_MAX_MOVE_DELTA_TIME as I,DEFAULT_MAX_MOVES_PER_PACKET as O,DEFAULT_MAX_REPLAYED_MOVES as j,DEFAULT_MAX_SERVER_MOVES_PER_TICK as G,DEFAULT_MAX_SAVED_MOVES as Y,DEFAULT_MAX_SERVER_MOVE_DELTA_TIME_SCALAR as N,DEFAULT_MAX_SERVER_MOVE_TIME_BUDGET as F,DEFAULT_MAX_SUBSTEP_DELTA_TIME as V,DEFAULT_MOVE_SEND_INTERVAL as H,DEFAULT_SIMULATED_INTERPOLATION_DELAY as U,DEFAULT_SIMULATED_STATE_INTERVAL as X,DEFAULT_SMALL_CORRECTION_TOLERANCE as E,DEFAULT_TELEPORT_SNAP_THRESHOLD as L,MOVE_FLAG_CROUCH as B,MOVE_FLAG_JUMP as Z,MOVE_FLAG_ROOT_MOTION as W,MOVE_FLAG_SLIDE_START as $,MOVE_FLAG_SPRINT as Q,MOVE_FLAG_SPRINT_START as J,SNAPSHOT_FLAG_CROUCH_SUPPRESSED as K,SNAPSHOT_FLAG_CROUCHING as _,NetCharacterProxySmoother as tt,NetCharacterSavedMoveBuffer as et,accrueNetCharacterServerMoveTime as it,createNetCharacterMovementSnapshot as ot,createNetCharacterServerMoveTimingState as st,consumeNetCharacterServerMoveTime as nt,decodeNetCharacterMoveBatch as rt,decodeNetCharacterOwnerAck as at,decodeNetCharacterOwnerCorrection as ht,decodeNetCharacterSimulatedState as lt,encodeNetCharacterMoveBatch as ct,encodeNetCharacterOwnerAck as dt,encodeNetCharacterOwnerCorrection as ut,encodeNetCharacterSimulatedState as pt,validateNetCharacterMove as mt}from"./net-character-movement-protocol.js";import{NetMode as yt}from"../../../../net/net-session.js";import{setSlideJumpVelocity as vt,shouldContinueSlide as gt,shouldStartSlide as St,updateSlideVelocity as Mt,updateSlideVelocityFromDisplacement as ft}from"./character-slide.js";export*from"./net-character-movement-protocol.js";const xt=131070,Tt=new h(0,1,0),Ct=new h,wt=new h,Rt=new h,At=new h,Dt=new h,qt=new h,bt=new h,zt=new h,kt=new h,Pt=new h,It=new h,Ot=new h,jt=new h,Gt=new h,Yt=new h(0,1,0),Nt=new h(0,-.05,0),Ft=new h,Vt=new a,Ht=new s.Euler,Ut=new h,Xt=new h,Et=new h,Lt=new h,Bt=new i.CharacterCollision;let Zt=class extends w{get autoStepMinWidth(){return this.cc.autostepMinWidth()}set autoStepMinWidth(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),t,this.cc.autostepIncludesDynamicBodies())}get autoStepDynamicObjects(){return this.cc.autostepIncludesDynamicBodies()}set autoStepDynamicObjects(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),this.cc.autostepMinWidth(),t)}get autoStepMaxHeight(){return this.cc.autostepMaxHeight()}set autoStepMaxHeight(t){this.cc.enableAutostep(t,this.cc.autostepMinWidth(),this.cc.autostepIncludesDynamicBodies())}get snapToGround(){return this.cc.snapToGroundDistance()}set snapToGround(t){this.cc.enableSnapToGround(t)}set offset(t){this.cc.setOffset(t)}get offset(){return this.cc.offset()}set normalNudgeFactor(t){this.cc.setNormalNudgeFactor(t)}get normalNudgeFactor(){return this.cc.normalNudgeFactor()}teleport(t,e=this.actor.rotation.y){this.state.position.copy(t),this.state.velocity.set(0,0,0),this.state.yaw=e,this.actor.position.copy(t),this.actor.rotation.y=e,this.rotationInput.rotation.y=e,this.physicsSystem.setPosition(this.actor,t),this.physicsSystem.setRotation(this.actor,this.actor.quaternion),this.physicsSystem.flushModifiedBodyPositionsToColliders()}constructor(){super(),this.isDefaultCharacterMovementComponent=!0,this.directionInput=new u,this.jumpInput=new d,this.sprintInput=new d,this.crouchInput=new d,this.rotationInput=new p,this.horizontalSpeed=0,this.maxSpeed=8,this.maxSpeedBackwards=8,this.maxSpeedSprint=12,this.maxSpeedCrouch=4,this.slideEnabled=!1,this.slideMinStartSpeed=8,this.slideMinExitSpeed=4,this.slideDeceleration=3,this.slideGravityScale=1,this.slideSteeringRate=2,this.sprintStartBoostSpeed=0,this.sprintStartBoostDamping=6,this.jumpVelocity=7,this.fallingMovementControl=.5,this.fallingReorientation=!1,this.groundAccelerationRate=4,this.gravityOverride=null,this.colliderHeight=2,this.colliderRadius=.5,this.crouchColliderHeight=1,this.crouchColliderRadius=null,this.jumpInAir=!1,this.mass=50,this.allowSliding=!0,this.minSlopeSlideAngle=r.degToRad(70),this.maxSlopeClimbAngle=r.degToRad(70),this.applyImpulsesToDynamicBodies=!0,this.normalizedDirection=!0,this.characterCollision=!1,this.allowRootMotionJumpCancel=!1,this.enabled=!0,this.rotateToMovementDirection=!1,this.smoothRotation=!0,this.rotationSpeed=40,this.maxRotationSpeed=100,this.impulseDamping=2,this.moveSendInterval=H,this.simulatedStateInterval=X,this.maxSavedMoves=Y,this.maxReplayedMoves=j,this.maxServerMovesPerTick=G,this.maxMovesPerPacket=O,this.maxMoveDeltaTime=I,this.maxCombinedMoveDeltaTime=P,this.maxServerMoveDeltaTimeScalar=N,this.maxClientTimeAhead=z,this.maxServerMoveTimeBudget=F,this.maxSubstepDeltaTime=V,this.fallGraceTime=.1,this.correctionToleranceSq=E*E,this.largeCorrectionThreshold=k,this.teleportSnapThreshold=L,this.listenServerSmoothing=!0,this.listenServerSmoothLocationTime=.04,this.listenServerMaxSmoothUpdateDistance=1,this.listenServerNoSmoothUpdateDistance=2.5,this.debugCorrections=!0,this.suppressUncrouchLift=!1,this.velocity=new h,this.visualSmoothingOffset=new h,this.slideDirection=new h,this.slideSurfaceNormal=new h(0,1,0),this.mode=A.walking,this.isSprinting=!1,this.isCrouching=!1,this.isSliding=!1,this.pressedJump=!1,this.rayTestResult=new f,this.groundRayTestOptions={debug:!1,excludeTriggers:!0,excludeActor:void 0,resolveActor:!1},this.physicsSystem=c(M),this.netService=c(S),this.state={sequence:0,position:new h,velocity:new h,yaw:0,lookYaw:0,mode:A.walking,grounded:!1,currentSpeed:0,fallGraceTime:0,prevInputDirection:new h,prevRotateToMovementDirection:!1},this.movementModes=new Map,this.savedMoves=new et(Y),this.serverMoveTiming=st(),this.serverMoveQueue=[],this.inputMoveScratch={sequence:0,clientTime:0,dt:0,inputX:0,inputY:0,yaw:0,flags:0,clientX:0,clientY:0,clientZ:0,rootMotionX:0,rootMotionY:0,rootMotionZ:0},this.authoritativeMoveScratch={sequence:0,clientTime:0,dt:0,inputX:0,inputY:0,yaw:0,flags:0,clientX:0,clientY:0,clientZ:0,rootMotionX:0,rootMotionY:0,rootMotionZ:0},this.movementModeContext={component:this,state:this.state,move:this.inputMoveScratch,deltaTime:0,rotatedDirection:wt,platformVelocity:At,outVelocity:Rt,rootMotionActive:!1,startedSprinting:!1},this.proxySmoother=new tt(U,L),this.proxySample=ot(),this.pendingSnapshot=ot(),this.impulse=new h,this.prevRootMotionPos=new h,this.rootMotionOptions={},this.rootMotionTargetConstraints=new Set,this.resetRootMotion=!1,this.nextMoveSequence=0,this.clientMoveTime=0,this.lastSentClientMoveTime=0,this.moveSendAccumulator=0,this.simulatedStateAccumulator=0,this.proxyTime=0,this.lastServerProcessedSequence=0,this.lastServerReceivedSequence=0,this.lastAutonomousMoveFlags=0,this.previousSprintInput=!1,this.previousCrouchInput=!1,this.crouchSuppressedUntilRelease=!1,this.slideOnLandingRequested=!1,this.initialized=!1,this.cc=this.physicsSystem.getCharacterController(.1),this.cc.enableSnapToGround(.1),this.cc.enableAutostep(0,.1,!1),this.registerMovementMode(Wt),this.registerMovementMode($t),this.registerMovementMode({mode:A.sliding,update:t=>this.updateSlidingMode(t)})}onInit(){this.groundRayTestOptions.excludeActor=this.actor,this.configureCharacterController(),this.physicsSystem.addActor(this.actor,[this.createCollisionShape()],{mass:0,type:C.kinematic,continousCollisionDetection:!1,friction:0,restitution:.5,ignoreForNavMesh:!0}),this.rotationInput.rotation.copy(this.actor.rotation),this.initializeStateFromActor(),this.initialized=!0,this.physicsSystem.beforeStep.pipe(o(this.disposed)).subscribe(t=>this.tick(t))}onLateUpdate(t){this.updateVisualSmoothing(t)}registerMovementMode(t){this.movementModes.set(t.mode,t)}applyImpulse(t){this.impulse.add(t)}getEffectiveGravity(){return this.gravityOverride??this.physicsSystem.getGravity().y}get isGrounded(){return this.rayTestResult.hasHit||this.cc.computedGrounded()}setRootMotionAction(t,e={}){const i=t?.getClip();if(i instanceof l){this.rootMotionAction=t,this.rootMotionOptions=e,this.resetRootMotion=!0;const o=[];this.rootMotionInterpolant=i.motionTrack.InterpolantFactoryMethodSmooth(o);const n=s.PropertyBinding.parseTrackName(i.motionTrack.name);this.rootMotionRootBone=this.actor.object.getObjectByName(n.nodeName)}}addRootMotionTargetConstraint(t,e,i=0){const o={targetPosition:t,minimumHorizontalDistance:Math.max(0,e),maximumAddedHorizontalDistance:Math.max(0,i),initialHorizontalDistance:Math.hypot(t.x-this.actor.position.x,t.z-this.actor.position.z),addedHorizontalDistance:0,requestedProgress:0};this.rootMotionTargetConstraints.add(o);let s=!1;return{setProgress:t=>{o.requestedProgress=Math.max(o.requestedProgress,Math.min(1,Math.max(0,t)))},dispose:()=>{s||(s=!0,this.rootMotionTargetConstraints.delete(o))}}}serverMove(t){const e=rt(t);if(e.ok)for(const t of e.value.moves)mt(t,this.lastServerReceivedSequence,this.maxMoveDeltaTime)&&(this.lastServerReceivedSequence=t.sequence,this.serverMoveQueue.push(t))}clientMoveAck(t){const e=at(t);e.ok&&this.actor.netRole===m.autonomousProxy&&(this.savedMoves.ack(e.value.sequence),this.sprintPolicy?.ack?.(e.value.sequence,!1))}clientMoveCorrection(t){const e=ht(t);e.ok&&this.actor.netRole===m.autonomousProxy&&(this.debugCorrections&&(null==this.correctionDebug&&(this.correctionDebug=new _t(ee(this.actor.object))),this.correctionDebug.update(this.state.position,e.value.snapshot)),this.applyCorrection(e.value.snapshot))}simulatedState(t){const e=lt(t);e.ok&&this.actor.netRole===m.simulatedProxy&&this.proxySmoother.push(e.value,this.proxyTime)}tick(t){if(!this.initialized)return;t=Math.min(.1,t);const e=this.actor.netRole,i=this.netService.mode;e!==m.simulatedProxy?this.enabled&&(e!==m.autonomousProxy?this.isRemoteControlledAuthority(i,e)?this.tickRemoteAuthority(t):this.tickAuthority(t,i):this.tickAutonomousProxy(t)):this.tickSimulatedProxy(t)}tickAutonomousProxy(t){const e=this.state.mode,i=this.lastAutonomousMoveFlags,o=this.createMoveFromInput(t,++this.nextMoveSequence,{quantizeClientTime:!0});this.performMove(o,ie),this.resetToggleCrouchAfterSlide(e);const s=this.state.mode!==e||o.flags!==i;this.lastAutonomousMoveFlags=o.flags,this.savedMoves.capacity=this.maxSavedMoves,this.savedMoves.maxCombinedDeltaTime=Math.min(this.maxCombinedMoveDeltaTime,this.maxMoveDeltaTime),this.savedMoves.push(o),this.sendSavedMoves(t,s)}tickAuthority(t,e){const i=this.state.mode,o=this.createMoveFromInput(t,++this.nextMoveSequence);this.performMove(o,ie),this.resetToggleCrouchAfterSlide(i),e!==yt.none&&this.sendSimulatedState(t,!1)}resetToggleCrouchAfterSlide(t){t===A.sliding&&this.state.mode!==A.sliding&&"toggle"===this.crouchInput.mode&&this.crouchInput.activated&&this.crouchInput.setActivated(!1)}tickRemoteAuthority(t){it(this.serverMoveTiming,t,this.maxServerMoveTimeBudget);let e=!1;const i=Number.isFinite(this.maxServerMovesPerTick)?Math.max(1,Math.floor(this.maxServerMovesPerTick)):this.serverMoveQueue.length,o=Math.min(this.serverMoveQueue.length,i),s=Et.copy(this.actor.position);let n=!1;for(let t=0;t<o;t++){const t=this.serverMoveQueue.shift();if(null==t)break;if(!mt(t,this.lastServerProcessedSequence,this.maxMoveDeltaTime)){console.log("Net: Invalid move",t),this.sendOwnerCorrection(!0),e=!0;continue}const i=nt(this.serverMoveTiming,t,{maxMoveDeltaTime:this.maxMoveDeltaTime,maxServerMoveDeltaTimeScalar:this.maxServerMoveDeltaTimeScalar,maxClientTimeAhead:this.maxClientTimeAhead});if(i<0){this.sendOwnerCorrection(!0),e=!0;continue}const o=Jt(t,this.authoritativeMoveScratch);o.dt=i,o.rootMotionX=0,o.rootMotionY=0,o.rootMotionZ=0,o.flags&=~W,this.performMove(o,{immediate:!0,savedRootMotion:!1}),n=!0,this.lastServerProcessedSequence=o.sequence;const s=Kt(this.state,t);if(s>this.correctionToleranceSq){console.log(`Net server: Correction error: ${Math.sqrt(s)}`);const o=this.state.position.x-t.clientX,n=this.state.position.y-t.clientY,r=this.state.position.z-t.clientZ;console.log(`diff x: ${o}, y: ${n}, z: ${r}`),console.log({sequence:t.sequence,moveDt:t.dt,serverMoveDeltaTime:i,flags:t.flags,mode:this.state.mode,grounded:this.state.grounded,fallGraceTime:this.state.fallGraceTime}),this.sendOwnerCorrection(s>this.largeCorrectionThreshold*this.largeCorrectionThreshold),e=!0}}0===this.lastServerProcessedSequence||e||(this.sprintPolicy?.ack?.(this.lastServerProcessedSequence,!1),this.clientMoveAck(dt(this.lastServerProcessedSequence))),n&&this.accumulateListenServerVisualSmoothing(s,this.actor.position),this.sendSimulatedState(t,!1)}tickSimulatedProxy(t){this.proxyTime+=t,this.proxySmoother.sample(this.proxyTime,this.proxySample)&&this.applySnapshot(this.proxySample,!0)}accumulateListenServerVisualSmoothing(t,e){if(!this.shouldSmoothListenServerRemoteAuthority())return void this.visualSmoothingOffset.set(0,0,0);Lt.subVectors(t,e);const i=Lt.lengthSq();i>1e-8&&(i>this.listenServerNoSmoothUpdateDistance*this.listenServerNoSmoothUpdateDistance?this.visualSmoothingOffset.set(0,0,0):(i>this.listenServerMaxSmoothUpdateDistance*this.listenServerMaxSmoothUpdateDistance&&Lt.setLength(this.listenServerMaxSmoothUpdateDistance),this.visualSmoothingOffset.add(Lt)))}updateVisualSmoothing(t){if(this.visualSmoothingOffset.lengthSq()<=1e-8)return void this.visualSmoothingOffset.set(0,0,0);if(!this.shouldSmoothListenServerRemoteAuthority())return void this.visualSmoothingOffset.set(0,0,0);const e=Math.max(.001,this.listenServerSmoothLocationTime);t<e?this.visualSmoothingOffset.multiplyScalar(1-t/e):this.visualSmoothingOffset.set(0,0,0),this.visualSmoothingOffset.lengthSq()<=1e-4&&this.visualSmoothingOffset.set(0,0,0)}shouldSmoothListenServerRemoteAuthority(){return this.listenServerSmoothing&&this.actor.netRole===m.authority&&this.netService.isServer&&!this.netService.isDedicatedServer&&this.isRemoteControlledAuthority()}createMoveFromInput(t,e,i={}){const o=r.clamp(t,.001,this.maxMoveDeltaTime);this.clientMoveTime+=o;let s=this.clientMoveTime,n=o;!0===i.quantizeClientTime&&(s=Math.max(this.lastSentClientMoveTime+.001,Math.round(1e3*this.clientMoveTime)/1e3),n=r.clamp(s-this.lastSentClientMoveTime,.001,this.maxMoveDeltaTime),this.lastSentClientMoveTime=s),this.sampleRootMotion(bt);const a=this.crouchInput.activated,h=a&&!this.previousCrouchInput;this.previousCrouchInput=a;const l=!a&&this.sprintInput.activated,c=l&&!this.previousSprintInput;this.previousSprintInput=l;const d=(this.jumpInput.activated?Z:0)|(l?Q:0)|(a?B:0)|(h&&this.slideEnabled?$:0)|(c?J:0)|(bt.lengthSq()>0?W:0),u=function(t,e){e.set(t.x,0,t.y),e.lengthSq()>1&&e.normalize();return e}(this.directionInput.vector,Ut),p=this.inputMoveScratch;return p.sequence=e>>>0,p.clientTime=s,p.dt=n,p.inputX=u.x,p.inputY=u.z,p.yaw=this.rotationInput.rotation.y,p.flags=d,p.clientX=this.state.position.x,p.clientY=this.state.position.y,p.clientZ=this.state.position.z,p.rootMotionX=bt.x,p.rootMotionY=bt.y,p.rootMotionZ=bt.z,p}performMove(t,e){const i=r.clamp(t.dt,.001,this.maxMoveDeltaTime),o=Math.max(1,Math.ceil(i/this.maxSubstepDeltaTime)),s=0!==(t.flags&Q)&&0===(t.flags&B);this.sprintPolicy?.update?.(i,t.sequence,s),Ot.set(e.savedRootMotion?t.rootMotionX:0,e.savedRootMotion?t.rootMotionY:0,e.savedRootMotion?t.rootMotionZ:0),e.savedRootMotion||this.sampleRootMotion(Ot);let n=i;const a=i/o;for(let s=0;s<o;s++){const o=i>0?a/i:1;this.performSubstep(t,Math.min(a,n),Ot,o,e.immediate,0===s),n-=a}t.clientX=this.state.position.x,t.clientY=this.state.position.y,t.clientZ=this.state.position.z,t.flags=Ot.lengthSq()>0?t.flags|W:t.flags&~W,this.state.sequence=t.sequence,this.syncPublicState()}performSubstep(t,e,i,o,s,n){if(e<.001)return;this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded;const r=null!=this.rootMotionAction&&this.rootMotionAction.enabled,a=i.lengthSq()>0,h=!r&&0!==(t.flags&Z),l=r||a;this.updateCrouchState(t,n,l,h),this.pressedJump=h,this.isSprinting=!1,this.updateRotation(t,e,r,a),this.resolvePlatformVelocity(At);const c=this.movementModeContext,d=this.movementModes.get(this.state.mode);if(null!=d){c.move=t,c.deltaTime=e,c.rootMotionActive=l,c.startedSprinting=n&&!l&&0===(t.flags&B)&&0!==(t.flags&J);const i=d.update(c);"number"==typeof i&&(this.state.mode=i)}else Rt.set(0,0,0);if(a){zt.copy(i).multiplyScalar(o).applyQuaternion(this.actor.quaternion),kt.copy(zt).divideScalar(e),this.state.mode===A.walking?(Rt.x=kt.x+At.x,Rt.z=kt.z+At.z):(Rt.x=kt.x,Rt.z=kt.z);const t=Math.sqrt(kt.x*kt.x+kt.z*kt.z);t>.4&&(this.state.currentSpeed=t)}if(this.applyImpulseToVelocity(Rt,e),h&&this.isSprinting){const t=Math.max(0,this.maxSpeedSprint),e=Qt(Rt);if(e>t){const i=t/e;Rt.x*=i,Rt.z*=i,this.state.velocity.x*=i,this.state.velocity.z*=i}}this.state.mode===A.walking&&this.state.velocity.copy(Rt),this.applyMovement(Rt,e,s),this.state.mode===A.sliding&&(ft(this.state.velocity,qt,At,this.slideSurfaceNormal,e),this.state.currentSpeed=Qt(this.state.velocity)),this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded,this.updateModeAfterMove(Rt,e),this.state.mode===A.sliding&&this.state.velocity.length()<Math.max(0,this.slideMinExitSpeed)&&(this.state.mode=A.walking)}updateRotation(t,e,i,o){Ct.set(-t.inputX,0,t.inputY),Ct.lengthSq()>1&&Ct.normalize();const s=this.state.prevRotateToMovementDirection!==this.rotateToMovementDirection;let n=r.euclideanModulo(t.yaw-this.state.lookYaw+Math.PI,2*Math.PI)-Math.PI;if(s&&(this.actor.object.quaternion.setFromEuler(Ht.set(0,t.yaw,0)),n=0,this.state.lookYaw=t.yaw,this.state.prevRotateToMovementDirection=this.rotateToMovementDirection),wt.set(0,0,0),i)this.state.lookYaw=t.yaw;else if(this.rotateToMovementDirection){if(Ct.lengthSq()>0&&this.state.mode!==A.falling){const i=Ht.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,o=Math.atan2(Ct.x,Ct.z),s=.99*t.yaw+o;if(this.smoothRotation){const t=r.euclideanModulo(s-i+Math.PI,2*Math.PI)-Math.PI;let o=r.clamp(t*this.rotationSpeed*e,-this.maxRotationSpeed*e,this.maxRotationSpeed*e);Math.abs(o)>Math.abs(t)&&(o=t),this.actor.object.quaternion.setFromEuler(Ht.set(0,i+o,0))}else this.actor.object.quaternion.setFromEuler(Ht.set(0,s,0));this.state.prevInputDirection.lerp(Ct,e*this.rotationSpeed),this.state.lookYaw+=n,wt.copy(this.actor.object.getWorldDirection(Ut).normalize())}}else o||(this.state.lookYaw=t.yaw,this.actor.object.quaternion.setFromEuler(Ht.set(0,t.yaw,0)),Ct.lengthSq()>0&&wt.copy(Ct).applyAxisAngle(Tt,t.yaw).normalize())}applyMovement(t,e,i){if(t.lengthSq()>0||!this.state.grounded){if(Dt.copy(t).multiplyScalar(e),this.state.grounded&&((o=this.state.mode)===A.walking||o===A.sliding)&&(this.state.mode===A.walking&&this.rayTestResult.distance<=this.cc.offset()&&(Dt.y=Math.max(0,At.y*e)),this.physicsSystem.getActorComputedMovement(this.actor,this.cc,Dt,this.getCollisionGroup()),this.cc.computedCollision(0,Bt),null!=Bt.normal1)){const t=Ut.copy(Bt.normal1);Math.acos(r.clamp(t.dot(Tt),-1,1))>this.cc.maxSlopeClimbAngle()&&(Dt.y=.016*this.getEffectiveGravity()*.5)}qt.copy(this.physicsSystem.getActorComputedMovement(this.actor,this.cc,Dt,this.getCollisionGroup()))}else qt.set(0,0,0);var o;this.suppressUncrouchLift&&(this.suppressUncrouchLift=!1,this.state.grounded&&this.state.mode===A.walking&&Dt.y<=1e-6&&qt.y>0&&(qt.y=0)),this.state.position.add(qt),i?(this.actor.position.copy(this.state.position),this.physicsSystem.updateActorTransform(this.actor),this.physicsSystem.flushModifiedBodyPositionsToColliders()):this.physicsSystem.setNextKinematicPosition(this.actor,this.state.position)}updateModeAfterMove(t,e){const i=function(t){if(0===t.numComputedCollisions())return!1;const e=t.computedCollision(0);Ft.set(e.normal2.x,e.normal2.y,e.normal2.z);const i=Ft.angleTo(Tt);Ft.set(e.normal1.x,e.normal1.y,e.normal1.z);const o=Ft.angleTo(Tt);if(i<100)return!1;return o>t.minSlopeSlideAngle()}(this.cc);!this.state.grounded||i?this.state.mode!==A.falling&&(this.state.fallGraceTime+=e,this.state.fallGraceTime>this.fallGraceTime+1e-6&&(this.state.mode=A.falling,this.state.velocity.copy(t))):this.state.velocity.y<=0&&(this.state.mode===A.falling&&(this.state.mode=A.walking),this.state.mode!==A.sliding&&(this.state.velocity.y=0),this.state.fallGraceTime=0)}applyImpulseToVelocity(t,e){if(this.impulse.lengthSq()<=.1)return void this.impulse.set(0,0,0);const i=Math.min(1,this.impulse.length()/5);t.x=r.lerp(t.x,this.impulse.x,i),t.z=r.lerp(t.z,this.impulse.z,i),t.y+=this.impulse.y;const o=Math.exp(-this.impulseDamping*e);this.impulse.x*=o,this.impulse.y>0?this.impulse.y+=e*this.getEffectiveGravity():this.impulse.y*=o,this.impulse.z*=o}sendSavedMoves(t,e=!1){if(this.moveSendAccumulator+=t,!e&&this.moveSendAccumulator<this.moveSendInterval)return;this.moveSendAccumulator=0;const i=this.savedMoves.getMovesForSend(this.maxMovesPerPacket);0!==i.length&&this.serverMove(ct(i))}sendOwnerCorrection(t){const e=this.toSnapshot(this.pendingSnapshot);t&&(e.horizontalSpeed=this.horizontalSpeed),this.sprintPolicy?.ack?.(e.sequence,!0),this.clientMoveCorrection(ut(e))}sendSimulatedState(t,e){this.simulatedStateAccumulator+=t,!e&&this.simulatedStateAccumulator<this.simulatedStateInterval||(this.simulatedStateAccumulator=0,this.simulatedState(pt(this.toSnapshot(this.pendingSnapshot))))}applyCorrection(t){this.sprintPolicy?.restore?.(t.sequence),this.savedMoves.ack(t.sequence),this.sprintPolicy?.ack?.(t.sequence,!0),this.applySnapshot(t,!0),this.savedMoves.replayAfter(t.sequence,t=>(this.performMove(t,{immediate:!0,savedRootMotion:!0}),null),this.maxReplayedMoves)}applySnapshot(t,e){this.state.sequence=t.sequence,this.state.position.set(t.x,t.y,t.z),this.state.velocity.set(t.velocityX,t.velocityY,t.velocityZ),this.state.yaw=t.yaw,this.state.lookYaw=t.yaw,this.state.mode=t.mode,this.state.currentSpeed=t.horizontalSpeed,this.state.fallGraceTime=0,this.actor.position.copy(this.state.position),this.actor.object.quaternion.setFromEuler(Ht.set(0,t.yaw,0)),this.crouchSuppressedUntilRelease=0!==(t.flags&K),this.setCrouching(0!==(t.flags&_)||t.mode===A.sliding),e&&(this.physicsSystem.updateActorTransform(this.actor),this.physicsSystem.flushModifiedBodyPositionsToColliders()),this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded,this.syncPublicState()}toSnapshot(t){return t.sequence=this.state.sequence,t.x=this.state.position.x,t.y=this.state.position.y,t.z=this.state.position.z,t.velocityX=this.state.velocity.x,t.velocityY=this.state.velocity.y,t.velocityZ=this.state.velocity.z,t.yaw=Ht.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,t.mode=this.state.mode,t.flags=(this.isCrouching?_:0)|(this.crouchSuppressedUntilRelease?K:0),t.horizontalSpeed=this.state.currentSpeed,t}syncPublicState(){this.velocity.copy(this.state.velocity),this.mode=this.state.mode,this.horizontalSpeed=this.state.currentSpeed,this.isSliding=this.state.mode===A.sliding,this.isSliding?(this.resolveGroundNormal(this.slideSurfaceNormal),this.slideDirection.copy(this.state.velocity).projectOnPlane(this.slideSurfaceNormal),this.slideDirection.lengthSq()>1e-8?this.slideDirection.normalize():this.slideDirection.set(0,0,0)):(this.slideDirection.set(0,0,0),this.slideSurfaceNormal.copy(Tt))}sampleRootMotion(t){if(t.set(0,0,0),null==this.rootMotionAction||this.rootMotionAction.isRunning()||this.clearRootMotionAction(this.rootMotionAction),null!=this.rootMotionAction&&this.rootMotionOptions.cancelWithJump&&this.jumpInput.activated&&(this.isGrounded||this.jumpInAir)){const e=this.rootMotionAction,i=this.rootMotionOptions.onJumpCancel;return this.clearRootMotionAction(e),e.stop(),i?.(),t}if(null==this.rootMotionAction)return t;if(!(this.rootMotionAction.getClip()instanceof l))return t;const e=this.rootMotionInterpolant;this.resetRootMotion&&(this.prevRootMotionPos.fromArray(e.evaluate(0)),this.resetRootMotion=!1),It.fromArray(e.evaluate(this.rootMotionAction.time)),t.subVectors(It,this.prevRootMotionPos),this.prevRootMotionPos.copy(It);if((this.rootMotionRootBone??this.rootMotionAction.getRoot()).getWorldScale(Pt),t.multiply(Pt),this.rootMotionTargetConstraints.size>0){zt.copy(t).applyQuaternion(this.actor.quaternion);for(const t of this.rootMotionTargetConstraints)if(t.requestedProgress>0&&t.addedHorizontalDistance<t.maximumAddedHorizontalDistance){const e=r.lerp(t.initialHorizontalDistance,t.minimumHorizontalDistance,t.requestedProgress),i=Math.min(D(zt,this.actor.position,t.targetPosition,e),t.maximumAddedHorizontalDistance-t.addedHorizontalDistance);t.addedHorizontalDistance+=b(zt,this.actor.position,t.targetPosition,t.minimumHorizontalDistance,i)}else q(zt,this.actor.position,t.targetPosition,t.minimumHorizontalDistance);t.copy(zt).applyQuaternion(Vt.copy(this.actor.quaternion).invert())}return t}clearRootMotionAction(t){null!=t&&this.rootMotionAction!==t||(this.rootMotionAction=null,this.rootMotionOptions={},this.resetRootMotion=!1)}isRemoteControlledAuthority(t=this.netService.mode,e=this.actor.netRole){if(t===yt.none||e!==m.authority||t>=yt.client)return!1;return null!=this.netService.resolveActorConnection(this.actor)&&!this.netService.isLocalOwner(this.actor)}configureCharacterController(){const t=this.cc;t.setApplyImpulsesToDynamicBodies(this.applyImpulsesToDynamicBodies),t.setMinSlopeSlideAngle(this.minSlopeSlideAngle),t.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle),t.setCharacterMass(this.mass),t.setSlideEnabled(this.allowSliding)}initializeStateFromActor(){this.state.position.copy(this.actor.position),this.state.velocity.set(0,0,0),this.state.yaw=this.actor.rotation.y,this.state.lookYaw=this.rotationInput.rotation.y,this.state.mode=this.mode,this.state.currentSpeed=this.horizontalSpeed,this.state.prevRotateToMovementDirection=this.rotateToMovementDirection}createCollisionShape(){const t=this.getColliderHeight(!1),e=this.getColliderRadius(!1),i=new x(t,e);return i.offset.y=this.getCapsuleOffsetY(t,e),i.collisionGroup=xt,i}updateCrouchState(t,e,i,o){if(!(0!==(t.flags&B)))return this.crouchSuppressedUntilRelease=!1,this.slideOnLandingRequested=!1,this.state.mode===A.sliding&&(this.state.mode=A.walking),void this.tryUncrouch();if(this.state.mode===A.sliding&&(!this.slideEnabled||i))return this.slideOnLandingRequested=!1,this.state.mode=A.walking,void(this.crouchSuppressedUntilRelease||this.setCrouching(!0));if(this.state.mode===A.sliding&&o)return this.crouchSuppressedUntilRelease=!0,this.slideOnLandingRequested=!1,void this.tryUncrouch();if(this.crouchSuppressedUntilRelease)return void(this.slideOnLandingRequested=!1);if(this.setCrouching(!0),!this.slideEnabled||i)return void(this.slideOnLandingRequested=!1);if(this.state.mode===A.falling)return void(this.slideOnLandingRequested=!0);this.resolveGroundNormal(Xt);const s=this.slideOnLandingRequested&&this.state.mode===A.walking&&this.state.grounded,n=e&&0!==(t.flags&$)||s;s&&(this.slideOnLandingRequested=!1);const r=Qt(this.state.velocity);this.state.mode===A.walking&&St(this.slideEnabled,n,this.state.grounded,this.isWalkableSlideSurface(Xt),i,r,this.slideMinStartSpeed)&&(this.state.mode=A.sliding,this.slideSurfaceNormal.copy(Xt),this.state.velocity.projectOnPlane(this.slideSurfaceNormal),this.state.currentSpeed=Qt(this.state.velocity))}updateSlidingMode(t){const e=t.state,i=t.move;this.resolveGroundNormal(this.slideSurfaceNormal);const o=this.isWalkableSlideSurface(this.slideSurfaceNormal),s=e.velocity.length();if(!e.grounded||!o)return e.mode=A.falling,$t.update(t),A.falling;if(this.slideEnabled&&0!==(i.flags&B)&&!t.rootMotionActive&&0!==(i.flags&Z))return vt(t.outVelocity,e.velocity,this.jumpVelocity),e.velocity.copy(t.outVelocity),e.currentSpeed=Qt(e.velocity),A.falling;if(!gt(this.slideEnabled,0!==(i.flags&B),e.grounded,o,t.rootMotionActive,s,this.slideMinExitSpeed))return e.mode=A.walking,Wt.update(t),A.walking;const n=Mt(e.velocity,e.velocity,this.slideSurfaceNormal,t.rotatedDirection,this.getEffectiveGravity(),t.deltaTime,this.slideDeceleration,this.slideGravityScale,this.slideSteeringRate);if(e.currentSpeed=Qt(e.velocity),n<Math.max(0,this.slideMinExitSpeed))return e.mode=A.walking,Wt.update(t),A.walking;t.outVelocity.copy(e.velocity).add(t.platformVelocity)}tryUncrouch(){this.isCrouching&&this.canUncrouch()&&this.setCrouching(!1)&&(this.suppressUncrouchLift=!0,this.state.fallGraceTime=0)}resolveGroundNormal(t){return!this.rayTestResult.hasHit||this.rayTestResult.hitNormal.lengthSq()<=1e-8?t.copy(Tt):(t.copy(this.rayTestResult.hitNormal).normalize(),t.dot(Tt)<0&&t.multiplyScalar(-1),t)}isWalkableSlideSurface(t){return t.dot(Tt)>=Math.cos(this.cc.maxSlopeClimbAngle())}setCrouching(t){return this.isCrouching!==t&&(this.isCrouching=t,this.syncColliderShape(),!0)}canUncrouch(){const t=this.getColliderHeight(!1),e=this.getColliderRadius(!1);return!this.physicsSystem.hasActorCapsuleIntersection(this.actor,this.state.position,t,e,this.getCapsuleOffsetY(t,e),this.getCollisionGroup())}syncColliderShape(){const t=this.getColliderHeight(this.isCrouching),e=this.getColliderRadius(this.isCrouching);this.physicsSystem.setActorCapsuleCollider(this.actor,t,e,this.getCapsuleOffsetY(t,e))}getColliderHeight(t){const e=Number.isFinite(this.colliderHeight)?Math.max(0,this.colliderHeight):0;if(!t)return e;const i=Number.isFinite(this.crouchColliderHeight)?this.crouchColliderHeight:e;return r.clamp(i,0,e)}getColliderRadius(t){const e=Number.isFinite(this.colliderRadius)?Math.max(.001,this.colliderRadius):.001;if(!t)return e;const i=this.crouchColliderRadius??e,o=Number.isFinite(i)?i:e;return r.clamp(o,.001,e)}getCapsuleOffsetY(t,e){return e+t/2+this.offset}checkGrounded(t){Nt.y=-Math.max(.05,this.cc.snapToGroundDistance()),this.physicsSystem.rayTest(jt.addVectors(t,Yt.set(0,this.offset,0)),Gt.addVectors(t,Nt),this.rayTestResult,this.groundRayTestOptions)}resolvePlatformVelocity(t){return t.set(0,0,0),this.rayTestResult.hasHit&&null!=this.rayTestResult.actor&&this.physicsSystem.getLinearVelocity(this.rayTestResult.actor,t),t}getCollisionGroup(){return this.characterCollision?null:xt}};t([T(),e("design:type",Number)],Zt.prototype,"colliderHeight",void 0),t([T(),e("design:type",Number)],Zt.prototype,"colliderRadius",void 0),t([T(),e("design:type",Number)],Zt.prototype,"crouchColliderHeight",void 0),t([T({optional:!0}),e("design:type",Number)],Zt.prototype,"crouchColliderRadius",void 0),t([g(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"serverMove",null),t([y(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"clientMoveAck",null),t([y(!0),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"clientMoveCorrection",null),t([v(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"simulatedState",null),Zt=t([R({inEditor:!1}),e("design:paramtypes",[])],Zt);export{Zt as CharacterMovementComponent};const Wt={mode:A.walking,update(t){const e=t.component,i=t.move,o=t.state,s=t.rotatedDirection,n=Math.min(1,Math.sqrt(i.inputX*i.inputX+i.inputY*i.inputY)),r=!e.rotateToMovementDirection&&i.inputY<0,a=e.isCrouching,h=!t.rootMotionActive&&!a&&0===(i.flags&B)&&0!==(i.flags&Q)&&!r&&0!==s.lengthSq()&&(e.sprintPolicy?.canSprint()??!0),l=(a?e.maxSpeedCrouch:r?e.maxSpeedBackwards:h?e.maxSpeedSprint:e.maxSpeed)*(e.normalizedDirection?1:n);if(0!==s.lengthSq()){e.isSprinting=h,h&&e.sprintPolicy?.commitSprint(t.deltaTime,i.sequence);let a=Math.min(l,o.currentSpeed),c=e.groundAccelerationRate;if(h&&t.startedSprinting&&e.sprintStartBoostSpeed>0){const t=e.normalizedDirection?1:n;a=Math.max(a,l+e.sprintStartBoostSpeed*t),c=e.sprintStartBoostDamping}else h&&!r&&e.sprintStartBoostSpeed>0&&o.currentSpeed>l&&(a=o.currentSpeed,c=e.sprintStartBoostDamping);o.currentSpeed=function(t,e,i,o){return e+(t-e)*Math.exp(-i*o)}(a,l,c,t.deltaTime),t.outVelocity.copy(s).multiplyScalar(function(t,e,i,o){const s=i*o;if(s<=1e-6)return t;return e+(t-e)*(1-Math.exp(-s))/s}(a,l,c,t.deltaTime))}else o.currentSpeed=0,t.outVelocity.set(0,0,0);if(0!==(i.flags&Z))return o.mode=A.falling,o.velocity.copy(t.outVelocity),o.velocity.y=e.jumpVelocity,A.falling;t.outVelocity.y=t.deltaTime*e.getEffectiveGravity(),t.outVelocity.add(t.platformVelocity)}},$t={mode:A.falling,update(t){const e=t.component,i=t.state,o=t.move;0!==(o.flags&Z)&&e.jumpInAir&&(i.velocity.copy(t.outVelocity),i.velocity.y=e.jumpVelocity),i.velocity.y+=t.deltaTime*e.getEffectiveGravity(),t.outVelocity.copy(i.velocity),t.outVelocity.addScaledVector(t.rotatedDirection,e.fallingMovementControl),e.fallingReorientation&&t.outVelocity.applyAxisAngle(Tt,r.euclideanModulo(o.yaw-i.lookYaw+Math.PI,2*Math.PI)-Math.PI)}};function Qt(t){return Math.sqrt(t.x*t.x+t.z*t.z)}function Jt(t,e){return e.sequence=t.sequence,e.clientTime=t.clientTime,e.dt=t.dt,e.inputX=t.inputX,e.inputY=t.inputY,e.yaw=t.yaw,e.flags=t.flags,e.clientX=t.clientX,e.clientY=t.clientY,e.clientZ=t.clientZ,e.rootMotionX=t.rootMotionX,e.rootMotionY=t.rootMotionY,e.rootMotionZ=t.rootMotionZ,e}function Kt(t,e){const i=t.position.x-e.clientX,o=t.position.y-e.clientY,s=t.position.z-e.clientZ;return i*i+o*o+s*s}class _t{constructor(t){this.scene=t,this.serverPosition=new h,this.direction=new h}update(t,e){const i=this.serverPosition.set(e.x,e.y,e.z),o=i.distanceTo(t);o>.1&&console.log(`Correction applied. Error: ${o.toFixed(3)}. Server position: (${i.x.toFixed(2)}, ${i.y.toFixed(2)}, ${i.z.toFixed(2)}), Client position: (${t.x.toFixed(2)}, ${t.y.toFixed(2)}, ${t.z.toFixed(2)})`);const s=this.direction.copy(i).sub(t).normalize();te.position.copy(t),te.setDirection(s),te.setLength(o);const n=ee(this.scene);n.add(te),setTimeout(()=>{n.remove(te)},1e3)}}const te=new n(new h(0,1,0),new h,1,16711680);function ee(t){return null==t.parent?t:ee(t.parent)}const ie={immediate:!1,savedRootMotion:!0};/*
1
+ import{__decorate as t,__metadata as e}from"tslib";import i from"@dimforge/rapier3d-simd-compat";import{takeUntil as o}from"rxjs";import*as s from"three";import{ArrowHelper as n,MathUtils as r,Quaternion as a,Vector3 as h}from"three";import{RootMotionClip as l}from"../../../../animation/root-motion.js";import{inject as c}from"../../../../inject.js";import{ActionInput as d,AxisInput as u,RotationInput as p}from"../../../../input/index.js";import{NetRole as m}from"../../../../net/service/net-actor-role.js";import{RunOnClient as y,RunOnNotOwner as v,RunOnServer as g}from"../../../../net/service/rpc-decorator.js";import{NetService as S}from"../../../../net/service/net-service.js";import{PhysicsSystem as M,RayTestResult as f}from"../../../../services/physics/physics-system.js";import{CapsuleCollisionShape as x}from"../../../../../scene/collision/collision-shape.js";import{Parameter as T}from"../../../../../shader/parameter.js";import{PhysicsBodyType as C}from"../../../../services/physics/physics-system.js";import{ActorComponent as w,Component as R}from"../../../component.js";import{CharacterMovementMode as A}from"./modes.js";import{calculateRootMotionTargetApproachCorrection as D,constrainRootMotionTargetApproach as q,warpRootMotionTargetApproach as b}from"./root-motion-constraint.js";import{DEFAULT_MAX_CLIENT_TIME_AHEAD as z,DEFAULT_LARGE_CORRECTION_THRESHOLD as k,DEFAULT_MAX_COMBINED_MOVE_DELTA_TIME as P,DEFAULT_MAX_MOVE_DELTA_TIME as I,DEFAULT_MAX_MOVES_PER_PACKET as G,DEFAULT_MAX_REPLAYED_MOVES as O,DEFAULT_MAX_SERVER_MOVES_PER_TICK as j,DEFAULT_MAX_SAVED_MOVES as Y,DEFAULT_MAX_SERVER_MOVE_DELTA_TIME_SCALAR as N,DEFAULT_MAX_SERVER_MOVE_TIME_BUDGET as F,DEFAULT_MAX_SUBSTEP_DELTA_TIME as V,DEFAULT_MOVE_SEND_INTERVAL as H,DEFAULT_SIMULATED_INTERPOLATION_DELAY as U,DEFAULT_SIMULATED_STATE_INTERVAL as X,DEFAULT_SMALL_CORRECTION_TOLERANCE as E,DEFAULT_TELEPORT_SNAP_THRESHOLD as L,MOVE_FLAG_CROUCH as B,MOVE_FLAG_JUMP as Z,MOVE_FLAG_ROOT_MOTION as W,MOVE_FLAG_SLIDE_START as $,MOVE_FLAG_SPRINT as Q,MOVE_FLAG_SPRINT_START as J,SNAPSHOT_FLAG_CROUCH_SUPPRESSED as K,SNAPSHOT_FLAG_CROUCHING as _,NetCharacterProxySmoother as tt,NetCharacterSavedMoveBuffer as et,accrueNetCharacterServerMoveTime as it,createNetCharacterMovementSnapshot as ot,createNetCharacterServerMoveTimingState as st,consumeNetCharacterServerMoveTime as nt,decodeNetCharacterMoveBatch as rt,decodeNetCharacterOwnerAck as at,decodeNetCharacterOwnerCorrection as ht,decodeNetCharacterSimulatedState as lt,encodeNetCharacterMoveBatch as ct,encodeNetCharacterOwnerAck as dt,encodeNetCharacterOwnerCorrection as ut,encodeNetCharacterSimulatedState as pt,validateNetCharacterMove as mt}from"./net-character-movement-protocol.js";import{NetMode as yt}from"../../../../net/net-session.js";import{setSlideJumpVelocity as vt,shouldContinueSlide as gt,shouldStartSlide as St,updateSlideVelocity as Mt,updateSlideVelocityFromDisplacement as ft}from"./character-slide.js";export*from"./net-character-movement-protocol.js";const xt=131070,Tt=new h(0,1,0),Ct=new h,wt=new h,Rt=new h,At=new h,Dt=new h,qt=new h,bt=new h,zt=new h,kt=new h,Pt=new h,It=new h,Gt=new h,Ot=new h,jt=new h,Yt=new h(0,1,0),Nt=new h(0,-.05,0),Ft=new h,Vt=new a,Ht=new s.Euler,Ut=new h,Xt=new h,Et=new h,Lt=new h,Bt=new i.CharacterCollision;let Zt=class extends w{get autoStepMinWidth(){return this.cc.autostepMinWidth()}set autoStepMinWidth(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),t,this.cc.autostepIncludesDynamicBodies())}get autoStepDynamicObjects(){return this.cc.autostepIncludesDynamicBodies()}set autoStepDynamicObjects(t){this.cc.enableAutostep(this.cc.autostepMaxHeight(),this.cc.autostepMinWidth(),t)}get autoStepMaxHeight(){return this.cc.autostepMaxHeight()}set autoStepMaxHeight(t){this.cc.enableAutostep(t,this.cc.autostepMinWidth(),this.cc.autostepIncludesDynamicBodies())}get snapToGround(){return this.cc.snapToGroundDistance()}set snapToGround(t){this.cc.enableSnapToGround(t)}set offset(t){this.cc.setOffset(t)}get offset(){return this.cc.offset()}set normalNudgeFactor(t){this.cc.setNormalNudgeFactor(t)}get normalNudgeFactor(){return this.cc.normalNudgeFactor()}teleport(t,e=this.actor.rotation.y){this.state.position.copy(t),this.state.velocity.set(0,0,0),this.state.yaw=e,this.actor.position.copy(t),this.actor.rotation.y=e,this.rotationInput.rotation.y=e,this.physicsSystem.setPosition(this.actor,t),this.physicsSystem.setRotation(this.actor,this.actor.quaternion),this.physicsSystem.flushModifiedBodyPositionsToColliders()}constructor(){super(),this.isDefaultCharacterMovementComponent=!0,this.directionInput=new u,this.jumpInput=new d,this.sprintInput=new d,this.crouchInput=new d,this.rotationInput=new p,this.horizontalSpeed=0,this.maxSpeed=8,this.maxSpeedBackwards=8,this.maxSpeedSprint=12,this.maxSpeedCrouch=4,this.slideEnabled=!1,this.slideMinStartSpeed=8,this.slideMinExitSpeed=4,this.slideDeceleration=3,this.slideGravityScale=1,this.slideSteeringRate=2,this.sprintStartBoostSpeed=0,this.sprintStartBoostDamping=6,this.jumpVelocity=7,this.fallingMovementControl=.5,this.fallingReorientation=!1,this.groundAccelerationRate=4,this.gravityOverride=null,this.colliderHeight=2,this.colliderRadius=.5,this.crouchColliderHeight=1,this.crouchColliderRadius=null,this.jumpInAir=!1,this.mass=50,this.allowSliding=!0,this.minSlopeSlideAngle=r.degToRad(70),this.maxSlopeClimbAngle=r.degToRad(70),this.applyImpulsesToDynamicBodies=!0,this.normalizedDirection=!0,this.characterCollision=!1,this.allowRootMotionJumpCancel=!1,this.enabled=!0,this.rotateToMovementDirection=!1,this.smoothRotation=!0,this.rotationSpeed=40,this.maxRotationSpeed=100,this.impulseDamping=2,this.moveSendInterval=H,this.simulatedStateInterval=X,this.maxSavedMoves=Y,this.maxReplayedMoves=O,this.maxServerMovesPerTick=j,this.maxMovesPerPacket=G,this.maxMoveDeltaTime=I,this.maxCombinedMoveDeltaTime=P,this.maxServerMoveDeltaTimeScalar=N,this.maxClientTimeAhead=z,this.maxServerMoveTimeBudget=F,this.maxSubstepDeltaTime=V,this.fallGraceTime=.1,this.correctionToleranceSq=E*E,this.largeCorrectionThreshold=k,this.teleportSnapThreshold=L,this.listenServerSmoothing=!0,this.listenServerSmoothLocationTime=.04,this.listenServerMaxSmoothUpdateDistance=1,this.listenServerNoSmoothUpdateDistance=2.5,this.debugCorrections=!0,this.suppressUncrouchLift=!1,this.velocity=new h,this.visualSmoothingOffset=new h,this.slideDirection=new h,this.slideSurfaceNormal=new h(0,1,0),this.mode=A.walking,this.isSprinting=!1,this.isCrouching=!1,this.isSliding=!1,this.pressedJump=!1,this.rayTestResult=new f,this.groundRayTestOptions={debug:!1,excludeTriggers:!0,excludeActor:void 0,resolveActor:!1},this.physicsSystem=c(M),this.netService=c(S),this.state={sequence:0,position:new h,velocity:new h,yaw:0,lookYaw:0,mode:A.walking,grounded:!1,currentSpeed:0,fallGraceTime:0,prevInputDirection:new h,prevRotateToMovementDirection:!1},this.movementModes=new Map,this.savedMoves=new et(Y),this.serverMoveTiming=st(),this.serverMoveQueue=[],this.inputMoveScratch={sequence:0,clientTime:0,dt:0,inputX:0,inputY:0,yaw:0,flags:0,clientX:0,clientY:0,clientZ:0,rootMotionX:0,rootMotionY:0,rootMotionZ:0},this.authoritativeMoveScratch={sequence:0,clientTime:0,dt:0,inputX:0,inputY:0,yaw:0,flags:0,clientX:0,clientY:0,clientZ:0,rootMotionX:0,rootMotionY:0,rootMotionZ:0},this.movementModeContext={component:this,state:this.state,move:this.inputMoveScratch,deltaTime:0,rotatedDirection:wt,platformVelocity:At,outVelocity:Rt,rootMotionActive:!1,startedSprinting:!1},this.proxySmoother=new tt(U,L),this.proxySample=ot(),this.pendingSnapshot=ot(),this.impulse=new h,this.prevRootMotionPos=new h,this.rootMotionOptions={},this.rootMotionTargetConstraints=new Set,this.resetRootMotion=!1,this.nextMoveSequence=0,this.clientMoveTime=0,this.lastSentClientMoveTime=0,this.moveSendAccumulator=0,this.simulatedStateAccumulator=0,this.proxyTime=0,this.lastServerProcessedSequence=0,this.lastServerReceivedSequence=0,this.lastAutonomousMoveFlags=0,this.previousSprintInput=!1,this.previousCrouchInput=!1,this.crouchSuppressedUntilRelease=!1,this.slideOnLandingRequested=!1,this.initialized=!1,this.cc=this.physicsSystem.getCharacterController(.1),this.cc.enableSnapToGround(.1),this.cc.enableAutostep(0,.1,!1),this.registerMovementMode(Wt),this.registerMovementMode($t),this.registerMovementMode({mode:A.sliding,update:t=>this.updateSlidingMode(t)})}onInit(){this.groundRayTestOptions.excludeActor=this.actor,this.configureCharacterController(),this.physicsSystem.addActor(this.actor,[this.createCollisionShape()],{mass:0,type:C.kinematic,continousCollisionDetection:!1,friction:0,restitution:.5,ignoreForNavMesh:!0}),this.rotationInput.rotation.copy(this.actor.rotation),this.initializeStateFromActor(),this.initialized=!0,this.physicsSystem.beforeStep.pipe(o(this.disposed)).subscribe(t=>this.tick(t))}onLateUpdate(t){this.updateVisualSmoothing(t)}registerMovementMode(t){this.movementModes.set(t.mode,t)}applyImpulse(t){this.impulse.add(t)}getEffectiveGravity(){return this.gravityOverride??this.physicsSystem.getGravity().y}get isGrounded(){return this.rayTestResult.hasHit||this.cc.computedGrounded()}setRootMotionAction(t,e={}){const i=t?.getClip();if(i instanceof l){this.rootMotionAction=t,this.rootMotionOptions=e,this.resetRootMotion=!0;const o=[];this.rootMotionInterpolant=i.motionTrack.InterpolantFactoryMethodSmooth(o);const n=s.PropertyBinding.parseTrackName(i.motionTrack.name);this.rootMotionRootBone=this.actor.object.getObjectByName(n.nodeName)}}addRootMotionTargetConstraint(t,e,i=0){const o={targetPosition:t,minimumHorizontalDistance:Math.max(0,e),maximumAddedHorizontalDistance:Math.max(0,i),initialHorizontalDistance:Math.hypot(t.x-this.actor.position.x,t.z-this.actor.position.z),addedHorizontalDistance:0,requestedProgress:0};this.rootMotionTargetConstraints.add(o);let s=!1;return{setProgress:t=>{o.requestedProgress=Math.max(o.requestedProgress,Math.min(1,Math.max(0,t)))},dispose:()=>{s||(s=!0,this.rootMotionTargetConstraints.delete(o))}}}serverMove(t){const e=rt(t);if(e.ok)for(const t of e.value.moves)mt(t,this.lastServerReceivedSequence,this.maxMoveDeltaTime)&&(this.lastServerReceivedSequence=t.sequence,this.serverMoveQueue.push(t))}clientMoveAck(t){const e=at(t);e.ok&&this.actor.netRole===m.autonomousProxy&&(this.savedMoves.ack(e.value.sequence),this.sprintPolicy?.ack?.(e.value.sequence,!1))}clientMoveCorrection(t){const e=ht(t);e.ok&&this.actor.netRole===m.autonomousProxy&&(this.debugCorrections&&(null==this.correctionDebug&&(this.correctionDebug=new _t(ee(this.actor.object))),this.correctionDebug.update(this.state.position,e.value.snapshot)),this.applyCorrection(e.value.snapshot))}simulatedState(t){const e=lt(t);e.ok&&this.actor.netRole===m.simulatedProxy&&this.proxySmoother.push(e.value,this.proxyTime)}tick(t){if(!this.initialized)return;t=Math.min(.1,t);const e=this.actor.netRole,i=this.netService.mode;e!==m.simulatedProxy?this.enabled&&(e!==m.autonomousProxy?this.isRemoteControlledAuthority(i,e)?this.tickRemoteAuthority(t):this.tickAuthority(t,i):this.tickAutonomousProxy(t)):this.tickSimulatedProxy(t)}tickAutonomousProxy(t){const e=this.state.mode,i=this.lastAutonomousMoveFlags,o=this.createMoveFromInput(t,++this.nextMoveSequence,{quantizeClientTime:!0});this.performMove(o,ie),this.resetToggleCrouchAfterSlide(e);const s=this.state.mode!==e||o.flags!==i;this.lastAutonomousMoveFlags=o.flags,this.savedMoves.capacity=this.maxSavedMoves,this.savedMoves.maxCombinedDeltaTime=Math.min(this.maxCombinedMoveDeltaTime,this.maxMoveDeltaTime),this.savedMoves.push(o),this.sendSavedMoves(t,s)}tickAuthority(t,e){const i=this.state.mode,o=this.createMoveFromInput(t,++this.nextMoveSequence);this.performMove(o,ie),this.resetToggleCrouchAfterSlide(i),e!==yt.none&&this.sendSimulatedState(t,!1)}resetToggleCrouchAfterSlide(t){t===A.sliding&&this.state.mode!==A.sliding&&"toggle"===this.crouchInput.mode&&this.crouchInput.activated&&this.crouchInput.setActivated(!1)}tickRemoteAuthority(t){it(this.serverMoveTiming,t,this.maxServerMoveTimeBudget);let e=!1;const i=Number.isFinite(this.maxServerMovesPerTick)?Math.max(1,Math.floor(this.maxServerMovesPerTick)):this.serverMoveQueue.length,o=Math.min(this.serverMoveQueue.length,i),s=Et.copy(this.actor.position);let n=!1;for(let t=0;t<o;t++){const t=this.serverMoveQueue.shift();if(null==t)break;if(!mt(t,this.lastServerProcessedSequence,this.maxMoveDeltaTime)){console.log("Net: Invalid move",t),this.sendOwnerCorrection(!0),e=!0;continue}const i=nt(this.serverMoveTiming,t,{maxMoveDeltaTime:this.maxMoveDeltaTime,maxServerMoveDeltaTimeScalar:this.maxServerMoveDeltaTimeScalar,maxClientTimeAhead:this.maxClientTimeAhead});if(i<0){this.sendOwnerCorrection(!0),e=!0;continue}const o=Jt(t,this.authoritativeMoveScratch);o.dt=i,o.rootMotionX=0,o.rootMotionY=0,o.rootMotionZ=0,o.flags&=~W,this.performMove(o,{immediate:!0,savedRootMotion:!1}),n=!0,this.lastServerProcessedSequence=o.sequence;const s=Kt(this.state,t);if(s>this.correctionToleranceSq){console.log(`Net server: Correction error: ${Math.sqrt(s)}`);const o=this.state.position.x-t.clientX,n=this.state.position.y-t.clientY,r=this.state.position.z-t.clientZ;console.log(`diff x: ${o}, y: ${n}, z: ${r}`),console.log({sequence:t.sequence,moveDt:t.dt,serverMoveDeltaTime:i,flags:t.flags,mode:this.state.mode,grounded:this.state.grounded,fallGraceTime:this.state.fallGraceTime}),this.sendOwnerCorrection(s>this.largeCorrectionThreshold*this.largeCorrectionThreshold),e=!0}}0===this.lastServerProcessedSequence||e||(this.sprintPolicy?.ack?.(this.lastServerProcessedSequence,!1),this.clientMoveAck(dt(this.lastServerProcessedSequence))),n&&this.accumulateListenServerVisualSmoothing(s,this.actor.position),this.sendSimulatedState(t,!1)}tickSimulatedProxy(t){this.proxyTime+=t,this.proxySmoother.sample(this.proxyTime,this.proxySample)&&this.applySnapshot(this.proxySample,!0)}accumulateListenServerVisualSmoothing(t,e){if(!this.shouldSmoothListenServerRemoteAuthority())return void this.visualSmoothingOffset.set(0,0,0);Lt.subVectors(t,e);const i=Lt.lengthSq();i>1e-8&&(i>this.listenServerNoSmoothUpdateDistance*this.listenServerNoSmoothUpdateDistance?this.visualSmoothingOffset.set(0,0,0):(i>this.listenServerMaxSmoothUpdateDistance*this.listenServerMaxSmoothUpdateDistance&&Lt.setLength(this.listenServerMaxSmoothUpdateDistance),this.visualSmoothingOffset.add(Lt)))}updateVisualSmoothing(t){if(this.visualSmoothingOffset.lengthSq()<=1e-8)return void this.visualSmoothingOffset.set(0,0,0);if(!this.shouldSmoothListenServerRemoteAuthority())return void this.visualSmoothingOffset.set(0,0,0);const e=Math.max(.001,this.listenServerSmoothLocationTime);t<e?this.visualSmoothingOffset.multiplyScalar(1-t/e):this.visualSmoothingOffset.set(0,0,0),this.visualSmoothingOffset.lengthSq()<=1e-4&&this.visualSmoothingOffset.set(0,0,0)}shouldSmoothListenServerRemoteAuthority(){return this.listenServerSmoothing&&this.actor.netRole===m.authority&&this.netService.isServer&&!this.netService.isDedicatedServer&&this.isRemoteControlledAuthority()}createMoveFromInput(t,e,i={}){const o=r.clamp(t,.001,this.maxMoveDeltaTime);this.clientMoveTime+=o;let s=this.clientMoveTime,n=o;!0===i.quantizeClientTime&&(s=Math.max(this.lastSentClientMoveTime+.001,Math.round(1e3*this.clientMoveTime)/1e3),n=r.clamp(s-this.lastSentClientMoveTime,.001,this.maxMoveDeltaTime),this.lastSentClientMoveTime=s),this.sampleRootMotion(bt);const a=this.crouchInput.activated,h=a&&!this.previousCrouchInput;this.previousCrouchInput=a;const l=!a&&this.sprintInput.activated,c=l&&!this.previousSprintInput;this.previousSprintInput=l;const d=(this.jumpInput.activated?Z:0)|(l?Q:0)|(a?B:0)|(h&&this.slideEnabled?$:0)|(c?J:0)|(bt.lengthSq()>0?W:0),u=function(t,e){e.set(t.x,0,t.y),e.lengthSq()>1&&e.normalize();return e}(this.directionInput.vector,Ut),p=this.inputMoveScratch;return p.sequence=e>>>0,p.clientTime=s,p.dt=n,p.inputX=u.x,p.inputY=u.z,p.yaw=this.rotationInput.rotation.y,p.flags=d,p.clientX=this.state.position.x,p.clientY=this.state.position.y,p.clientZ=this.state.position.z,p.rootMotionX=bt.x,p.rootMotionY=bt.y,p.rootMotionZ=bt.z,p}performMove(t,e){const i=r.clamp(t.dt,.001,this.maxMoveDeltaTime),o=Math.max(1,Math.ceil(i/this.maxSubstepDeltaTime)),s=0!==(t.flags&Q)&&0===(t.flags&B);this.sprintPolicy?.update?.(i,t.sequence,s),Gt.set(e.savedRootMotion?t.rootMotionX:0,e.savedRootMotion?t.rootMotionY:0,e.savedRootMotion?t.rootMotionZ:0),e.savedRootMotion||this.sampleRootMotion(Gt);let n=i;const a=i/o;for(let s=0;s<o;s++){const o=i>0?a/i:1;this.performSubstep(t,Math.min(a,n),Gt,o,e.immediate,0===s),n-=a}t.clientX=this.state.position.x,t.clientY=this.state.position.y,t.clientZ=this.state.position.z,t.flags=Gt.lengthSq()>0?t.flags|W:t.flags&~W,this.state.sequence=t.sequence,this.syncPublicState()}performSubstep(t,e,i,o,s,n){if(e<.001)return;this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded;const r=null!=this.rootMotionAction&&this.rootMotionAction.enabled,a=i.lengthSq()>0,h=!r&&0!==(t.flags&Z),l=r||a;this.updateCrouchState(t,n,l,h),this.pressedJump=h,this.isSprinting=!1,this.updateRotation(t,e,r,a),this.resolvePlatformVelocity(At);const c=this.movementModeContext,d=this.movementModes.get(this.state.mode);if(null!=d){c.move=t,c.deltaTime=e,c.rootMotionActive=l,c.startedSprinting=n&&!l&&0===(t.flags&B)&&0!==(t.flags&J);const i=d.update(c);"number"==typeof i&&(this.state.mode=i)}else Rt.set(0,0,0);if(a){zt.copy(i).multiplyScalar(o).applyQuaternion(this.actor.quaternion),kt.copy(zt).divideScalar(e),this.state.mode===A.walking?(Rt.x=kt.x+At.x,Rt.z=kt.z+At.z):(Rt.x=kt.x,Rt.z=kt.z);const t=Math.sqrt(kt.x*kt.x+kt.z*kt.z);t>.4&&(this.state.currentSpeed=t)}if(this.applyImpulseToVelocity(Rt,e),h&&this.isSprinting){const t=Math.max(0,this.maxSpeedSprint),e=Qt(Rt);if(e>t){const i=t/e;Rt.x*=i,Rt.z*=i,this.state.velocity.x*=i,this.state.velocity.z*=i}}this.state.mode===A.walking&&this.state.velocity.copy(Rt),this.applyMovement(Rt,e,s),this.state.mode===A.sliding&&(ft(this.state.velocity,qt,At,this.slideSurfaceNormal,e),this.state.currentSpeed=Qt(this.state.velocity)),this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded,this.updateModeAfterMove(Rt,e),this.state.mode===A.sliding&&this.state.velocity.length()<Math.max(0,this.slideMinExitSpeed)&&(this.state.mode=A.walking)}updateRotation(t,e,i,o){Ct.set(-t.inputX,0,t.inputY),Ct.lengthSq()>1&&Ct.normalize();const s=this.state.prevRotateToMovementDirection!==this.rotateToMovementDirection;let n=r.euclideanModulo(t.yaw-this.state.lookYaw+Math.PI,2*Math.PI)-Math.PI;if(s&&(this.actor.object.quaternion.setFromEuler(Ht.set(0,t.yaw,0)),n=0,this.state.lookYaw=t.yaw,this.state.prevRotateToMovementDirection=this.rotateToMovementDirection),wt.set(0,0,0),i)this.state.lookYaw=t.yaw;else if(this.rotateToMovementDirection){if(Ct.lengthSq()>0&&this.state.mode!==A.falling){const i=Ht.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,o=Math.atan2(Ct.x,Ct.z),s=.99*t.yaw+o;if(this.smoothRotation){const t=r.euclideanModulo(s-i+Math.PI,2*Math.PI)-Math.PI;let o=r.clamp(t*this.rotationSpeed*e,-this.maxRotationSpeed*e,this.maxRotationSpeed*e);Math.abs(o)>Math.abs(t)&&(o=t),this.actor.object.quaternion.setFromEuler(Ht.set(0,i+o,0))}else this.actor.object.quaternion.setFromEuler(Ht.set(0,s,0));this.state.prevInputDirection.lerp(Ct,e*this.rotationSpeed),this.state.lookYaw+=n,wt.copy(this.actor.object.getWorldDirection(Ut).normalize())}}else o||(this.state.lookYaw=t.yaw,this.actor.object.quaternion.setFromEuler(Ht.set(0,t.yaw,0)),Ct.lengthSq()>0&&wt.copy(Ct).applyAxisAngle(Tt,t.yaw).normalize())}applyMovement(t,e,i){if(t.lengthSq()>0||!this.state.grounded)if(Dt.copy(t).multiplyScalar(e),this.state.grounded&&((o=this.state.mode)===A.walking||o===A.sliding)){if(this.state.mode===A.walking&&this.rayTestResult.distance<=this.cc.offset()&&(Dt.y=Math.max(0,At.y*e)),qt.copy(this.physicsSystem.getActorComputedMovement(this.actor,this.cc,Dt,this.getCollisionGroup())),this.cc.computedCollision(0,Bt),null!=Bt.normal1){const t=Ut.copy(Bt.normal1);if(Math.acos(r.clamp(t.dot(Tt),-1,1))>this.cc.maxSlopeClimbAngle()){const t=.016*this.getEffectiveGravity()*.5;Dt.y!==t&&(Dt.y=t,qt.copy(this.physicsSystem.getActorComputedMovement(this.actor,this.cc,Dt,this.getCollisionGroup())))}}}else qt.copy(this.physicsSystem.getActorComputedMovement(this.actor,this.cc,Dt,this.getCollisionGroup()));else qt.set(0,0,0);var o;this.suppressUncrouchLift&&(this.suppressUncrouchLift=!1,this.state.grounded&&this.state.mode===A.walking&&Dt.y<=1e-6&&qt.y>0&&(qt.y=0)),this.state.position.add(qt),i?(this.actor.position.copy(this.state.position),this.physicsSystem.updateActorTransform(this.actor),this.physicsSystem.flushModifiedBodyPositionsToColliders()):this.physicsSystem.setNextKinematicPosition(this.actor,this.state.position)}updateModeAfterMove(t,e){const i=function(t){if(0===t.numComputedCollisions())return!1;const e=t.computedCollision(0);Ft.set(e.normal2.x,e.normal2.y,e.normal2.z);const i=Ft.angleTo(Tt);Ft.set(e.normal1.x,e.normal1.y,e.normal1.z);const o=Ft.angleTo(Tt);if(i<100)return!1;return o>t.minSlopeSlideAngle()}(this.cc);!this.state.grounded||i?this.state.mode!==A.falling&&(this.state.fallGraceTime+=e,this.state.fallGraceTime>this.fallGraceTime+1e-6&&(this.state.mode=A.falling,this.state.velocity.copy(t))):this.state.velocity.y<=0&&(this.state.mode===A.falling&&(this.state.mode=A.walking),this.state.mode!==A.sliding&&(this.state.velocity.y=0),this.state.fallGraceTime=0)}applyImpulseToVelocity(t,e){if(this.impulse.lengthSq()<=.1)return void this.impulse.set(0,0,0);const i=Math.min(1,this.impulse.length()/5);t.x=r.lerp(t.x,this.impulse.x,i),t.z=r.lerp(t.z,this.impulse.z,i),t.y+=this.impulse.y;const o=Math.exp(-this.impulseDamping*e);this.impulse.x*=o,this.impulse.y>0?this.impulse.y+=e*this.getEffectiveGravity():this.impulse.y*=o,this.impulse.z*=o}sendSavedMoves(t,e=!1){if(this.moveSendAccumulator+=t,!e&&this.moveSendAccumulator<this.moveSendInterval)return;this.moveSendAccumulator=0;const i=this.savedMoves.getMovesForSend(this.maxMovesPerPacket);0!==i.length&&this.serverMove(ct(i))}sendOwnerCorrection(t){const e=this.toSnapshot(this.pendingSnapshot);t&&(e.horizontalSpeed=this.horizontalSpeed),this.sprintPolicy?.ack?.(e.sequence,!0),this.clientMoveCorrection(ut(e))}sendSimulatedState(t,e){this.simulatedStateAccumulator+=t,!e&&this.simulatedStateAccumulator<this.simulatedStateInterval||(this.simulatedStateAccumulator=0,this.simulatedState(pt(this.toSnapshot(this.pendingSnapshot))))}applyCorrection(t){this.sprintPolicy?.restore?.(t.sequence),this.savedMoves.ack(t.sequence),this.sprintPolicy?.ack?.(t.sequence,!0),this.applySnapshot(t,!0),this.savedMoves.replayAfter(t.sequence,t=>(this.performMove(t,{immediate:!0,savedRootMotion:!0}),null),this.maxReplayedMoves)}applySnapshot(t,e){this.state.sequence=t.sequence,this.state.position.set(t.x,t.y,t.z),this.state.velocity.set(t.velocityX,t.velocityY,t.velocityZ),this.state.yaw=t.yaw,this.state.lookYaw=t.yaw,this.state.mode=t.mode,this.state.currentSpeed=t.horizontalSpeed,this.state.fallGraceTime=0,this.actor.position.copy(this.state.position),this.actor.object.quaternion.setFromEuler(Ht.set(0,t.yaw,0)),this.crouchSuppressedUntilRelease=0!==(t.flags&K),this.setCrouching(0!==(t.flags&_)||t.mode===A.sliding),e&&(this.physicsSystem.updateActorTransform(this.actor),this.physicsSystem.flushModifiedBodyPositionsToColliders()),this.checkGrounded(this.state.position),this.state.grounded=this.isGrounded,this.syncPublicState()}toSnapshot(t){return t.sequence=this.state.sequence,t.x=this.state.position.x,t.y=this.state.position.y,t.z=this.state.position.z,t.velocityX=this.state.velocity.x,t.velocityY=this.state.velocity.y,t.velocityZ=this.state.velocity.z,t.yaw=Ht.setFromQuaternion(this.actor.object.quaternion,"YXZ").y,t.mode=this.state.mode,t.flags=(this.isCrouching?_:0)|(this.crouchSuppressedUntilRelease?K:0),t.horizontalSpeed=this.state.currentSpeed,t}syncPublicState(){this.velocity.copy(this.state.velocity),this.mode=this.state.mode,this.horizontalSpeed=this.state.currentSpeed,this.isSliding=this.state.mode===A.sliding,this.isSliding?(this.resolveGroundNormal(this.slideSurfaceNormal),this.slideDirection.copy(this.state.velocity).projectOnPlane(this.slideSurfaceNormal),this.slideDirection.lengthSq()>1e-8?this.slideDirection.normalize():this.slideDirection.set(0,0,0)):(this.slideDirection.set(0,0,0),this.slideSurfaceNormal.copy(Tt))}sampleRootMotion(t){if(t.set(0,0,0),null==this.rootMotionAction||this.rootMotionAction.isRunning()||this.clearRootMotionAction(this.rootMotionAction),null!=this.rootMotionAction&&this.rootMotionOptions.cancelWithJump&&this.jumpInput.activated&&(this.isGrounded||this.jumpInAir)){const e=this.rootMotionAction,i=this.rootMotionOptions.onJumpCancel;return this.clearRootMotionAction(e),e.stop(),i?.(),t}if(null==this.rootMotionAction)return t;if(!(this.rootMotionAction.getClip()instanceof l))return t;const e=this.rootMotionInterpolant;this.resetRootMotion&&(this.prevRootMotionPos.fromArray(e.evaluate(0)),this.resetRootMotion=!1),It.fromArray(e.evaluate(this.rootMotionAction.time)),t.subVectors(It,this.prevRootMotionPos),this.prevRootMotionPos.copy(It);if((this.rootMotionRootBone??this.rootMotionAction.getRoot()).getWorldScale(Pt),t.multiply(Pt),this.rootMotionTargetConstraints.size>0){zt.copy(t).applyQuaternion(this.actor.quaternion);for(const t of this.rootMotionTargetConstraints)if(t.requestedProgress>0&&t.addedHorizontalDistance<t.maximumAddedHorizontalDistance){const e=r.lerp(t.initialHorizontalDistance,t.minimumHorizontalDistance,t.requestedProgress),i=Math.min(D(zt,this.actor.position,t.targetPosition,e),t.maximumAddedHorizontalDistance-t.addedHorizontalDistance);t.addedHorizontalDistance+=b(zt,this.actor.position,t.targetPosition,t.minimumHorizontalDistance,i)}else q(zt,this.actor.position,t.targetPosition,t.minimumHorizontalDistance);t.copy(zt).applyQuaternion(Vt.copy(this.actor.quaternion).invert())}return t}clearRootMotionAction(t){null!=t&&this.rootMotionAction!==t||(this.rootMotionAction=null,this.rootMotionOptions={},this.resetRootMotion=!1)}isRemoteControlledAuthority(t=this.netService.mode,e=this.actor.netRole){if(t===yt.none||e!==m.authority||t>=yt.client)return!1;return null!=this.netService.resolveActorConnection(this.actor)&&!this.netService.isLocalOwner(this.actor)}configureCharacterController(){const t=this.cc;t.setApplyImpulsesToDynamicBodies(this.applyImpulsesToDynamicBodies),t.setMinSlopeSlideAngle(this.minSlopeSlideAngle),t.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle),t.setCharacterMass(this.mass),t.setSlideEnabled(this.allowSliding)}initializeStateFromActor(){this.state.position.copy(this.actor.position),this.state.velocity.set(0,0,0),this.state.yaw=this.actor.rotation.y,this.state.lookYaw=this.rotationInput.rotation.y,this.state.mode=this.mode,this.state.currentSpeed=this.horizontalSpeed,this.state.prevRotateToMovementDirection=this.rotateToMovementDirection}createCollisionShape(){const t=this.getColliderHeight(!1),e=this.getColliderRadius(!1),i=new x(t,e);return i.offset.y=this.getCapsuleOffsetY(t,e),i.collisionGroup=xt,i}updateCrouchState(t,e,i,o){if(!(0!==(t.flags&B)))return this.crouchSuppressedUntilRelease=!1,this.slideOnLandingRequested=!1,this.state.mode===A.sliding&&(this.state.mode=A.walking),void this.tryUncrouch();if(this.state.mode===A.sliding&&(!this.slideEnabled||i))return this.slideOnLandingRequested=!1,this.state.mode=A.walking,void(this.crouchSuppressedUntilRelease||this.setCrouching(!0));if(this.state.mode===A.sliding&&o)return this.crouchSuppressedUntilRelease=!0,this.slideOnLandingRequested=!1,void this.tryUncrouch();if(this.crouchSuppressedUntilRelease)return void(this.slideOnLandingRequested=!1);if(this.setCrouching(!0),!this.slideEnabled||i)return void(this.slideOnLandingRequested=!1);if(this.state.mode===A.falling)return void(this.slideOnLandingRequested=!0);this.resolveGroundNormal(Xt);const s=this.slideOnLandingRequested&&this.state.mode===A.walking&&this.state.grounded,n=e&&0!==(t.flags&$)||s;s&&(this.slideOnLandingRequested=!1);const r=Qt(this.state.velocity);this.state.mode===A.walking&&St(this.slideEnabled,n,this.state.grounded,this.isWalkableSlideSurface(Xt),i,r,this.slideMinStartSpeed)&&(this.state.mode=A.sliding,this.slideSurfaceNormal.copy(Xt),this.state.velocity.projectOnPlane(this.slideSurfaceNormal),this.state.currentSpeed=Qt(this.state.velocity))}updateSlidingMode(t){const e=t.state,i=t.move;this.resolveGroundNormal(this.slideSurfaceNormal);const o=this.isWalkableSlideSurface(this.slideSurfaceNormal),s=e.velocity.length();if(!e.grounded||!o)return e.mode=A.falling,$t.update(t),A.falling;if(this.slideEnabled&&0!==(i.flags&B)&&!t.rootMotionActive&&0!==(i.flags&Z))return vt(t.outVelocity,e.velocity,this.jumpVelocity),e.velocity.copy(t.outVelocity),e.currentSpeed=Qt(e.velocity),A.falling;if(!gt(this.slideEnabled,0!==(i.flags&B),e.grounded,o,t.rootMotionActive,s,this.slideMinExitSpeed))return e.mode=A.walking,Wt.update(t),A.walking;const n=Mt(e.velocity,e.velocity,this.slideSurfaceNormal,t.rotatedDirection,this.getEffectiveGravity(),t.deltaTime,this.slideDeceleration,this.slideGravityScale,this.slideSteeringRate);if(e.currentSpeed=Qt(e.velocity),n<Math.max(0,this.slideMinExitSpeed))return e.mode=A.walking,Wt.update(t),A.walking;t.outVelocity.copy(e.velocity).add(t.platformVelocity)}tryUncrouch(){this.isCrouching&&this.canUncrouch()&&this.setCrouching(!1)&&(this.suppressUncrouchLift=!0,this.state.fallGraceTime=0)}resolveGroundNormal(t){return!this.rayTestResult.hasHit||this.rayTestResult.hitNormal.lengthSq()<=1e-8?t.copy(Tt):(t.copy(this.rayTestResult.hitNormal).normalize(),t.dot(Tt)<0&&t.multiplyScalar(-1),t)}isWalkableSlideSurface(t){return t.dot(Tt)>=Math.cos(this.cc.maxSlopeClimbAngle())}setCrouching(t){return this.isCrouching!==t&&(this.isCrouching=t,this.syncColliderShape(),!0)}canUncrouch(){const t=this.getColliderHeight(!1),e=this.getColliderRadius(!1);return!this.physicsSystem.hasActorCapsuleIntersection(this.actor,this.state.position,t,e,this.getCapsuleOffsetY(t,e),this.getCollisionGroup())}syncColliderShape(){const t=this.getColliderHeight(this.isCrouching),e=this.getColliderRadius(this.isCrouching);this.physicsSystem.setActorCapsuleCollider(this.actor,t,e,this.getCapsuleOffsetY(t,e))}getColliderHeight(t){const e=Number.isFinite(this.colliderHeight)?Math.max(0,this.colliderHeight):0;if(!t)return e;const i=Number.isFinite(this.crouchColliderHeight)?this.crouchColliderHeight:e;return r.clamp(i,0,e)}getColliderRadius(t){const e=Number.isFinite(this.colliderRadius)?Math.max(.001,this.colliderRadius):.001;if(!t)return e;const i=this.crouchColliderRadius??e,o=Number.isFinite(i)?i:e;return r.clamp(o,.001,e)}getCapsuleOffsetY(t,e){return e+t/2+this.offset}checkGrounded(t){Nt.y=-Math.max(.05,this.cc.snapToGroundDistance()),this.physicsSystem.rayTest(Ot.addVectors(t,Yt.set(0,this.offset,0)),jt.addVectors(t,Nt),this.rayTestResult,this.groundRayTestOptions)}resolvePlatformVelocity(t){return t.set(0,0,0),this.rayTestResult.hasHit&&null!=this.rayTestResult.actor&&this.physicsSystem.getLinearVelocity(this.rayTestResult.actor,t),t}getCollisionGroup(){return this.characterCollision?null:xt}};t([T(),e("design:type",Number)],Zt.prototype,"colliderHeight",void 0),t([T(),e("design:type",Number)],Zt.prototype,"colliderRadius",void 0),t([T(),e("design:type",Number)],Zt.prototype,"crouchColliderHeight",void 0),t([T({optional:!0}),e("design:type",Number)],Zt.prototype,"crouchColliderRadius",void 0),t([g(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"serverMove",null),t([y(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"clientMoveAck",null),t([y(!0),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"clientMoveCorrection",null),t([v(!1),e("design:type",Function),e("design:paramtypes",[Uint8Array]),e("design:returntype",void 0)],Zt.prototype,"simulatedState",null),Zt=t([R({inEditor:!1}),e("design:paramtypes",[])],Zt);export{Zt as CharacterMovementComponent};const Wt={mode:A.walking,update(t){const e=t.component,i=t.move,o=t.state,s=t.rotatedDirection,n=Math.min(1,Math.sqrt(i.inputX*i.inputX+i.inputY*i.inputY)),r=!e.rotateToMovementDirection&&i.inputY<0,a=e.isCrouching,h=!t.rootMotionActive&&!a&&0===(i.flags&B)&&0!==(i.flags&Q)&&!r&&0!==s.lengthSq()&&(e.sprintPolicy?.canSprint()??!0),l=(a?e.maxSpeedCrouch:r?e.maxSpeedBackwards:h?e.maxSpeedSprint:e.maxSpeed)*(e.normalizedDirection?1:n);if(0!==s.lengthSq()){e.isSprinting=h,h&&e.sprintPolicy?.commitSprint(t.deltaTime,i.sequence);let a=Math.min(l,o.currentSpeed),c=e.groundAccelerationRate;if(h&&t.startedSprinting&&e.sprintStartBoostSpeed>0){const t=e.normalizedDirection?1:n;a=Math.max(a,l+e.sprintStartBoostSpeed*t),c=e.sprintStartBoostDamping}else h&&!r&&e.sprintStartBoostSpeed>0&&o.currentSpeed>l&&(a=o.currentSpeed,c=e.sprintStartBoostDamping);o.currentSpeed=function(t,e,i,o){return e+(t-e)*Math.exp(-i*o)}(a,l,c,t.deltaTime),t.outVelocity.copy(s).multiplyScalar(function(t,e,i,o){const s=i*o;if(s<=1e-6)return t;return e+(t-e)*(1-Math.exp(-s))/s}(a,l,c,t.deltaTime))}else o.currentSpeed=0,t.outVelocity.set(0,0,0);if(0!==(i.flags&Z))return o.mode=A.falling,o.velocity.copy(t.outVelocity),o.velocity.y=e.jumpVelocity,A.falling;t.outVelocity.y=t.deltaTime*e.getEffectiveGravity(),t.outVelocity.add(t.platformVelocity)}},$t={mode:A.falling,update(t){const e=t.component,i=t.state,o=t.move;0!==(o.flags&Z)&&e.jumpInAir&&(i.velocity.copy(t.outVelocity),i.velocity.y=e.jumpVelocity),i.velocity.y+=t.deltaTime*e.getEffectiveGravity(),t.outVelocity.copy(i.velocity),t.outVelocity.addScaledVector(t.rotatedDirection,e.fallingMovementControl),e.fallingReorientation&&t.outVelocity.applyAxisAngle(Tt,r.euclideanModulo(o.yaw-i.lookYaw+Math.PI,2*Math.PI)-Math.PI)}};function Qt(t){return Math.sqrt(t.x*t.x+t.z*t.z)}function Jt(t,e){return e.sequence=t.sequence,e.clientTime=t.clientTime,e.dt=t.dt,e.inputX=t.inputX,e.inputY=t.inputY,e.yaw=t.yaw,e.flags=t.flags,e.clientX=t.clientX,e.clientY=t.clientY,e.clientZ=t.clientZ,e.rootMotionX=t.rootMotionX,e.rootMotionY=t.rootMotionY,e.rootMotionZ=t.rootMotionZ,e}function Kt(t,e){const i=t.position.x-e.clientX,o=t.position.y-e.clientY,s=t.position.z-e.clientZ;return i*i+o*o+s*s}class _t{constructor(t){this.scene=t,this.serverPosition=new h,this.direction=new h}update(t,e){const i=this.serverPosition.set(e.x,e.y,e.z),o=i.distanceTo(t);o>.1&&console.log(`Correction applied. Error: ${o.toFixed(3)}. Server position: (${i.x.toFixed(2)}, ${i.y.toFixed(2)}, ${i.z.toFixed(2)}), Client position: (${t.x.toFixed(2)}, ${t.y.toFixed(2)}, ${t.z.toFixed(2)})`);const s=this.direction.copy(i).sub(t).normalize();te.position.copy(t),te.setDirection(s),te.setLength(o);const n=ee(this.scene);n.add(te),setTimeout(()=>{n.remove(te)},1e3)}}const te=new n(new h(0,1,0),new h,1,16711680);function ee(t){return null==t.parent?t:ee(t.parent)}const ie={immediate:!1,savedRootMotion:!0};/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,33 @@
1
+ import { NodeState, type BehaviorTreeContext, type Node, type StopReason } from './bt.js';
2
+ /** Owns one tree instance. Build the topology before construction; do not share nodes. */
3
+ export declare class BehaviorTree implements BehaviorTreeContext {
4
+ readonly root: Node;
5
+ private readonly executions;
6
+ private readonly activeNodes;
7
+ private current;
8
+ private elapsed;
9
+ private visit;
10
+ private updating;
11
+ private ticks;
12
+ constructor(root: Node);
13
+ get dt(): number;
14
+ /** Unordered live view, intended for inspection. */
15
+ get active(): readonly Node[];
16
+ getState(node: Node): NodeState | undefined;
17
+ isActive(node: Node): boolean;
18
+ /** Monotonic update number, including updates that throw. */
19
+ get tickCount(): number;
20
+ /** Last update that evaluated this node; zero means never evaluated. */
21
+ getLastTick(node: Node): number;
22
+ /** Last completion/interruption reason; cleared when execution starts again. */
23
+ getStopReason(node: Node): StopReason | undefined;
24
+ tick(dt: number): NodeState;
25
+ execute(node: Node, dt?: number): NodeState;
26
+ /** Abort a subtree, or the whole tree when called without an argument. */
27
+ abort(node?: Node): void;
28
+ retain(node: Node): void;
29
+ private finish;
30
+ private lookup;
31
+ private register;
32
+ }
33
+ //# sourceMappingURL=behavior-tree.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{NodeState as t}from"./bt.js";export class BehaviorTree{constructor(t){this.root=t,this.executions=new Map,this.activeNodes=[],this.elapsed=0,this.visit=0,this.updating=!1,this.ticks=0,this.register(t,void 0)}get dt(){return this.elapsed}get active(){return this.activeNodes}getState(t){return this.lookup(t).result}isActive(t){return this.lookup(t).active}get tickCount(){return this.ticks}getLastTick(t){return this.lookup(t).lastTick}getStopReason(t){return this.lookup(t).stopReason}tick(t){if(this.updating)throw new Error("BehaviorTree.tick cannot be reentered");this.updating=!0,this.ticks++,this.elapsed=t;try{return this.execute(this.root)}catch(t){try{this.abort(this.root)}catch{}throw t}finally{this.updating=!1}}execute(e,i=this.elapsed){const s=this.lookup(e);if(!this.updating||(this.current?s.parent!==this.current:e!==this.root))throw new Error("Execute nodes through tree.tick or their parent context");if(s.executing)throw new Error("A node cannot execute recursively");const r=this.current,o=this.elapsed,n=++this.visit;s.visited=n,s.lastTick=this.ticks,s.executing=!0,this.current=s,this.elapsed=i;try{s.active||(s.active=!0,s.activeIndex=this.activeNodes.length,this.activeNodes.push(e),s.result=void 0,s.stopReason=void 0,e.start());const r=e.tick(i,this);if(r!==t.RUNNING&&r!==t.SUCCESS&&r!==t.FAILURE)throw new Error("Node returned an invalid execution result");if(s.result=r,r!==t.RUNNING)this.finish(s,r===t.SUCCESS?"success":"failure");else for(const t of s.children)t.active&&t.visited<=n&&this.finish(t,"aborted");return r}finally{s.executing=!1,this.current=r,this.elapsed=o}}abort(t=this.root){const e=this.lookup(t);if(e.executing)throw new Error("Cannot abort a node during its own execution");this.finish(e,"aborted")}retain(t){const e=this.lookup(t);if(!this.current||e.parent!==this.current)throw new Error("Only the executing parent can retain its child");e.visited=++this.visit}finish(t,e){if(!t.active)return;let i,s=!1;for(const e of t.children)try{this.finish(e,"aborted")}catch(t){s||(i=t,s=!0)}if(t.active){t.active=!1,t.stopReason=e;const r=this.activeNodes.pop();r!==t.node&&(this.activeNodes[t.activeIndex]=r,this.lookup(r).activeIndex=t.activeIndex),t.activeIndex=-1;try{t.node.stop(e)}catch(t){s||(i=t,s=!0)}}if(s)throw i}lookup(t){const e=this.executions.get(t);if(!e)throw new Error("Node is not part of this behavior tree");return e}register(t,e){if(this.executions.has(t))throw new Error("Behavior tree nodes cannot be shared or cyclic");const i={node:t,parent:e,children:[],active:!1,activeIndex:-1,executing:!1,visited:0,result:void 0,lastTick:0,stopReason:void 0};this.executions.set(t,i);for(const e of t.getChildren())i.children.push(this.register(e,i));return i}}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=behavior-tree.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{describe as t,expect as e,it as o,vi as a}from"vitest";import{BehaviorTree as n}from"./behavior-tree.js";import{Node as i,NodeState as s,SequenceNode as c,GuardNode as r,ThrottleNode as l}from"./bt.js";class d extends i{constructor(t=s.RUNNING){super(),this.result=t,this.start=a.fn(),this.stop=a.fn(t=>{}),this.tick=a.fn((t,e)=>this.result)}}class h extends i{constructor(t){super(),this.child=t,this.enabled=!0}getChildren(){return[this.child]}tick(t,e){return this.enabled&&e.execute(this.child,t),s.RUNNING}}t("BehaviorTree lifecycle",()=>{o("exposes instant evaluations and distinguishes old results from current activity",()=>{const t=new d(s.SUCCESS),o=new d,a=new c;a.addChild(t),a.addChild(o);const i=new n(a);e(i.tickCount).toBe(0),e(i.getLastTick(t)).toBe(0),i.tick(.1),e(i.isActive(t)).toBe(!1),e(i.getState(t)).toBe(s.SUCCESS),e(i.getLastTick(t)).toBe(1),e(i.getStopReason(t)).toBe("success"),i.tick(.1),e(i.tickCount).toBe(2),e(i.getLastTick(t)).toBe(1),e(i.getLastTick(o)).toBe(2),i.abort(),e(i.getState(o)).toBe(s.RUNNING),e(i.isActive(o)).toBe(!1),e(i.getStopReason(o)).toBe("aborted"),i.tick(.1),e(i.getStopReason(o)).toBeUndefined(),e(i.getLastTick(t)).toBe(3)}),o("does not report retained descendants as evaluated during a skipped update",()=>{const t=new d,o=new n(new l(t,1));o.tick(.1),o.tick(.1),e(o.isActive(t)).toBe(!0),e(o.getLastTick(t)).toBe(1),e(o.tickCount).toBe(2),e(o.getStopReason(t)).toBeUndefined()}),o("starts once, stops once, and restarts after completion",()=>{const t=new d,o=new n(t);o.tick(.1),o.tick(.1),e(t.start).toHaveBeenCalledTimes(1),e(o.active).toEqual([t]),e(o.getState(t)).toBe(s.RUNNING),t.result=s.SUCCESS,o.tick(.1),e(t.stop).toHaveBeenCalledExactlyOnceWith("success"),e(o.active).toEqual([]),o.tick(.1),e(t.start).toHaveBeenCalledTimes(2),e(t.stop).toHaveBeenCalledTimes(2)}),o("pairs start and stop for immediate failure",()=>{const t=new d(s.FAILURE),o=new n(t);e(o.tick(.1)).toBe(s.FAILURE),e(t.start).toHaveBeenCalledTimes(1),e(t.stop).toHaveBeenCalledExactlyOnceWith("failure")}),o("stops descendants before their parent and makes abort idempotent",()=>{const t=[],o=new d,a=new h(o),i=new n(a);o.stop.mockImplementation(()=>{t.push("child")}),a.stop=()=>{t.push("parent")},i.tick(.1),i.abort(),i.abort(),e(t).toEqual(["child","parent"]),e(i.active).toEqual([]),i.tick(.1),e(o.start).toHaveBeenCalledTimes(2)}),o("automatically cancels an abandoned running child",()=>{const t=new d,o=new h(t),a=new n(o);a.tick(.1),o.enabled=!1,a.tick(.1),e(t.stop).toHaveBeenCalledExactlyOnceWith("aborted"),e(a.active).toEqual([o])}),o("retains a throttled subtree without restarting or ticking it",()=>{const t=new d,o=new c;o.addChild(t);const a=new l(o,1),i=new n(a);i.tick(.1),i.tick(.1),i.tick(.1),e(t.start).toHaveBeenCalledTimes(1),e(t.tick).toHaveBeenCalledTimes(1),e(t.stop).not.toHaveBeenCalled(),e(i.active).toHaveLength(3),i.abort(),e(t.stop).toHaveBeenCalledExactlyOnceWith("aborted")}),o("restores context dt after a child executes with accumulated time",()=>{const t=[],o=new d;new n(new class extends h{tick(e,o){return t.push(o.dt),o.execute(this.child,.75),t.push(o.dt),s.RUNNING}}(o)).tick(.1),e(t).toEqual([.1,.1]),e(o.tick.mock.calls[0][0]).toBe(.75)}),o("cleans up when start or tick throws and remains reusable",()=>{const t=new d,o=new n(t);t.start.mockImplementationOnce(()=>{throw new Error("start failure")}),e(()=>o.tick(.1)).toThrow("start failure"),e(t.stop).toHaveBeenCalledExactlyOnceWith("aborted"),e(o.active).toEqual([]),o.tick(.1),t.tick.mockImplementationOnce(()=>{throw new Error("tick failure")}),e(()=>o.tick(.1)).toThrow("tick failure"),e(o.active).toEqual([]),o.tick(.1),e(o.isActive(t)).toBe(!0)}),o("continues cleaning siblings and parents if a stop hook throws",()=>{const t=new d,o=new d;const c=new class extends i{constructor(){super(...arguments),this.stop=a.fn()}getChildren(){return[t,o]}tick(e,a){return a.execute(t,e),a.execute(o,e),s.RUNNING}},r=new n(c);t.stop.mockImplementationOnce(()=>{throw new Error("stop failure")}),r.tick(.1),e(()=>r.abort()).toThrow("stop failure"),e(o.stop).toHaveBeenCalledExactlyOnceWith("aborted"),e(c.stop).toHaveBeenCalledExactlyOnceWith("aborted"),e(r.active).toEqual([])}),o("rejects shared children, cycles, foreign nodes and reentrant ticks",()=>{const t=new d,o=new c;o.addChild(t),o.addChild(t),e(()=>new n(o)).toThrow("shared or cyclic");const a=new c;a.addChild(a),e(()=>new n(a)).toThrow("shared or cyclic");const i=new n(t);e(()=>i.execute(t)).toThrow("through tree.tick"),e(()=>i.abort(new d)).toThrow("not part"),t.tick.mockImplementationOnce(()=>i.tick(.1)),e(()=>i.tick(.1)).toThrow("reentered"),e(i.active).toEqual([])}),o("starts a fresh guarded execution after interruption",()=>{let t=!0;const o=new d,a=new r(o,()=>t),i=new n(a);i.tick(.1),t=!1,e(i.tick(.1)).toBe(s.FAILURE),e(o.stop).toHaveBeenCalledExactlyOnceWith("aborted"),t=!0,i.tick(.1),e(o.start).toHaveBeenCalledTimes(2)})});/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,15 +1,28 @@
1
- export declare abstract class Node {
2
- /**
3
- * @param dt The amount of time passed between behaviour tree updates
4
- * to be used by actions that depend on the time elapsed in game.
5
- */
6
- abstract tick(dt: number): NodeState;
7
- }
8
1
  export declare enum NodeState {
9
2
  SUCCESS = 0,
10
3
  FAILURE = 1,
11
4
  RUNNING = 2
12
5
  }
6
+ export type StopReason = 'success' | 'failure' | 'aborted';
7
+ export interface BehaviorTreeContext {
8
+ readonly dt: number;
9
+ execute(node: Node, dt?: number): NodeState;
10
+ abort(node: Node): void;
11
+ /** Preserve a running subtree when intentionally skipping its update. */
12
+ retain(node: Node): void;
13
+ }
14
+ export declare abstract class Node {
15
+ /** Optional human-readable label for development inspectors. */
16
+ debugLabel?: string;
17
+ /** dt is elapsed game time in seconds. */
18
+ abstract tick(dt: number, context: BehaviorTreeContext): NodeState;
19
+ /** Called once before the first update of each execution. */
20
+ start(): void;
21
+ /** Called once on completion or interruption, after active descendants stop. */
22
+ stop(_reason: StopReason): void;
23
+ /** Children are fixed for the lifetime of a runtime; nodes must not be shared. */
24
+ getChildren(): readonly Node[];
25
+ }
13
26
  export declare abstract class LeafNode extends Node {
14
27
  }
15
28
  export declare class ActionNode extends LeafNode {
@@ -27,6 +40,17 @@ export declare class FailNode extends LeafNode {
27
40
  constructor(action: () => unknown);
28
41
  tick(): NodeState;
29
42
  }
43
+ /** Starts once; aborted completions are ignored. Rejections produce FAILURE. */
44
+ export declare class AsyncActionNode extends LeafNode {
45
+ private action;
46
+ private result;
47
+ private execution;
48
+ constructor(action: () => Promise<NodeState>);
49
+ start(): void;
50
+ tick(): NodeState;
51
+ private finish;
52
+ stop(): void;
53
+ }
30
54
  export declare class ConditionNode extends LeafNode {
31
55
  private condition;
32
56
  constructor(condition: () => boolean);
@@ -34,68 +58,73 @@ export declare class ConditionNode extends LeafNode {
34
58
  }
35
59
  export declare abstract class CompositeNode extends Node {
36
60
  protected children: Node[];
61
+ getChildren(): readonly Node[];
37
62
  addChild(node: Node): void;
38
63
  }
64
+ /** Resumes the running child without repeating completed steps. */
39
65
  export declare class SequenceNode extends CompositeNode {
40
66
  private current;
41
- tick(dt: number): NodeState;
42
- reset(): void;
67
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
68
+ stop(): void;
43
69
  }
70
+ /** Reactive selector: higher priorities are checked every tick. */
44
71
  export declare class SelectorNode extends CompositeNode {
45
- tick(dt: number): NodeState;
72
+ private runningChild;
73
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
74
+ stop(): void;
46
75
  }
47
76
  export declare abstract class DecoratorNode extends Node {
48
77
  protected child: Node;
49
78
  constructor(child: Node);
79
+ getChildren(): readonly Node[];
80
+ }
81
+ /** Updates shared state before its branch on every active tick, including while tasks run.
82
+ * Services do not select branches or complete tasks; the supplied child owns execution.
83
+ * Use start/stop for service activation and cleanup. */
84
+ export declare abstract class ServiceNode extends DecoratorNode {
85
+ protected abstract update(dt: number, context: BehaviorTreeContext): void;
86
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
50
87
  }
51
88
  export declare class InverterNode extends DecoratorNode {
52
- tick(dt: number): NodeState;
89
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
53
90
  }
91
+ /** At most one iteration per tick, including for the default infinite limit. */
54
92
  export declare class RepeatTimesNode extends DecoratorNode {
55
93
  private limit;
56
94
  private counter;
57
95
  constructor(child: Node, limit?: number);
58
- tick(dt: number): NodeState;
96
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
97
+ stop(): void;
59
98
  }
60
99
  export declare class RepeatNode extends DecoratorNode {
61
- constructor(child: Node);
62
- tick(dt: number): NodeState;
100
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
63
101
  }
64
- /**
65
- * Repeats its child node until a specific condition is met, then stops.
66
- * Useful for looping actions like searching for the player until they’re found.
67
- */
68
102
  export declare class RepeatUntilNode extends DecoratorNode {
69
103
  private condition;
70
104
  constructor(child: Node, condition: () => boolean);
71
- tick(dt: number): NodeState;
105
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
72
106
  }
73
107
  export declare class RepeatUntilFailNode extends DecoratorNode {
74
- constructor(child: Node);
75
- tick(dt: number): NodeState;
108
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
76
109
  }
77
- /**
78
- * Delay starting the child node.
79
- * Can be used when performing multiple actions in parallel and one should start slightly later.
80
- */
110
+ /** Delay in milliseconds before starting the child. */
81
111
  export declare class DelayNode extends DecoratorNode {
82
112
  private delay;
83
- private state;
84
113
  private elapsed;
85
114
  constructor(child: Node, delay: number);
86
- tick(dt: number): NodeState;
115
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
116
+ stop(): void;
87
117
  }
88
- /**
89
- * Delay after the child node
90
- * Used to stop from making any actions.
91
- */
118
+ /** Delay in milliseconds after the child finishes, preserving its result. */
92
119
  export declare class DelayAfterNode extends DecoratorNode {
93
120
  private delay;
94
- private state;
95
121
  private elapsed;
122
+ private state;
96
123
  constructor(child: Node, delay: number);
97
- tick(dt: number): NodeState;
124
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
125
+ stop(): void;
98
126
  }
127
+ /** Wait duration in milliseconds. */
99
128
  export declare class WaitNode extends LeafNode {
100
129
  private delayMin;
101
130
  private delayMax?;
@@ -104,68 +133,61 @@ export declare class WaitNode extends LeafNode {
104
133
  constructor(delayMin: number, delayMax?: number);
105
134
  tick(dt: number): NodeState;
106
135
  reset(): void;
136
+ stop(): void;
137
+ start(): void;
107
138
  }
108
- /**
109
- * Prevents its child node from executing until a cooldown period has passed.
110
- * Useful for enforcing time constraints, like ensuring an NPC cannot attack again too quickly.
111
- */
139
+ /** Cooldown in wall-clock milliseconds, preserved across interruptions. */
112
140
  export declare class CooldownNode extends DecoratorNode {
113
141
  private cooldownTime;
114
142
  private lastExecutionTime;
115
143
  constructor(child: Node, cooldownTime: number);
116
- tick(dt: number): NodeState;
144
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
117
145
  }
118
- /**
119
- * Execute an action for a limited amount of time, such as searching for a player for 10 seconds before giving up.
120
- */
146
+ /** Maximum execution duration in wall-clock milliseconds. */
121
147
  export declare class TimerNode extends DecoratorNode {
122
148
  private duration;
123
149
  private startTime;
124
150
  constructor(child: Node, duration: number);
125
- tick(dt: number): NodeState;
151
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
152
+ stop(): void;
126
153
  }
127
- /**
128
- * Selects a child node randomly, but with weights assigned to each node to influence the likelihood of selection.
129
- * Add randomness to NPC behavior, like having a higher chance to patrol but occasionally stopping to rest.
130
- */
154
+ /** Retains the randomly selected child until it finishes. */
131
155
  export declare class WeightedRandomSelectorNode extends CompositeNode {
156
+ private current;
132
157
  private weights;
133
158
  private totalWeight;
134
159
  constructor(weights: number[]);
135
160
  private getRandomIndex;
136
- tick(dt: number): NodeState;
161
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
162
+ stop(): void;
137
163
  }
138
- /**
139
- * Executes its child node only if a condition is met.
140
- * Add conditional logic to restrict when a node should run, such as checking if the player is within a certain range.
141
- *
142
- * Compared to ConditionNode, it can be used for any node when a precondition has to be met rathern
143
- * than using sequence nodes with consitions. For example, check that the character has a specific
144
- * resource before trying.
145
- */
146
164
  export declare class GuardNode extends DecoratorNode {
147
165
  private condition;
148
166
  constructor(child: Node, condition: () => boolean);
149
- tick(dt: number): NodeState;
167
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
150
168
  }
151
- /**
152
- * Executes all children in parallel and returns success as soon as any child node succeeds. It fails only if all children fail.
153
- * Perform multiple checks simultaneously, such as detecting threats from multiple sources, and succeed if any are found.
154
- */
155
- export declare class ParallelSelectorNode extends CompositeNode {
156
- tick(dt: number): NodeState;
169
+ /** Stores terminal results until the parallel execution completes. */
170
+ declare abstract class ParallelNode extends CompositeNode {
171
+ private states;
172
+ protected tickParallel(dt: number, context: BehaviorTreeContext, terminal: NodeState): NodeState;
173
+ stop(): void;
157
174
  }
158
- /**
159
- * Executes all children in parallel and only succeeds when all children succeed. It fails as soon as any child fails.
160
- * Use this for tasks that must all complete simultaneously, such as preparing a coordinated attack.
161
- */
162
- export declare class ParallelSequenceNode extends CompositeNode {
163
- tick(dt: number): NodeState;
175
+ /** Succeeds on any success; fails when all children fail. */
176
+ export declare class ParallelSelectorNode extends ParallelNode {
177
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
178
+ }
179
+ /** Succeeds when all children succeed; fails on any failure. */
180
+ export declare class ParallelSequenceNode extends ParallelNode {
181
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
164
182
  }
183
+ /** Duration in seconds. Skipped updates accumulate into the child's dt. */
165
184
  export declare class ThrottleNode extends DecoratorNode {
166
185
  private duration;
186
+ private elapsed;
187
+ private started;
167
188
  constructor(child: Node, duration: number);
168
- private timeSinceLastTick;
169
- tick(dt: number): NodeState;
189
+ tick(dt: number, context: BehaviorTreeContext): NodeState;
190
+ stop(): void;
170
191
  }
192
+ export {};
171
193
  //# sourceMappingURL=bt.d.ts.map
@@ -1,4 +1,4 @@
1
- export class Node{}export var NodeState;!function(t){t[t.SUCCESS=0]="SUCCESS",t[t.FAILURE=1]="FAILURE",t[t.RUNNING=2]="RUNNING"}(NodeState||(NodeState={}));export class LeafNode extends Node{}export class ActionNode extends LeafNode{constructor(t){super(),this.action=t}tick(){return this.action()}}export class SuccessNode extends LeafNode{constructor(t){super(),this.action=t}tick(){return this.action(),NodeState.SUCCESS}}export class FailNode extends LeafNode{constructor(t){super(),this.action=t}tick(){return this.action(),NodeState.FAILURE}}export class ConditionNode extends LeafNode{constructor(t){super(),this.condition=t}tick(){return this.condition()?NodeState.SUCCESS:NodeState.FAILURE}}export class CompositeNode extends Node{constructor(){super(...arguments),this.children=[]}addChild(t){this.children.push(t)}}export class SequenceNode extends CompositeNode{constructor(){super(...arguments),this.current=0}tick(t){if(0===this.children.length)return this.reset(),NodeState.SUCCESS;const e=this.children[this.current].tick(t);if(e===NodeState.FAILURE)return this.reset(),NodeState.FAILURE;if(e===NodeState.SUCCESS){if(this.current==this.children.length-1)return this.reset(),NodeState.SUCCESS;this.current++}return NodeState.SUCCESS}reset(){this.current=0}}export class SelectorNode extends CompositeNode{tick(t){for(const e of this.children){const s=e.tick(t);if(s!==NodeState.FAILURE)return s}return NodeState.FAILURE}}export class DecoratorNode extends Node{constructor(t){super(),this.child=t}}export class InverterNode extends DecoratorNode{tick(t){const e=this.child.tick(t);return e===NodeState.SUCCESS?NodeState.FAILURE:e===NodeState.FAILURE?NodeState.SUCCESS:e}}export class RepeatTimesNode extends DecoratorNode{constructor(t,e=1/0){super(t),this.counter=0,this.limit=e}tick(t){for(;this.counter<this.limit;){if(this.child.tick(t)===NodeState.RUNNING)return NodeState.RUNNING;this.counter++}return this.counter=0,NodeState.SUCCESS}}export class RepeatNode extends DecoratorNode{constructor(t){super(t)}tick(t){return this.child.tick(t),NodeState.RUNNING}}export class RepeatUntilNode extends DecoratorNode{constructor(t,e){super(t),this.condition=e}tick(t){if(this.condition())return NodeState.SUCCESS;return this.child.tick(t)===NodeState.FAILURE?NodeState.FAILURE:NodeState.RUNNING}}export class RepeatUntilFailNode extends DecoratorNode{constructor(t){super(t)}tick(t){return this.child.tick(t)===NodeState.FAILURE?NodeState.FAILURE:NodeState.RUNNING}}export class DelayNode extends DecoratorNode{constructor(t,e){super(t),this.state=NodeState.RUNNING,this.elapsed=null,this.delay=e}tick(t){return null===this.elapsed&&(this.elapsed=0),this.elapsed+=1e3*t,this.elapsed>=this.delay&&(this.state=this.child.tick(t),this.state!==NodeState.RUNNING&&(this.elapsed=null)),this.state}}export class DelayAfterNode extends DecoratorNode{constructor(t,e){super(t),this.state=NodeState.RUNNING,this.elapsed=null,this.delay=e}tick(t){if(null==this.elapsed){if(this.state=this.child.tick(t),this.state===NodeState.RUNNING)return this.state;this.elapsed=0}return this.elapsed+=1e3*t,this.elapsed<this.delay?NodeState.RUNNING:(this.elapsed=null,this.state)}}export class WaitNode extends LeafNode{constructor(t,e){super(),this.delayMin=t,this.delayMax=e,this.elapsed=null,this.delay=this.delayMin,this.reset()}tick(t){return null===this.elapsed&&(this.elapsed=0),this.elapsed+=1e3*t,this.elapsed>=this.delay?(this.elapsed=null,this.reset(),NodeState.SUCCESS):NodeState.RUNNING}reset(){null!=this.delayMax?this.delay=(this.delayMax-this.delayMin)*Math.random()+this.delayMin:this.delay=this.delayMin}}export class CooldownNode extends DecoratorNode{constructor(t,e){super(t),this.cooldownTime=e,this.lastExecutionTime=null}tick(t){const e=Date.now();if(null===this.lastExecutionTime||e-this.lastExecutionTime>=this.cooldownTime){const s=this.child.tick(t);return s===NodeState.SUCCESS&&(this.lastExecutionTime=e),s}return NodeState.FAILURE}}export class TimerNode extends DecoratorNode{constructor(t,e){super(t),this.startTime=null,this.duration=e}tick(t){null===this.startTime&&(this.startTime=Date.now());return Date.now()-this.startTime<this.duration?this.child.tick(t):(this.startTime=null,NodeState.FAILURE)}}export class WeightedRandomSelectorNode extends CompositeNode{constructor(t){super(),this.weights=t,this.totalWeight=this.weights.reduce((t,e)=>t+e,0)}getRandomIndex(){let t=Math.random()*this.totalWeight;for(let e=0;e<this.weights.length;e++)if(t-=this.weights[e],t<=0)return e;return this.weights.length-1}tick(t){const e=this.getRandomIndex();return this.children[e].tick(t)}}export class GuardNode extends DecoratorNode{constructor(t,e){super(t),this.condition=e}tick(t){return this.condition()?this.child.tick(t):NodeState.FAILURE}}export class ParallelSelectorNode extends CompositeNode{tick(t){let e=!0;for(const s of this.children){const i=s.tick(t);if(i===NodeState.SUCCESS)return NodeState.SUCCESS;i===NodeState.RUNNING&&(e=!1)}return e?NodeState.FAILURE:NodeState.RUNNING}}export class ParallelSequenceNode extends CompositeNode{tick(t){let e=!0;for(const s of this.children){const i=s.tick(t);if(i===NodeState.FAILURE)return NodeState.FAILURE;i===NodeState.RUNNING&&(e=!1)}return e?NodeState.SUCCESS:NodeState.RUNNING}}export class ThrottleNode extends DecoratorNode{constructor(t,e){super(t),this.duration=e,this.timeSinceLastTick=0}tick(t){return 0===this.timeSinceLastTick||this.timeSinceLastTick>this.duration?(this.timeSinceLastTick=t,this.child.tick(this.timeSinceLastTick)):(this.timeSinceLastTick+=t,NodeState.RUNNING)}}/*
1
+ export var NodeState;!function(t){t[t.SUCCESS=0]="SUCCESS",t[t.FAILURE=1]="FAILURE",t[t.RUNNING=2]="RUNNING"}(NodeState||(NodeState={}));export class Node{start(){}stop(t){}getChildren(){return[]}}export class LeafNode extends Node{}export class ActionNode extends LeafNode{constructor(t){super(),this.action=t}tick(){return this.action()}}export class SuccessNode extends LeafNode{constructor(t){super(),this.action=t}tick(){return this.action(),NodeState.SUCCESS}}export class FailNode extends LeafNode{constructor(t){super(),this.action=t}tick(){return this.action(),NodeState.FAILURE}}export class AsyncActionNode extends LeafNode{constructor(t){super(),this.action=t,this.execution=0}start(){this.result=void 0;const t=++this.execution;try{this.action().then(e=>this.finish(t,e),()=>this.finish(t,NodeState.FAILURE))}catch{this.result=NodeState.FAILURE}}tick(){return this.result??NodeState.RUNNING}finish(t,e){t===this.execution&&(this.result=e)}stop(){this.execution++,this.result=void 0}}export class ConditionNode extends LeafNode{constructor(t){super(),this.condition=t}tick(){return this.condition()?NodeState.SUCCESS:NodeState.FAILURE}}export class CompositeNode extends Node{constructor(){super(...arguments),this.children=[]}getChildren(){return this.children}addChild(t){this.children.push(t)}}export class SequenceNode extends CompositeNode{constructor(){super(...arguments),this.current=0}tick(t,e){for(;this.current<this.children.length;){const s=e.execute(this.children[this.current],t);if(s===NodeState.RUNNING)return s;if(s===NodeState.FAILURE)return this.current=0,s;this.current++}return this.current=0,NodeState.SUCCESS}stop(){this.current=0}}export class SelectorNode extends CompositeNode{tick(t,e){for(const s of this.children){const i=e.execute(s,t);if(i!==NodeState.FAILURE)return this.runningChild!==s&&this.runningChild&&e.abort(this.runningChild),this.runningChild=i===NodeState.RUNNING?s:void 0,i;this.runningChild===s&&(this.runningChild=void 0)}return NodeState.FAILURE}stop(){this.runningChild=void 0}}export class DecoratorNode extends Node{constructor(t){super(),this.child=t}getChildren(){return[this.child]}}export class ServiceNode extends DecoratorNode{tick(t,e){return this.update(t,e),e.execute(this.child,t)}}export class InverterNode extends DecoratorNode{tick(t,e){const s=e.execute(this.child,t);return s===NodeState.SUCCESS?NodeState.FAILURE:s===NodeState.FAILURE?NodeState.SUCCESS:s}}export class RepeatTimesNode extends DecoratorNode{constructor(t,e=1/0){super(t),this.limit=e,this.counter=0}tick(t,e){if(this.counter>=this.limit)return this.counter=0,NodeState.SUCCESS;const s=e.execute(this.child,t);return s===NodeState.RUNNING?s:(this.counter++,this.counter>=this.limit?(this.counter=0,NodeState.SUCCESS):NodeState.RUNNING)}stop(){this.counter=0}}export class RepeatNode extends DecoratorNode{tick(t,e){return e.execute(this.child,t),NodeState.RUNNING}}export class RepeatUntilNode extends DecoratorNode{constructor(t,e){super(t),this.condition=e}tick(t,e){return this.condition()?(e.abort(this.child),NodeState.SUCCESS):e.execute(this.child,t)===NodeState.FAILURE?NodeState.FAILURE:NodeState.RUNNING}}export class RepeatUntilFailNode extends DecoratorNode{tick(t,e){return e.execute(this.child,t)===NodeState.FAILURE?NodeState.FAILURE:NodeState.RUNNING}}export class DelayNode extends DecoratorNode{constructor(t,e){super(t),this.delay=e,this.elapsed=0}tick(t,e){if(this.elapsed+=1e3*t,this.elapsed<this.delay)return NodeState.RUNNING;const s=e.execute(this.child,t);return s!==NodeState.RUNNING&&(this.elapsed=0),s}stop(){this.elapsed=0}}export class DelayAfterNode extends DecoratorNode{constructor(t,e){super(t),this.delay=e,this.elapsed=null,this.state=NodeState.RUNNING}tick(t,e){if(null===this.elapsed){if(this.state=e.execute(this.child,t),this.state===NodeState.RUNNING)return this.state;if(this.elapsed=0,this.delay>0)return NodeState.RUNNING}else this.elapsed+=1e3*t;return this.elapsed<this.delay?NodeState.RUNNING:(this.elapsed=null,this.state)}stop(){this.elapsed=null,this.state=NodeState.RUNNING}}export class WaitNode extends LeafNode{constructor(t,e){super(),this.delayMin=t,this.delayMax=e,this.elapsed=0,this.delay=t}tick(t){return this.elapsed+=1e3*t,this.elapsed<this.delay?NodeState.RUNNING:(this.elapsed=0,NodeState.SUCCESS)}reset(){this.elapsed=0,this.delay=null==this.delayMax?this.delayMin:(this.delayMax-this.delayMin)*Math.random()+this.delayMin}stop(){this.elapsed=0}start(){this.reset()}}export class CooldownNode extends DecoratorNode{constructor(t,e){super(t),this.cooldownTime=e,this.lastExecutionTime=null}tick(t,e){const s=Date.now();if(null!==this.lastExecutionTime&&s-this.lastExecutionTime<this.cooldownTime)return NodeState.FAILURE;const i=e.execute(this.child,t);return i===NodeState.SUCCESS&&(this.lastExecutionTime=s),i}}export class TimerNode extends DecoratorNode{constructor(t,e){super(t),this.duration=e,this.startTime=null}tick(t,e){const s=Date.now();if(this.startTime??(this.startTime=s),s-this.startTime>=this.duration)return e.abort(this.child),NodeState.FAILURE;const i=e.execute(this.child,t);return i!==NodeState.RUNNING&&(this.startTime=null),i}stop(){this.startTime=null}}export class WeightedRandomSelectorNode extends CompositeNode{constructor(t){if(super(),t.some(t=>!Number.isFinite(t)||t<0))throw new Error("Selector weights must be finite and non-negative");if(this.weights=t.slice(),this.totalWeight=this.weights.reduce((t,e)=>t+e,0),!Number.isFinite(this.totalWeight))throw new Error("Selector total weight must be finite")}getRandomIndex(){let t=Math.random()*this.totalWeight;for(let e=0;e<this.weights.length;e++)if(t-=this.weights[e],t<0)return e;for(let t=this.weights.length-1;t>=0;t--)if(this.weights[t]>0)return t;return-1}tick(t,e){if(this.children.length!==this.weights.length||this.totalWeight<=0)return NodeState.FAILURE;this.current??(this.current=this.getRandomIndex());const s=e.execute(this.children[this.current],t);return s!==NodeState.RUNNING&&(this.current=void 0),s}stop(){this.current=void 0}}export class GuardNode extends DecoratorNode{constructor(t,e){super(t),this.condition=e}tick(t,e){return this.condition()?e.execute(this.child,t):(e.abort(this.child),NodeState.FAILURE)}}class t extends CompositeNode{constructor(){super(...arguments),this.states=[]}tickParallel(t,e,s){let i=!1;for(let o=0;o<this.children.length;o++){const r=this.states[o],d=void 0===r||r===NodeState.RUNNING?e.execute(this.children[o],t):r;if(this.states[o]=d,d===s)return s;d===NodeState.RUNNING&&(i=!0)}return i?NodeState.RUNNING:(this.states.length=0,s===NodeState.SUCCESS?NodeState.FAILURE:NodeState.SUCCESS)}stop(){this.states.length=0}}export class ParallelSelectorNode extends t{tick(t,e){return this.tickParallel(t,e,NodeState.SUCCESS)}}export class ParallelSequenceNode extends t{tick(t,e){return this.tickParallel(t,e,NodeState.FAILURE)}}export class ThrottleNode extends DecoratorNode{constructor(t,e){super(t),this.duration=e,this.elapsed=0,this.started=!1}tick(t,e){if(this.elapsed+=t,this.started&&this.elapsed<this.duration)return e.retain(this.child),NodeState.RUNNING;this.started=!0;const s=this.elapsed;this.elapsed=0;const i=e.execute(this.child,s);return i!==NodeState.RUNNING&&(this.started=!1),i}stop(){this.elapsed=0,this.started=!1}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bt.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{BehaviorTree as e}from"./behavior-tree.js";import{describe as t,expect as n,it as o,vi as s}from"vitest";import{AsyncActionNode as a,DelayAfterNode as i,DelayNode as r,GuardNode as c,Node as l,NodeState as d,ParallelSelectorNode as w,ParallelSequenceNode as C,RepeatTimesNode as S,RepeatUntilNode as u,SelectorNode as p,SequenceNode as m,ServiceNode as B,ThrottleNode as N,TimerNode as U,WaitNode as h,WeightedRandomSelectorNode as k}from"./bt.js";class E extends l{constructor(e=d.RUNNING){super(),this.state=e,this.tick=s.fn(e=>this.state),this.start=s.fn(),this.stop=s.fn()}}const R=new WeakMap;function v(t){let n=R.get(t);return n||(n=new e(t),R.set(t,n)),n}function I(e,t=0){return v(e).tick(t)}function f(e,...t){return t.forEach(t=>e.addChild(t)),e}t("behavior tree execution",()=>{o("resumes a sequence and only reports success after all steps complete",()=>{const e=new E(d.SUCCESS),t=new E,o=new E(d.SUCCESS),s=f(new m,e,t,o);n(I(s,.1)).toBe(d.RUNNING),n(o.tick).not.toHaveBeenCalled(),t.state=d.SUCCESS,n(I(s,.1)).toBe(d.SUCCESS),n(e.tick).toHaveBeenCalledTimes(1),n(o.tick).toHaveBeenCalledTimes(1)}),o("restarts interrupted sequences from the beginning",()=>{const e=new E(d.SUCCESS),t=new E,o=f(new m,e,t);I(o,.1),v(o).abort(),n(t.stop).toHaveBeenCalledTimes(1),I(o,.1),n(e.tick).toHaveBeenCalledTimes(2)}),o("keeps selectors reactive and aborts the displaced branch once",()=>{const e=new E(d.FAILURE),t=new E,o=f(new p,e,t);I(o,.1),e.state=d.RUNNING,I(o,.1),I(o,.1),n(t.stop).toHaveBeenCalledTimes(1),n(t.tick).toHaveBeenCalledTimes(1),v(o).abort(),n(e.stop).toHaveBeenLastCalledWith("aborted")}),o("retains random choices and rejects unusable weights safely",()=>{const e=s.spyOn(Math,"random").mockReturnValue(0);try{const t=new E,o=new E,s=f(new k([1,1]),t,o);I(s,.1),e.mockReturnValue(.9),I(s,.1),n(o.tick).not.toHaveBeenCalled(),t.state=d.SUCCESS,I(s,.1),I(s,.1),n(o.tick).toHaveBeenCalledTimes(1),n(I(new k([]),.1)).toBe(d.FAILURE),n(()=>new k([-1])).toThrow()}finally{e.mockRestore()}}),o("does not repeat terminal parallel children and cancels unfinished siblings",()=>{const e=new E(d.SUCCESS),t=new E,o=f(new C,e,t);I(o,.1),I(o,.1),n(e.tick).toHaveBeenCalledTimes(1),t.state=d.FAILURE,n(I(o,.1)).toBe(d.FAILURE),e.state=d.RUNNING,t.state=d.SUCCESS;const s=f(new w,e,t);n(I(s,.1)).toBe(d.SUCCESS),n(e.stop).toHaveBeenLastCalledWith("aborted");const a=new E(d.FAILURE),i=new E,r=f(new w,a,i);I(r,.1),I(r,.1),n(a.tick).toHaveBeenCalledTimes(1)}),o("cancels guarded and repeated tasks when their conditions change",()=>{let e=!0;const t=new E,o=new c(t,()=>e);I(o,.1),e=!1,I(o,.1),I(o,.1),n(t.stop).toHaveBeenCalledTimes(1);const s=new u(t,()=>e);I(s,.1),e=!0,n(I(s,.1)).toBe(d.SUCCESS),n(t.stop).toHaveBeenCalledTimes(2)}),o("clears interrupted waits and does not return a stale delay result",()=>{const e=new h(100);I(e,.06),v(e).abort(),n(I(e,.06)).toBe(d.RUNNING),n(I(e,.04)).toBe(d.SUCCESS);const t=new r(new E(d.SUCCESS),100);n(I(t,.1)).toBe(d.SUCCESS),n(I(t,.05)).toBe(d.RUNNING),v(t).abort(),n(I(t,.05)).toBe(d.RUNNING)}),o("delays after completion without counting time before completion",()=>{const e=new i(new E(d.FAILURE),100);n(I(e,1)).toBe(d.RUNNING),n(I(e,.05)).toBe(d.RUNNING),n(I(e,.05)).toBe(d.FAILURE),n(I(e,1)).toBe(d.RUNNING)}),o("bounds repeat work even with the default infinite limit",()=>{const e=new E(d.SUCCESS);n(I(new S(e),.1)).toBe(d.RUNNING),n(e.tick).toHaveBeenCalledTimes(1);const t=new S(e,2);n(I(t,.1)).toBe(d.RUNNING),n(I(t,.1)).toBe(d.SUCCESS)}),o("passes accumulated elapsed time to throttled running tasks",()=>{const e=new E,t=new N(e,.3);I(t,.1),I(t,.1),I(t,.1),I(t,.1),n(e.tick).toHaveBeenCalledTimes(2),n(e.tick.mock.calls[1][0]).toBeCloseTo(.3),v(t).abort(),n(e.stop).toHaveBeenCalledTimes(1)}),o("resets timer deadlines after completion and aborts on timeout",()=>{const e=s.spyOn(Date,"now").mockReturnValue(0);try{const t=new E(d.SUCCESS),o=new U(t,100);n(I(o,.1)).toBe(d.SUCCESS),e.mockReturnValue(200),t.state=d.RUNNING,n(I(o,.1)).toBe(d.RUNNING),e.mockReturnValue(300),n(I(o,.1)).toBe(d.FAILURE),n(t.stop).toHaveBeenLastCalledWith("aborted")}finally{e.mockRestore()}}),o("starts async work once and ignores completion from an aborted execution",async()=>{let e;const t=s.fn(()=>new Promise(t=>{e=t})),o=new a(t);I(o),I(o),n(t).toHaveBeenCalledTimes(1);const i=e;v(o).abort(),I(o),i(d.SUCCESS),await Promise.resolve(),n(I(o)).toBe(d.RUNNING),e(d.FAILURE),await Promise.resolve(),n(I(o)).toBe(d.FAILURE),I(o),n(t).toHaveBeenCalledTimes(3)}),o("reports async rejections and synchronous throws as failure",async()=>{const e=new a(()=>Promise.reject(new Error("failed")));I(e),await Promise.resolve(),n(I(e)).toBe(d.FAILURE),n(I(new a(()=>{throw new Error("failed")}))).toBe(d.FAILURE)})}),t("branch services",()=>{o("updates before a running child and cleans up on interruption",()=>{const t=[];const o=new class extends B{start(){t.push("activate")}update(e){t.push("update:"+e)}stop(){t.push("deactivate")}}(new class extends l{tick(){return t.push("task"),d.RUNNING}stop(){t.push("task stopped")}}),s=new e(o);s.tick(.1),s.tick(.2),s.abort(),n(t).toEqual(["activate","update:0.1","task","update:0.2","task","task stopped","deactivate"])}),o("runs while its branch is selected and propagates completion",()=>{let t=!0,o=0;const s=new E(d.SUCCESS),a=new e(new c(new class extends B{update(){o++}}(s),()=>t));n(a.tick(.1)).toBe(d.SUCCESS),t=!1,n(a.tick(.1)).toBe(d.FAILURE),n(o).toBe(1),n(s.tick).toHaveBeenCalledTimes(1)})});/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -23,6 +23,7 @@ export declare class CharacterMoveToNode extends LeafNode {
23
23
  constructor(navigation: Navigation, movement: CharacterMovementLike);
24
24
  private cardinalAxis?;
25
25
  tick(dt: number): NodeState;
26
+ stop(): void;
26
27
  private snapInputToCardinalAxis;
27
28
  }
28
29
  //# sourceMappingURL=move.d.ts.map
@@ -1,4 +1,4 @@
1
- import{Vector3 as t}from"three";import{LeafNode as i,NodeState as e}from"./bt.js";export class CharacterMoveToNode extends i{constructor(t,i){super(),this.navigation=t,this.movement=i,this.distanceFrom=.5,this.speedScale=1,this.lateralSpeedScale=1,this.cardinalMovement=!1}tick(t){const i=this.movement.actor.object.position,s=null!=this.target?this.target():null;if(null==s)return this.movement.directionInput.vector.set(0,0),this.cardinalAxis=void 0,e.FAILURE;if(i.distanceTo(s)<this.distanceFrom)return this.movement.directionInput.vector.set(0,0),this.cardinalAxis=void 0,e.SUCCESS;const{success:a,path:o}=this.navigation.findPath(i,s);if(!a||o.length<2)return this.movement.directionInput.vector.set(0,0),this.cardinalAxis=void 0,e.FAILURE;const r=o[1],c=n.subVectors(r,i);c.y=0,c.normalize();const h=this.facingTarget?.(),l=null!=h?h.x-i.x:0,m=null!=h?h.z-i.z:0,d=l*l+m*m;if(null!=h&&d>1e-4){const t=Math.atan2(l,m),i=1/Math.sqrt(d),e=l*i,n=m*i,s=n,a=-e;this.movement.rotationInput.rotation.y=t,this.movement.directionInput.vector.set(-(c.x*s+c.z*a),c.x*e+c.z*n)}else this.movement.rotationInput.rotation.y=Math.atan2(c.x,c.z),this.movement.directionInput.vector.set(0,1);return this.cardinalMovement&&this.snapInputToCardinalAxis(),Math.abs(this.movement.directionInput.vector.x)>Math.abs(this.movement.directionInput.vector.y)&&this.movement.directionInput.vector.multiplyScalar(Math.max(0,Math.min(1,this.lateralSpeedScale))),this.movement.directionInput.vector.multiplyScalar(Math.max(0,Math.min(1,this.speedScale))),e.RUNNING}snapInputToCardinalAxis(){const t=this.movement.directionInput.vector,i=Math.abs(t.x),e=Math.abs(t.y);if(i+e<=1e-4)return void(this.cardinalAxis=void 0);const n=i>e?"x":"y";if(null==this.cardinalAxis)this.cardinalAxis=n;else{const t="x"===this.cardinalAxis?i:e;("x"===this.cardinalAxis?e:i)>t*s&&(this.cardinalAxis="x"===this.cardinalAxis?"y":"x")}"x"===this.cardinalAxis?t.set(Math.sign(t.x),0):t.set(0,Math.sign(t.y))}}const n=new t,s=1.25;/*
1
+ import{Vector3 as t}from"three";import{LeafNode as i,NodeState as e}from"./bt.js";export class CharacterMoveToNode extends i{constructor(t,i){super(),this.navigation=t,this.movement=i,this.distanceFrom=.5,this.speedScale=1,this.lateralSpeedScale=1,this.cardinalMovement=!1}tick(t){const i=this.movement.actor.object.position,s=null!=this.target?this.target():null;if(null==s)return this.movement.directionInput.vector.set(0,0),this.cardinalAxis=void 0,e.FAILURE;if(i.distanceTo(s)<this.distanceFrom)return this.movement.directionInput.vector.set(0,0),this.cardinalAxis=void 0,e.SUCCESS;const{success:a,path:o}=this.navigation.findPath(i,s);if(!a||o.length<2)return this.movement.directionInput.vector.set(0,0),this.cardinalAxis=void 0,e.FAILURE;const r=o[1],c=n.subVectors(r,i);c.y=0,c.normalize();const h=this.facingTarget?.(),l=null!=h?h.x-i.x:0,m=null!=h?h.z-i.z:0,d=l*l+m*m;if(null!=h&&d>1e-4){const t=Math.atan2(l,m),i=1/Math.sqrt(d),e=l*i,n=m*i,s=n,a=-e;this.movement.rotationInput.rotation.y=t,this.movement.directionInput.vector.set(-(c.x*s+c.z*a),c.x*e+c.z*n)}else this.movement.rotationInput.rotation.y=Math.atan2(c.x,c.z),this.movement.directionInput.vector.set(0,1);return this.cardinalMovement&&this.snapInputToCardinalAxis(),Math.abs(this.movement.directionInput.vector.x)>Math.abs(this.movement.directionInput.vector.y)&&this.movement.directionInput.vector.multiplyScalar(Math.max(0,Math.min(1,this.lateralSpeedScale))),this.movement.directionInput.vector.multiplyScalar(Math.max(0,Math.min(1,this.speedScale))),e.RUNNING}stop(){this.cardinalAxis=void 0}snapInputToCardinalAxis(){const t=this.movement.directionInput.vector,i=Math.abs(t.x),e=Math.abs(t.y);if(i+e<=1e-4)return void(this.cardinalAxis=void 0);const n=i>e?"x":"y";if(null==this.cardinalAxis)this.cardinalAxis=n;else{const t="x"===this.cardinalAxis?i:e;("x"===this.cardinalAxis?e:i)>t*s&&(this.cardinalAxis="x"===this.cardinalAxis?"y":"x")}"x"===this.cardinalAxis?t.set(Math.sign(t.x),0):t.set(0,Math.sign(t.y))}}const n=new t,s=1.25;/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -2,4 +2,5 @@ export * from './navigation.js';
2
2
  export * from './navigation-areas.js';
3
3
  export * from './behavior-tree/bt.js';
4
4
  export * from './behavior-tree/move.js';
5
+ export * from './behavior-tree/behavior-tree.js';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,4 @@
1
- export*from"./navigation.js";export*from"./navigation-areas.js";export*from"./behavior-tree/bt.js";export*from"./behavior-tree/move.js";/*
1
+ export*from"./navigation.js";export*from"./navigation-areas.js";export*from"./behavior-tree/bt.js";export*from"./behavior-tree/move.js";export*from"./behavior-tree/behavior-tree.js";/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,23 @@
1
+ import { AnimationClip } from 'three';
2
+ import type { Object3D, VectorKeyframeTrack } from 'three';
3
+ import type { AnimationFootContacts } from './foot-contact.js';
4
+ export type FootContactBakeOptions = {
5
+ samplesPerSecond?: number;
6
+ /** Height above each foot's lowest sampled position, in presentation-space units. */
7
+ heightThreshold?: number;
8
+ maxVerticalSpeed?: number;
9
+ minimumContactTime?: number;
10
+ /** Restore authored root travel while sampling a fixed-in-place RootMotionClip. */
11
+ rootMotionTrack?: VectorKeyframeTrack;
12
+ };
13
+ /** Clip preprocessing: uses an isolated rig, never seeks the live character mixer. */
14
+ export declare class FootContactBaker {
15
+ private readonly root;
16
+ private readonly left;
17
+ private readonly right;
18
+ private readonly mixer;
19
+ private readonly point;
20
+ constructor(root: Object3D, leftFootName: string, rightFootName: string);
21
+ bake(clip: AnimationClip, options?: FootContactBakeOptions): AnimationFootContacts | undefined;
22
+ }
23
+ //# sourceMappingURL=foot-contact-baker.d.ts.map