@zylem/game-lib 0.6.3 → 0.6.4
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.
- package/dist/actions.d.ts +5 -5
- package/dist/actions.js +196 -32
- package/dist/actions.js.map +1 -1
- package/dist/behavior/jumper-2d.d.ts +114 -0
- package/dist/behavior/jumper-2d.js +711 -0
- package/dist/behavior/jumper-2d.js.map +1 -0
- package/dist/behavior/platformer-3d.d.ts +14 -14
- package/dist/behavior/platformer-3d.js +347 -104
- package/dist/behavior/platformer-3d.js.map +1 -1
- package/dist/behavior/ricochet-2d.d.ts +4 -3
- package/dist/behavior/ricochet-2d.js +53 -22
- package/dist/behavior/ricochet-2d.js.map +1 -1
- package/dist/behavior/ricochet-3d.d.ts +117 -0
- package/dist/behavior/ricochet-3d.js +443 -0
- package/dist/behavior/ricochet-3d.js.map +1 -0
- package/dist/behavior/screen-visibility.d.ts +79 -0
- package/dist/behavior/screen-visibility.js +358 -0
- package/dist/behavior/screen-visibility.js.map +1 -0
- package/dist/behavior/screen-wrap.d.ts +4 -3
- package/dist/behavior/screen-wrap.js +100 -49
- package/dist/behavior/screen-wrap.js.map +1 -1
- package/dist/behavior/shooter-2d.d.ts +79 -0
- package/dist/behavior/shooter-2d.js +180 -0
- package/dist/behavior/shooter-2d.js.map +1 -0
- package/dist/behavior/thruster.d.ts +5 -4
- package/dist/behavior/thruster.js +133 -75
- package/dist/behavior/thruster.js.map +1 -1
- package/dist/behavior/top-down-movement.d.ts +56 -0
- package/dist/behavior/top-down-movement.js +125 -0
- package/dist/behavior/top-down-movement.js.map +1 -0
- package/dist/behavior/world-boundary-2d.d.ts +4 -3
- package/dist/behavior/world-boundary-2d.js +90 -36
- package/dist/behavior/world-boundary-2d.js.map +1 -1
- package/dist/behavior/world-boundary-3d.d.ts +76 -0
- package/dist/behavior/world-boundary-3d.js +274 -0
- package/dist/behavior/world-boundary-3d.js.map +1 -0
- package/dist/{behavior-descriptor-BWNWmIjv.d.ts → behavior-descriptor-BXnVR8Ki.d.ts} +22 -5
- package/dist/{blueprints-BWGz8fII.d.ts → blueprints-DmbK2dki.d.ts} +2 -2
- package/dist/camera-4XO5gbQH.d.ts +905 -0
- package/dist/camera.d.ts +1 -1
- package/dist/camera.js +876 -289
- package/dist/camera.js.map +1 -1
- package/dist/{composition-DrzFrbqI.d.ts → composition-BASvMKrW.d.ts} +1 -1
- package/dist/{core-DAkskq6Y.d.ts → core-CARRaS55.d.ts} +57 -14
- package/dist/core.d.ts +9 -8
- package/dist/core.js +4519 -1255
- package/dist/core.js.map +1 -1
- package/dist/{entities-DC9ce_vx.d.ts → entities-ChFirVL9.d.ts} +22 -28
- package/dist/entities.d.ts +4 -4
- package/dist/entities.js +1231 -314
- package/dist/entities.js.map +1 -1
- package/dist/{entity-BpbZqg19.d.ts → entity-vj-HTjzU.d.ts} +80 -11
- package/dist/{global-change-Dc8uCKi2.d.ts → global-change-2JvMaz44.d.ts} +1 -1
- package/dist/main.d.ts +718 -19
- package/dist/main.js +12129 -5959
- package/dist/main.js.map +1 -1
- package/dist/physics-pose-DCc4oE44.d.ts +25 -0
- package/dist/physics-protocol-BDD3P5W2.d.ts +200 -0
- package/dist/physics-worker.d.ts +21 -0
- package/dist/physics-worker.js +306 -0
- package/dist/physics-worker.js.map +1 -0
- package/dist/physics.d.ts +205 -0
- package/dist/physics.js +577 -0
- package/dist/physics.js.map +1 -0
- package/dist/{stage-types-BFsm3qsZ.d.ts → stage-types-C19IhuzA.d.ts} +253 -89
- package/dist/stage.d.ts +9 -8
- package/dist/stage.js +3782 -1041
- package/dist/stage.js.map +1 -1
- package/dist/sync-state-machine-CZyspBpj.d.ts +16 -0
- package/dist/{thruster-DhRaJnoL.d.ts → thruster-23lzoPZd.d.ts} +16 -8
- package/dist/world-DfgxoNMt.d.ts +105 -0
- package/package.json +25 -1
- package/dist/camera-B5e4c78l.d.ts +0 -468
- package/dist/world-Be5m1XC1.d.ts +0 -31
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/behaviors/jumper-2d/components.ts","../../src/lib/behaviors/jumper-2d/jumper-2d.behavior.ts","../../src/lib/core/utility/sync-state-machine.ts","../../src/lib/behaviors/jumper-2d/jumper-2d-fsm.ts","../../src/lib/behaviors/behavior-descriptor.ts","../../src/lib/actions/capabilities/velocity-intents.ts","../../src/lib/behaviors/shared/ground-probe-3d.ts","../../src/lib/physics/serialize-descriptors.ts","../../src/lib/behaviors/jumper-2d/jumper-2d.descriptor.ts"],"sourcesContent":["export interface JumpConfig2D {\n\tjumpHeight: number;\n\tgravity: number;\n\tmaxFallSpeed?: number;\n\tmaxJumps: number;\n\tresetJumpsOnGround: boolean;\n\tcoyoteTimeMs: number;\n\tjumpBufferMs: number;\n\tminTimeBetweenJumpsMs?: number;\n\tvariableJump?: {\n\t\tenabled: boolean;\n\t\tcutGravityMultiplier: number;\n\t\tmaxHoldMs?: number;\n\t};\n}\n\nexport function createJumpConfig2D(\n\toptions: Partial<JumpConfig2D> = {},\n): JumpConfig2D {\n\treturn {\n\t\tjumpHeight: options.jumpHeight ?? 2.5,\n\t\tgravity: options.gravity ?? 20,\n\t\tmaxFallSpeed: options.maxFallSpeed,\n\t\tmaxJumps: options.maxJumps ?? 1,\n\t\tresetJumpsOnGround: options.resetJumpsOnGround ?? true,\n\t\tcoyoteTimeMs: options.coyoteTimeMs ?? 100,\n\t\tjumpBufferMs: options.jumpBufferMs ?? 80,\n\t\tminTimeBetweenJumpsMs: options.minTimeBetweenJumpsMs,\n\t\tvariableJump: options.variableJump,\n\t};\n}\n\nexport interface JumpInput2D {\n\tjumpPressed: boolean;\n\tjumpHeld: boolean;\n\tjumpReleased: boolean;\n\tfastFall?: boolean;\n}\n\nexport function createJumpInput2D(): JumpInput2D {\n\treturn {\n\t\tjumpPressed: false,\n\t\tjumpHeld: false,\n\t\tjumpReleased: false,\n\t\tfastFall: false,\n\t};\n}\n\nexport interface JumpContext2D {\n\tdt: number;\n\tvelocityY: number;\n\tisGrounded: boolean;\n\ttimeSinceGroundedMs: number;\n\tsetVerticalVelocity(y: number): void;\n}\n\nexport interface JumpState2D {\n\tjumpsUsed: number;\n\tlastJumpTimeMs: number;\n\tbufferedJumpMs: number;\n\tcoyoteMs: number;\n\tisJumping: boolean;\n\tjumpHoldMs: number;\n\tjumpCutApplied: boolean;\n}\n\nexport function createJumpState2D(): JumpState2D {\n\treturn {\n\t\tjumpsUsed: 0,\n\t\tlastJumpTimeMs: 0,\n\t\tbufferedJumpMs: 0,\n\t\tcoyoteMs: 0,\n\t\tisJumping: false,\n\t\tjumpHoldMs: 0,\n\t\tjumpCutApplied: false,\n\t};\n}\n","import type {\n\tJumpConfig2D,\n\tJumpContext2D,\n\tJumpInput2D,\n\tJumpState2D,\n} from './components';\n\nfunction jumpVelocityFromHeight(gravity: number, height: number): number {\n\treturn Math.sqrt(2 * gravity * height);\n}\n\nexport enum Jumper2DTickEvent {\n\tNone = 'none',\n\tJump = 'jump',\n\tFall = 'fall',\n\tLand = 'land',\n}\n\nexport interface Jumper2DTickResult {\n\tevent: Jumper2DTickEvent;\n}\n\nexport class Jumper2DBehavior {\n\ttick(\n\t\tconfig: JumpConfig2D,\n\t\tinput: JumpInput2D,\n\t\tctx: JumpContext2D,\n\t\tstate: JumpState2D,\n\t): Jumper2DTickResult {\n\t\tconst dtMs = ctx.dt * 1000;\n\t\tconst now = performance.now();\n\t\tlet event = Jumper2DTickEvent.None;\n\t\tlet jumpedThisFrame = false;\n\n\t\tif (ctx.isGrounded) {\n\t\t\tstate.coyoteMs = config.coyoteTimeMs;\n\t\t\tif (config.resetJumpsOnGround) {\n\t\t\t\tstate.jumpsUsed = 0;\n\t\t\t}\n\t\t\tif (state.isJumping) {\n\t\t\t\tstate.isJumping = false;\n\t\t\t\tstate.jumpCutApplied = false;\n\t\t\t\tevent = Jumper2DTickEvent.Land;\n\t\t\t}\n\t\t} else {\n\t\t\tstate.coyoteMs = Math.max(0, state.coyoteMs - dtMs);\n\t\t}\n\n\t\tif (input.jumpPressed) {\n\t\t\tstate.bufferedJumpMs = config.jumpBufferMs;\n\t\t} else {\n\t\t\tstate.bufferedJumpMs = Math.max(0, state.bufferedJumpMs - dtMs);\n\t\t}\n\n\t\tif (state.isJumping && input.jumpHeld) {\n\t\t\tstate.jumpHoldMs += dtMs;\n\t\t}\n\n\t\tconst wantsJump = state.bufferedJumpMs > 0;\n\t\tconst isFirstJump =\n\t\t\tctx.isGrounded || (state.coyoteMs > 0 && state.jumpsUsed === 0);\n\t\tconst hasAirJumps = state.jumpsUsed > 0 && state.jumpsUsed < config.maxJumps;\n\t\tconst canJump = isFirstJump || hasAirJumps;\n\t\tconst cooldownOk =\n\t\t\tconfig.minTimeBetweenJumpsMs == null ||\n\t\t\tnow - state.lastJumpTimeMs >= config.minTimeBetweenJumpsMs;\n\n\t\tif (wantsJump && canJump && cooldownOk) {\n\t\t\tctx.setVerticalVelocity(jumpVelocityFromHeight(config.gravity, config.jumpHeight));\n\t\t\tjumpedThisFrame = true;\n\t\t\tstate.jumpsUsed++;\n\t\t\tstate.lastJumpTimeMs = now;\n\t\t\tstate.bufferedJumpMs = 0;\n\t\t\tstate.coyoteMs = 0;\n\t\t\tstate.isJumping = true;\n\t\t\tstate.jumpHoldMs = 0;\n\t\t\tstate.jumpCutApplied = false;\n\t\t\tevent = Jumper2DTickEvent.Jump;\n\t\t}\n\n\t\tif (!ctx.isGrounded || jumpedThisFrame) {\n\t\t\tlet gravityMul = 1;\n\t\t\tconst isFalling = ctx.velocityY < 0;\n\n\t\t\tif (isFalling) {\n\t\t\t\tgravityMul = input.fastFall ? 1.75 : 1;\n\t\t\t\tif (event !== Jumper2DTickEvent.Land) {\n\t\t\t\t\tevent = Jumper2DTickEvent.Fall;\n\t\t\t\t}\n\t\t\t} else if (state.isJumping) {\n\t\t\t\tconst variableJump = config.variableJump;\n\t\t\t\tif (variableJump?.enabled && !state.jumpCutApplied) {\n\t\t\t\t\tconst holdExpired =\n\t\t\t\t\t\tvariableJump.maxHoldMs != null &&\n\t\t\t\t\t\tstate.jumpHoldMs >= variableJump.maxHoldMs;\n\t\t\t\t\tif (!input.jumpHeld || holdExpired) {\n\t\t\t\t\t\tgravityMul = variableJump.cutGravityMultiplier;\n\t\t\t\t\t\tstate.jumpCutApplied = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet newVelocityY = ctx.velocityY - config.gravity * gravityMul * ctx.dt;\n\t\t\tif (config.maxFallSpeed != null) {\n\t\t\t\tnewVelocityY = Math.max(-config.maxFallSpeed, newVelocityY);\n\t\t\t}\n\t\t\tctx.setVerticalVelocity(newVelocityY);\n\t\t} else {\n\t\t\tctx.setVerticalVelocity(0);\n\t\t}\n\n\t\treturn { event };\n\t}\n}\n","import {\n\tStateMachine as BaseStateMachine,\n\ttype ILogger,\n\ttype ITransition,\n\ttype SyncCallback,\n} from 'typescript-fsm';\n\nexport { t } from 'typescript-fsm';\nexport type { ILogger, ITransition, SyncCallback };\n\n/**\n * Local wrapper around typescript-fsm's SyncStateMachine.\n *\n * typescript-fsm@1.6.0 incorrectly reports callback-less transitions as\n * unhandled even after moving to the next state, which causes noisy\n * `No transition...` console errors for valid FSM dispatches.\n */\nexport class SyncStateMachine<\n\tSTATE extends string | number | symbol,\n\tEVENT extends string | number | symbol,\n\tCALLBACK extends Record<EVENT, SyncCallback> = Record<EVENT, SyncCallback>,\n> extends BaseStateMachine<STATE, EVENT, CALLBACK> {\n\tconstructor(\n\t\tinit: STATE,\n\t\ttransitions: ITransition<STATE, EVENT, CALLBACK[EVENT]>[] = [],\n\t\tlogger: ILogger = console,\n\t) {\n\t\tsuper(init, transitions, logger);\n\t}\n\n\tdispatch<E extends EVENT>(_event: E, ..._args: unknown[]): Promise<void> {\n\t\tthrow new Error('SyncStateMachine does not support async dispatch.');\n\t}\n\n\tsyncDispatch<E extends EVENT>(event: E, ...args: unknown[]): boolean {\n\t\tconst found = this.transitions.some((transition) => {\n\t\t\tif (transition.fromState !== this._current || transition.event !== event) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst current = this._current;\n\t\t\tthis._current = transition.toState;\n\n\t\t\tif (!transition.cb) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\ttransition.cb(...args);\n\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\tthis._current = current;\n\t\t\t\tthis.logger.error('Exception in callback', error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t});\n\n\t\tif (!found) {\n\t\t\tconst errorMessage = this.formatErr(this._current, event);\n\t\t\tthis.logger.error(errorMessage);\n\t\t}\n\n\t\treturn found;\n\t}\n}\n","import { SyncStateMachine, t } from '../../core/utility/sync-state-machine';\nimport type { JumpState2D } from './components';\n\nexport enum Jumper2DState {\n\tGrounded = 'grounded',\n\tJumping = 'jumping',\n\tFalling = 'falling',\n}\n\nexport enum Jumper2DEvent {\n\tJump = 'jump',\n\tFall = 'fall',\n\tLand = 'land',\n}\n\nexport interface Jumper2DFSMContext {\n\tstate: JumpState2D;\n}\n\nexport class Jumper2DFSM {\n\tmachine: SyncStateMachine<Jumper2DState, Jumper2DEvent, never>;\n\n\tconstructor(private ctx: Jumper2DFSMContext) {\n\t\tthis.machine = new SyncStateMachine<Jumper2DState, Jumper2DEvent, never>(\n\t\t\tJumper2DState.Grounded,\n\t\t\t[\n\t\t\t\tt(Jumper2DState.Grounded, Jumper2DEvent.Jump, Jumper2DState.Jumping),\n\t\t\t\tt(Jumper2DState.Grounded, Jumper2DEvent.Fall, Jumper2DState.Falling),\n\t\t\t\tt(Jumper2DState.Grounded, Jumper2DEvent.Land, Jumper2DState.Grounded),\n\t\t\t\tt(Jumper2DState.Jumping, Jumper2DEvent.Fall, Jumper2DState.Falling),\n\t\t\t\tt(Jumper2DState.Jumping, Jumper2DEvent.Land, Jumper2DState.Grounded),\n\t\t\t\tt(Jumper2DState.Jumping, Jumper2DEvent.Jump, Jumper2DState.Jumping),\n\t\t\t\tt(Jumper2DState.Falling, Jumper2DEvent.Land, Jumper2DState.Grounded),\n\t\t\t\tt(Jumper2DState.Falling, Jumper2DEvent.Jump, Jumper2DState.Jumping),\n\t\t\t\tt(Jumper2DState.Falling, Jumper2DEvent.Fall, Jumper2DState.Falling),\n\t\t\t],\n\t\t);\n\t}\n\n\tgetState(): Jumper2DState {\n\t\treturn this.machine.getState();\n\t}\n\n\tdispatch(event: Jumper2DEvent): void {\n\t\tif (this.machine.can(event)) {\n\t\t\tthis.machine.syncDispatch(event);\n\t\t}\n\t}\n\n\tisJumping(): boolean {\n\t\treturn this.getState() === Jumper2DState.Jumping;\n\t}\n\n\tisGrounded(): boolean {\n\t\treturn this.getState() === Jumper2DState.Grounded;\n\t}\n\n\tgetJumpsUsed(): number {\n\t\treturn this.ctx.state.jumpsUsed;\n\t}\n\n\tapplyTickEvent(tickEvent: string, isGrounded: boolean): void {\n\t\tswitch (tickEvent) {\n\t\t\tcase 'jump':\n\t\t\t\tthis.dispatch(Jumper2DEvent.Jump);\n\t\t\t\tbreak;\n\t\t\tcase 'fall':\n\t\t\t\tthis.dispatch(Jumper2DEvent.Fall);\n\t\t\t\tbreak;\n\t\t\tcase 'land':\n\t\t\t\tthis.dispatch(Jumper2DEvent.Land);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (!isGrounded && this.getState() === Jumper2DState.Grounded) {\n\t\t\t\t\tthis.dispatch(Jumper2DEvent.Fall);\n\t\t\t\t}\n\t\t\t\tif (isGrounded && this.getState() !== Jumper2DState.Grounded) {\n\t\t\t\t\tthis.dispatch(Jumper2DEvent.Land);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n","/**\n * BehaviorDescriptor\n *\n * Type-safe behavior descriptors that provide options inference.\n * Used with entity.use() to declaratively attach behaviors to entities.\n *\n * Each behavior can define its own handle type via `createHandle`,\n * providing behavior-specific methods with full type safety.\n */\n\nimport type { BehaviorSystemFactory } from './behavior-system';\n\n/**\n * Base handle returned by entity.use() for lazy access to behavior runtime.\n * FSM is null until entity is spawned and components are initialized.\n */\nexport interface BaseBehaviorHandle<\n O extends Record<string, any> = Record<string, any>,\n> {\n /** Get the FSM instance (null until entity is spawned) */\n getFSM(): any | null;\n /** Get the current options */\n getOptions(): O;\n /** Access the underlying behavior ref */\n readonly ref: BehaviorRef<O>;\n}\n\n/**\n * Reference to a behavior stored on an entity\n */\nexport interface BehaviorRef<\n O extends Record<string, any> = Record<string, any>,\n> {\n /** The behavior descriptor */\n descriptor: BehaviorDescriptor<O, any>;\n /** Merged options (defaults + overrides) */\n options: O;\n /** Optional FSM instance - set lazily when entity is spawned */\n fsm?: any;\n}\n\n/**\n * A typed behavior descriptor that associates a symbol key with:\n * - Default options (providing type inference)\n * - A system factory to create the behavior system\n * - An optional handle factory for behavior-specific methods\n */\nexport interface BehaviorDescriptor<\n O extends Record<string, any> = Record<string, any>,\n H extends Record<string, any> = Record<string, never>,\n I = unknown,\n> {\n /** Unique symbol identifying this behavior */\n readonly key: symbol;\n /** Default options (used for type inference) */\n readonly defaultOptions: O;\n /** Factory to create the behavior system */\n readonly systemFactory: BehaviorSystemFactory;\n /**\n * Optional factory to create behavior-specific handle methods.\n * These methods are merged into the handle returned by entity.use().\n */\n readonly createHandle?: (ref: BehaviorRef<O>) => H;\n}\n\n/**\n * The full handle type returned by entity.use().\n * Combines base handle with behavior-specific methods.\n */\nexport type BehaviorHandle<\n O extends Record<string, any> = Record<string, any>,\n H extends Record<string, any> = Record<string, never>,\n> = BaseBehaviorHandle<O> & H;\n\n/**\n * Configuration for defining a new behavior\n */\nexport interface DefineBehaviorConfig<\n O extends Record<string, any>,\n H extends Record<string, any> = Record<string, never>,\n I = unknown,\n> {\n /** Human-readable name for debugging */\n name: string;\n /** Default options - these define the type */\n defaultOptions: O;\n /** Factory function to create the system */\n systemFactory: BehaviorSystemFactory;\n /**\n * Optional factory to create behavior-specific handle methods.\n * The returned object is merged into the handle returned by entity.use().\n *\n * @example\n * ```typescript\n * createHandle: (ref) => ({\n * getLastHits: () => ref.fsm?.getLastHits() ?? null,\n * getMovement: (moveX, moveY) => ref.fsm?.getMovement(moveX, moveY) ?? { moveX, moveY },\n * }),\n * ```\n */\n createHandle?: (ref: BehaviorRef<O>) => H;\n}\n\n/**\n * Define a typed behavior descriptor.\n *\n * @example\n * ```typescript\n * export const WorldBoundary2DBehavior = defineBehavior({\n * name: 'world-boundary-2d',\n * defaultOptions: { boundaries: { top: 0, bottom: 0, left: 0, right: 0 } },\n * systemFactory: (ctx) => new WorldBoundary2DSystem(ctx.world),\n * createHandle: (ref) => ({\n * getLastHits: () => ref.fsm?.getLastHits() ?? null,\n * getMovement: (moveX: number, moveY: number) =>\n * ref.fsm?.getMovement(moveX, moveY) ?? { moveX, moveY },\n * }),\n * });\n *\n * // Usage - handle has getLastHits and getMovement with full types\n * const boundary = ship.use(WorldBoundary2DBehavior, { ... });\n * const hits = boundary.getLastHits(); // Fully typed!\n * ```\n */\nexport function defineBehavior<\n O extends Record<string, any>,\n H extends Record<string, any> = Record<string, never>,\n I = unknown,\n>(\n config: DefineBehaviorConfig<O, H, I>,\n): BehaviorDescriptor<O, H, I> {\n return {\n key: Symbol.for(`zylem:behavior:${config.name}`),\n defaultOptions: config.defaultOptions,\n systemFactory: config.systemFactory,\n createHandle: config.createHandle,\n };\n}\n","import { TransformState, VelocityIntentMode } from './transform-store';\n\nexport interface VelocityIntentOptions {\n\tmode?: VelocityIntentMode;\n\tpriority?: number;\n}\n\nexport interface VelocityIntentVector {\n\tx?: number;\n\ty?: number;\n\tz?: number;\n}\n\nexport function setVelocityIntent(\n\tstore: TransformState,\n\tsourceId: string,\n\tvector: VelocityIntentVector,\n\toptions: VelocityIntentOptions = {},\n): void {\n\tconst prev = store.velocityChannels[sourceId];\n\tconst mode = options.mode ?? prev?.mode ?? 'replace';\n\tconst priority = options.priority ?? prev?.priority ?? 0;\n\tconst isAdditiveMerge = mode === 'add' && prev?.mode === 'add';\n\n\tconst x =\n\t\tvector.x == null\n\t\t\t? prev?.x\n\t\t\t: isAdditiveMerge\n\t\t\t\t? (prev?.x ?? 0) + vector.x\n\t\t\t\t: vector.x;\n\tconst y =\n\t\tvector.y == null\n\t\t\t? prev?.y\n\t\t\t: isAdditiveMerge\n\t\t\t\t? (prev?.y ?? 0) + vector.y\n\t\t\t\t: vector.y;\n\tconst z =\n\t\tvector.z == null\n\t\t\t? prev?.z\n\t\t\t: isAdditiveMerge\n\t\t\t\t? (prev?.z ?? 0) + vector.z\n\t\t\t\t: vector.z;\n\n\tstore.velocityChannels[sourceId] = {\n\t\tx,\n\t\ty,\n\t\tz,\n\t\tmode,\n\t\tpriority,\n\t};\n\tstore.dirty.velocityChannels = true;\n}\n\nexport function clearVelocityIntent(store: TransformState, sourceId: string): void {\n\tif (!(sourceId in store.velocityChannels)) return;\n\tdelete store.velocityChannels[sourceId];\n\tstore.dirty.velocityChannels = true;\n}\n","import { Ray } from '@dimforge/rapier3d-compat';\nimport { BufferGeometry, Line, LineBasicMaterial, Vector3 } from 'three';\nimport { serializeColliderDesc } from '../../physics/serialize-descriptors';\n\nexport interface GroundProbeOffset {\n\tx: number;\n\tz: number;\n}\n\nexport type GroundProbeMode = 'center' | 'any';\n\nexport interface GroundProbeEntity {\n\tuuid: string;\n\tbody: any;\n}\n\nexport interface GroundProbeOptions {\n\trayLength: number;\n\toffsets?: readonly GroundProbeOffset[];\n\tmode?: GroundProbeMode;\n\tdebug?: boolean;\n\tscene?: any;\n\toriginYOffset?: number;\n}\n\nexport interface GroundProbeSupportHit {\n\ttoi: number;\n\tpoint: {\n\t\tx: number;\n\t\ty: number;\n\t\tz: number;\n\t};\n\torigin: {\n\t\tx: number;\n\t\ty: number;\n\t\tz: number;\n\t};\n\trayIndex: number;\n\tcolliderUuid?: string;\n}\n\nexport const GROUND_SNAP_EPSILON = 0.001;\n\nconst DEFAULT_OFFSETS: readonly GroundProbeOffset[] = [\n\t{ x: 0, z: 0 },\n\t{ x: 0.4, z: 0.4 },\n\t{ x: -0.4, z: 0.4 },\n\t{ x: 0.4, z: -0.4 },\n\t{ x: -0.4, z: -0.4 },\n] as const;\n\nexport class GroundProbe3D {\n\tprivate rays = new Map<string, Ray[]>();\n\tprivate debugLines = new Map<string, Line[]>();\n\n\tconstructor(private world: any) {}\n\n\tprobeSupport(\n\t\tentity: GroundProbeEntity,\n\t\toptions: GroundProbeOptions,\n\t): GroundProbeSupportHit | null {\n\t\tif (!this.world?.world || !entity.body) return null;\n\n\t\tconst mode = options.mode ?? 'any';\n\t\tconst offsets =\n\t\t\tmode === 'center'\n\t\t\t\t? (options.offsets ?? DEFAULT_OFFSETS).slice(0, 1)\n\t\t\t\t: (options.offsets ?? DEFAULT_OFFSETS);\n\t\tconst translation = entity.body.translation();\n\t\tconst rays = this.getOrCreateRays(entity.uuid, offsets.length);\n\t\tconst originYOffset = options.originYOffset ?? 0;\n\t\tlet support: GroundProbeSupportHit | null = null;\n\n\t\tfor (let index = 0; index < offsets.length; index++) {\n\t\t\tconst offset = offsets[index];\n\t\t\tconst ray = rays[index];\n\n\t\t\tray.origin = {\n\t\t\t\tx: translation.x + offset.x,\n\t\t\t\ty: translation.y + originYOffset,\n\t\t\t\tz: translation.z + offset.z,\n\t\t\t};\n\t\t\tray.dir = { x: 0, y: -1, z: 0 };\n\n\t\t\tconst hit = this.world.world.castRay(\n\t\t\t\tray,\n\t\t\t\toptions.rayLength,\n\t\t\t\ttrue,\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\tentity.body,\n\t\t\t);\n\t\t\tif (!hit) continue;\n\n\t\t\tconst nextSupport: GroundProbeSupportHit = {\n\t\t\t\ttoi: hit.toi,\n\t\t\t\tpoint: {\n\t\t\t\t\tx: ray.origin.x + ray.dir.x * hit.toi,\n\t\t\t\t\ty: ray.origin.y + ray.dir.y * hit.toi,\n\t\t\t\t\tz: ray.origin.z + ray.dir.z * hit.toi,\n\t\t\t\t},\n\t\t\t\torigin: {\n\t\t\t\t\tx: ray.origin.x,\n\t\t\t\t\ty: ray.origin.y,\n\t\t\t\t\tz: ray.origin.z,\n\t\t\t\t},\n\t\t\t\trayIndex: index,\n\t\t\t\tcolliderUuid: hit.collider?._parent?.userData?.uuid,\n\t\t\t};\n\n\t\t\tif (mode === 'center') {\n\t\t\t\tsupport = nextSupport;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (!support || nextSupport.toi < support.toi) {\n\t\t\t\tsupport = nextSupport;\n\t\t\t}\n\t\t}\n\n\t\tif (options.debug && options.scene) {\n\t\t\tthis.updateDebugLines(\n\t\t\t\tentity.uuid,\n\t\t\t\trays,\n\t\t\t\tBoolean(support),\n\t\t\t\toptions.rayLength,\n\t\t\t\toptions.scene,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.disposeDebugLines(entity.uuid);\n\t\t}\n\n\t\treturn support;\n\t}\n\n\tdetect(entity: GroundProbeEntity, options: GroundProbeOptions): boolean {\n\t\treturn this.probeSupport(entity, options) != null;\n\t}\n\n\tdestroyEntity(uuid: string): void {\n\t\tthis.rays.delete(uuid);\n\t\tthis.disposeDebugLines(uuid);\n\t}\n\n\tdestroy(): void {\n\t\tthis.rays.clear();\n\t\tfor (const uuid of this.debugLines.keys()) {\n\t\t\tthis.disposeDebugLines(uuid);\n\t\t}\n\t\tthis.debugLines.clear();\n\t}\n\n\tprivate getOrCreateRays(uuid: string, count: number): Ray[] {\n\t\tlet rays = this.rays.get(uuid);\n\t\tif (!rays || rays.length !== count) {\n\t\t\trays = Array.from(\n\t\t\t\t{ length: count },\n\t\t\t\t() => new Ray({ x: 0, y: 0, z: 0 }, { x: 0, y: -1, z: 0 }),\n\t\t\t);\n\t\t\tthis.rays.set(uuid, rays);\n\t\t}\n\t\treturn rays;\n\t}\n\n\tprivate updateDebugLines(\n\t\tuuid: string,\n\t\trays: Ray[],\n\t\thasGround: boolean,\n\t\tlength: number,\n\t\tscene: any,\n\t): void {\n\t\tlet lines = this.debugLines.get(uuid);\n\t\tif (!lines) {\n\t\t\tlines = rays.map(() => {\n\t\t\t\tconst geometry = new BufferGeometry().setFromPoints([\n\t\t\t\t\tnew Vector3(),\n\t\t\t\t\tnew Vector3(),\n\t\t\t\t]);\n\t\t\t\tconst material = new LineBasicMaterial({ color: 0xff0000 });\n\t\t\t\tconst line = new Line(geometry, material);\n\t\t\t\tscene.add(line);\n\t\t\t\treturn line;\n\t\t\t});\n\t\t\tthis.debugLines.set(uuid, lines);\n\t\t}\n\n\t\trays.forEach((ray, index) => {\n\t\t\tconst line = lines![index];\n\t\t\tconst start = new Vector3(ray.origin.x, ray.origin.y, ray.origin.z);\n\t\t\tconst end = new Vector3(\n\t\t\t\tray.origin.x + ray.dir.x * length,\n\t\t\t\tray.origin.y + ray.dir.y * length,\n\t\t\t\tray.origin.z + ray.dir.z * length,\n\t\t\t);\n\t\t\tline.visible = true;\n\t\t\tline.geometry.setFromPoints([start, end]);\n\t\t\t(line.material as LineBasicMaterial).color.setHex(\n\t\t\t\thasGround ? 0x00ff00 : 0xff0000,\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate disposeDebugLines(uuid: string): void {\n\t\tconst lines = this.debugLines.get(uuid);\n\t\tif (!lines) return;\n\n\t\tfor (const line of lines) {\n\t\t\tline.removeFromParent();\n\t\t\tline.geometry.dispose();\n\t\t\t(line.material as LineBasicMaterial).dispose();\n\t\t}\n\n\t\tthis.debugLines.delete(uuid);\n\t}\n}\n\nexport function getGroundAnchorOffsetY(entity: any): number {\n\tconst runtimeColliderDesc = entity?.colliderDesc;\n\tif (runtimeColliderDesc) {\n\t\tconst serialized = serializeColliderDesc(runtimeColliderDesc);\n\t\tconst centerY = serialized.translation?.[1] ?? 0;\n\t\tif (serialized.shape === 'capsule' && serialized.dimensions.length >= 2) {\n\t\t\tconst halfCylinder = serialized.dimensions[0] ?? 0;\n\t\t\tconst radius = serialized.dimensions[1] ?? 0;\n\t\t\treturn halfCylinder + radius - centerY;\n\t\t}\n\t\tif (serialized.shape === 'cuboid' && serialized.dimensions.length >= 2) {\n\t\t\tconst halfHeight = serialized.dimensions[1] ?? 0;\n\t\t\treturn halfHeight - centerY;\n\t\t}\n\t}\n\n\tconst collisionSize =\n\t\tentity?.options?.collision?.size ??\n\t\tentity?.options?.collisionSize ??\n\t\tentity?.options?.size;\n\tconst height = collisionSize?.y ?? 0;\n\tif (height <= 0) {\n\t\treturn 0;\n\t}\n\n\tconst collisionPosition =\n\t\tentity?.options?.collision?.position ??\n\t\tentity?.options?.collisionPosition;\n\tconst centerY = collisionPosition?.y ?? height / 2;\n\treturn (height / 2) - centerY;\n}\n\nexport function getGroundSnapTargetY(\n\tentity: any,\n\tsupport: GroundProbeSupportHit,\n\tepsilon: number = GROUND_SNAP_EPSILON,\n): number {\n\treturn support.point.y + getGroundAnchorOffsetY(entity) + epsilon;\n}\n","import type { RigidBodyDesc, ColliderDesc } from '@dimforge/rapier3d-compat';\nimport { RigidBodyType } from '@dimforge/rapier3d-compat';\nimport type {\n\tSerializableBodyDesc,\n\tSerializableBodyType,\n\tSerializableColliderDesc,\n\tColliderShapeKind,\n\tSerializableCharacterController,\n} from './physics-protocol';\n\n/**\n * Convert a Rapier RigidBodyDesc to a plain serializable object.\n *\n * Rapier descriptors are WASM-backed class instances that cannot cross\n * the postMessage boundary. This extracts the relevant data into a\n * JSON-safe format that the worker can reconstruct.\n */\nexport function serializeBodyDesc(desc: RigidBodyDesc): SerializableBodyDesc {\n\tconst status = (desc as any).status as number;\n\tlet type: SerializableBodyType = 'dynamic';\n\tif (status === RigidBodyType.Fixed) type = 'fixed';\n\telse if (status === RigidBodyType.KinematicPositionBased) type = 'kinematicPositionBased';\n\telse if (status === RigidBodyType.KinematicVelocityBased) type = 'kinematicVelocityBased';\n\n\tconst t = (desc as any).translation ?? { x: 0, y: 0, z: 0 };\n\n\treturn {\n\t\ttype,\n\t\ttranslation: [t.x ?? 0, t.y ?? 0, t.z ?? 0],\n\t\tgravityScale: (desc as any).gravityScale ?? 1,\n\t\tcanSleep: (desc as any).canSleep ?? false,\n\t\tccdEnabled: (desc as any).ccdEnabled ?? true,\n\t};\n}\n\n/**\n * Convert a Rapier ColliderDesc to a plain serializable object.\n *\n * Because Rapier's ColliderDesc uses opaque shape enums and internal\n * buffers, we infer the shape from the descriptor's internal type tag\n * and extract the numeric dimensions.\n */\nexport function serializeColliderDesc(desc: ColliderDesc): SerializableColliderDesc {\n\tconst internal = desc as any;\n\tconst customShapeData = internal.__zylemShapeData as\n\t\t| { shape: 'trimesh'; vertices: number[]; indices: number[] }\n\t\t| undefined;\n\tif (customShapeData?.shape === 'trimesh') {\n\t\tconst result: SerializableColliderDesc = {\n\t\t\tshape: 'trimesh',\n\t\t\tdimensions: [],\n\t\t\tvertices: [...customShapeData.vertices],\n\t\t\tindices: [...customShapeData.indices],\n\t\t};\n\n\t\tconst translation = internal.translation;\n\t\tif (\n\t\t\ttranslation\n\t\t\t&& (translation.x !== 0 || translation.y !== 0 || translation.z !== 0)\n\t\t) {\n\t\t\tresult.translation = [translation.x, translation.y, translation.z];\n\t\t}\n\n\t\tif (internal.isSensor) {\n\t\t\tresult.sensor = true;\n\t\t}\n\n\t\tif (internal.collisionGroups !== undefined && internal.collisionGroups !== 0xFFFFFFFF) {\n\t\t\tresult.collisionGroups = internal.collisionGroups;\n\t\t}\n\n\t\tif (internal.activeCollisionTypes !== undefined) {\n\t\t\tresult.activeCollisionTypes = internal.activeCollisionTypes;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tconst shapeType = internal.shape?.type ?? internal.shapeType ?? 0;\n\n\tconst { shape, dimensions, heightfieldMeta } = extractShapeData(shapeType, internal);\n\n\tconst result: SerializableColliderDesc = {\n\t\tshape,\n\t\tdimensions,\n\t};\n\n\tconst t = internal.translation;\n\tif (t && (t.x !== 0 || t.y !== 0 || t.z !== 0)) {\n\t\tresult.translation = [t.x, t.y, t.z];\n\t}\n\n\tif (internal.isSensor) {\n\t\tresult.sensor = true;\n\t}\n\n\tif (internal.collisionGroups !== undefined && internal.collisionGroups !== 0xFFFFFFFF) {\n\t\tresult.collisionGroups = internal.collisionGroups;\n\t}\n\n\tif (internal.activeCollisionTypes !== undefined) {\n\t\tresult.activeCollisionTypes = internal.activeCollisionTypes;\n\t}\n\n\tif (heightfieldMeta) {\n\t\tresult.heightfieldMeta = heightfieldMeta;\n\t}\n\n\treturn result;\n}\n\n/**\n * Create a serializable character controller descriptor.\n */\nexport function serializeCharacterController(): SerializableCharacterController {\n\treturn {\n\t\toffset: 0.01,\n\t\tmaxSlopeClimbAngle: 45 * Math.PI / 180,\n\t\tminSlopeSlideAngle: 30 * Math.PI / 180,\n\t\tsnapToGroundDistance: 0.01,\n\t\tslideEnabled: true,\n\t\tapplyImpulsesToDynamic: true,\n\t\tcharacterMass: 1,\n\t};\n}\n\n// ─── Shape Extraction ──────────────────────────────────────────────────────\n\n/**\n * Rapier shape type enum values (from rapier internals):\n * 0 = Ball, 1 = Cuboid, 2 = Capsule, 6 = Cone, 7 = Cylinder,\n * 11 = HeightField\n */\nfunction extractShapeData(\n\tshapeType: number,\n\tinternal: any,\n): { shape: ColliderShapeKind; dimensions: number[]; heightfieldMeta?: { nrows: number; ncols: number } } {\n\tswitch (shapeType) {\n\t\tcase 0: // Ball\n\t\t\treturn {\n\t\t\t\tshape: 'ball',\n\t\t\t\tdimensions: [internal.shape?.radius ?? internal.halfExtents?.x ?? 1],\n\t\t\t};\n\t\tcase 1: // Cuboid\n\t\t\treturn {\n\t\t\t\tshape: 'cuboid',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfExtents?.x ?? internal.halfExtents?.x ?? 0.5,\n\t\t\t\t\tinternal.shape?.halfExtents?.y ?? internal.halfExtents?.y ?? 0.5,\n\t\t\t\t\tinternal.shape?.halfExtents?.z ?? internal.halfExtents?.z ?? 0.5,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 2: // Capsule\n\t\t\treturn {\n\t\t\t\tshape: 'capsule',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 0.5,\n\t\t\t\t\tinternal.shape?.radius ?? 0.5,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 6: // Cone\n\t\t\treturn {\n\t\t\t\tshape: 'cone',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 1,\n\t\t\t\t\tinternal.shape?.radius ?? 1,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 7: // Cylinder\n\t\t\treturn {\n\t\t\t\tshape: 'cylinder',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 1,\n\t\t\t\t\tinternal.shape?.radius ?? 1,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 11: { // HeightField\n\t\t\tconst nrows = internal.shape?.nrows ?? 10;\n\t\t\tconst ncols = internal.shape?.ncols ?? 10;\n\t\t\tconst heights = internal.shape?.heights;\n\t\t\treturn {\n\t\t\t\tshape: 'heightfield',\n\t\t\t\tdimensions: heights ? Array.from(heights) : [],\n\t\t\t\theightfieldMeta: { nrows, ncols },\n\t\t\t};\n\t\t}\n\t\tdefault:\n\t\t\treturn { shape: 'cuboid', dimensions: [0.5, 0.5, 0.5] };\n\t}\n}\n","import type { IWorld } from 'bitecs';\nimport { defineBehavior } from '../behavior-descriptor';\nimport type { BehaviorEntityLink, BehaviorSystem } from '../behavior-system';\nimport { setVelocityIntent } from '../../actions/capabilities/velocity-intents';\nimport {\n\tGroundProbe3D,\n\tgetGroundAnchorOffsetY,\n\tgetGroundSnapTargetY,\n\ttype GroundProbeSupportHit,\n} from '../shared/ground-probe-3d';\nimport {\n\tcreateJumpConfig2D,\n\tcreateJumpInput2D,\n\tcreateJumpState2D,\n\ttype JumpConfig2D,\n\ttype JumpContext2D,\n\ttype JumpInput2D,\n\ttype JumpState2D,\n} from './components';\nimport {\n\tJumper2DBehavior,\n\tJumper2DTickEvent,\n} from './jumper-2d.behavior';\nimport { Jumper2DFSM, Jumper2DState } from './jumper-2d-fsm';\n\nexport interface Jumper2DBehaviorOptions {\n\tjumpHeight?: number;\n\tgravity?: number;\n\tmaxFallSpeed?: number;\n\tmaxJumps?: number;\n\tresetJumpsOnGround?: boolean;\n\tcoyoteTimeMs?: number;\n\tjumpBufferMs?: number;\n\tminTimeBetweenJumpsMs?: number;\n\tvariableJump?: JumpConfig2D['variableJump'];\n\tgroundRayLength?: number;\n\tsnapToGroundDistance?: number;\n\tdebugGroundProbe?: boolean;\n}\n\nconst defaultOptions: Jumper2DBehaviorOptions = {\n\tjumpHeight: 2.5,\n\tgravity: 20,\n\tmaxJumps: 1,\n\tresetJumpsOnGround: true,\n\tcoyoteTimeMs: 100,\n\tjumpBufferMs: 80,\n\tgroundRayLength: 1,\n\tdebugGroundProbe: false,\n};\n\nconst JUMPER_2D_BEHAVIOR_KEY = Symbol.for('zylem:behavior:jumper-2d');\nconst JUMPER_2D_OFFSETS = [\n\t{ x: 0, z: 0 },\n\t{ x: 0.35, z: 0 },\n\t{ x: -0.35, z: 0 },\n] as const;\n\nexport function isJumper2DGrounded(params: {\n\tnearGround?: boolean;\n\tvelocityY: number;\n\tsupportToi?: number | null;\n\tsnapToGroundDistance?: number;\n}): boolean {\n\tif (params.velocityY > 0) {\n\t\treturn false;\n\t}\n\n\tif (params.snapToGroundDistance != null) {\n\t\treturn (\n\t\t\tparams.supportToi != null &&\n\t\t\tparams.supportToi <= params.snapToGroundDistance\n\t\t);\n\t}\n\n\treturn params.nearGround === true;\n}\n\nfunction shouldSnapJumper2DToGround(\n\tsupport: GroundProbeSupportHit | null,\n\toptions: Jumper2DBehaviorOptions,\n\tvelocityY: number,\n): support is GroundProbeSupportHit {\n\treturn (\n\t\tsupport != null &&\n\t\toptions.snapToGroundDistance != null &&\n\t\tvelocityY <= 0 &&\n\t\tsupport.toi <= options.snapToGroundDistance\n\t);\n}\n\nexport interface Jumper2DEntity {\n\tuuid: string;\n\tbody: any;\n\ttransformStore: any;\n\tjumper2d: JumpConfig2D;\n\t$jumper2d: JumpInput2D;\n\tjumper2dState: JumpState2D;\n}\n\nclass Jumper2DBehaviorSystem implements BehaviorSystem {\n\tprivate behavior = new Jumper2DBehavior();\n\tprivate groundProbe: GroundProbe3D;\n\tprivate initializedEntities = new Set<string>();\n\tprivate timeSinceGroundedMs = new Map<string, number>();\n\tprivate wasJumpHeld = new Map<string, boolean>();\n\n\tconstructor(\n\t\tprivate world: any,\n\t\tprivate scene: any,\n\t\tprivate getBehaviorLinks?: (key: symbol) => Iterable<BehaviorEntityLink>,\n\t) {\n\t\tthis.groundProbe = new GroundProbe3D(world);\n\t}\n\n\tupdate(_ecs: IWorld, delta: number): void {\n\t\tconst links = this.getBehaviorLinks?.(JUMPER_2D_BEHAVIOR_KEY);\n\t\tif (!links) return;\n\n\t\tfor (const link of links) {\n\t\t\tconst gameEntity = link.entity as any;\n\t\t\tconst jumperRef = link.ref as any;\n\t\t\tif (!gameEntity.body) continue;\n\n\t\t\tconst options = jumperRef.options as Jumper2DBehaviorOptions;\n\n\t\t\tif (!gameEntity.jumper2d) {\n\t\t\t\tgameEntity.jumper2d = createJumpConfig2D(options);\n\t\t\t}\n\t\t\tif (!gameEntity.$jumper2d) {\n\t\t\t\tgameEntity.$jumper2d = createJumpInput2D();\n\t\t\t}\n\t\t\tif (!gameEntity.jumper2dState) {\n\t\t\t\tgameEntity.jumper2dState = createJumpState2D();\n\t\t\t}\n\t\t\tif (!this.initializedEntities.has(gameEntity.uuid)) {\n\t\t\t\tthis.initializedEntities.add(gameEntity.uuid);\n\t\t\t\tgameEntity.body.setGravityScale(0, true);\n\t\t\t}\n\t\t\tif (!jumperRef.fsm && gameEntity.jumper2dState) {\n\t\t\t\tjumperRef.fsm = new Jumper2DFSM({\n\t\t\t\t\tstate: gameEntity.jumper2dState,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst rayLength = options.groundRayLength ?? 1;\n\t\t\tconst bodyVelocity = gameEntity.body.linvel();\n\t\t\tconst probeOriginYOffset = 0.05 - getGroundAnchorOffsetY(gameEntity);\n\t\t\tconst support = this.groundProbe.probeSupport(gameEntity, {\n\t\t\t\trayLength,\n\t\t\t\toffsets: JUMPER_2D_OFFSETS,\n\t\t\t\tmode: 'any',\n\t\t\t\tdebug: options.debugGroundProbe ?? false,\n\t\t\t\tscene: this.scene,\n\t\t\t\toriginYOffset: probeOriginYOffset,\n\t\t\t});\n\t\t\tconst nearGround = support != null;\n\t\t\tconst isGrounded = isJumper2DGrounded({\n\t\t\t\tnearGround,\n\t\t\t\tvelocityY: bodyVelocity.y,\n\t\t\t\tsupportToi: support?.toi ?? null,\n\t\t\t\tsnapToGroundDistance: options.snapToGroundDistance,\n\t\t\t});\n\t\t\tif (shouldSnapJumper2DToGround(support, options, bodyVelocity.y)) {\n\t\t\t\tconst currentPosition = gameEntity.body.translation();\n\t\t\t\tgameEntity.body.setTranslation(\n\t\t\t\t\t{\n\t\t\t\t\t\tx: currentPosition.x,\n\t\t\t\t\t\ty: getGroundSnapTargetY(gameEntity, support),\n\t\t\t\t\t\tz: currentPosition.z,\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet timeSinceGroundedMs = this.timeSinceGroundedMs.get(gameEntity.uuid) ?? 0;\n\t\t\tif (isGrounded) {\n\t\t\t\ttimeSinceGroundedMs = 0;\n\t\t\t} else {\n\t\t\t\ttimeSinceGroundedMs += delta * 1000;\n\t\t\t}\n\t\t\tthis.timeSinceGroundedMs.set(gameEntity.uuid, timeSinceGroundedMs);\n\n\t\t\tconst config: JumpConfig2D = gameEntity.jumper2d;\n\t\t\tconst input: JumpInput2D = gameEntity.$jumper2d;\n\t\t\tconst state: JumpState2D = gameEntity.jumper2dState;\n\t\t\tconst previousHeld = this.wasJumpHeld.get(gameEntity.uuid) ?? false;\n\t\t\tconst held = input.jumpHeld === true;\n\t\t\tconst effectiveInput: JumpInput2D = {\n\t\t\t\t...input,\n\t\t\t\tjumpPressed: input.jumpPressed || (held && !previousHeld),\n\t\t\t\tjumpReleased: input.jumpReleased || (!held && previousHeld),\n\t\t\t};\n\n\t\t\tconst store = gameEntity.transformStore;\n\t\t\tconst ctx: JumpContext2D = {\n\t\t\t\tdt: delta,\n\t\t\t\tvelocityY: bodyVelocity.y,\n\t\t\t\tisGrounded,\n\t\t\t\ttimeSinceGroundedMs,\n\t\t\t\tsetVerticalVelocity: (y: number) => {\n\t\t\t\t\tsetVelocityIntent(\n\t\t\t\t\t\tstore,\n\t\t\t\t\t\t'jumper-2d',\n\t\t\t\t\t\t{ y },\n\t\t\t\t\t\t{ mode: 'replace', priority: 20 },\n\t\t\t\t\t);\n\t\t\t\t\tctx.velocityY = y;\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst result = this.behavior.tick(config, effectiveInput, ctx, state);\n\t\t\tthis.wasJumpHeld.set(gameEntity.uuid, held);\n\n\t\t\tif (jumperRef.fsm) {\n\t\t\t\t(jumperRef.fsm as Jumper2DFSM).applyTickEvent(result.event, isGrounded);\n\t\t\t}\n\t\t}\n\t}\n\n\tdestroy(_ecs: IWorld): void {\n\t\tthis.groundProbe.destroy();\n\t\tthis.initializedEntities.clear();\n\t\tthis.timeSinceGroundedMs.clear();\n\t\tthis.wasJumpHeld.clear();\n\t}\n}\n\nexport const Jumper2D = defineBehavior<\n\tJumper2DBehaviorOptions,\n\t{\n\t\tgetState: () => Jumper2DState;\n\t\tisJumping: () => boolean;\n\t\tgetJumpsUsed: () => number;\n\t\tgetJumpsRemaining: () => number;\n\t},\n\tJumper2DEntity\n>({\n\tname: 'jumper-2d',\n\tdefaultOptions,\n\tsystemFactory: (ctx) =>\n\t\tnew Jumper2DBehaviorSystem(ctx.world, ctx.scene, ctx.getBehaviorLinks),\n\tcreateHandle: (ref) => ({\n\t\tgetState: () =>\n\t\t\t(ref.fsm as Jumper2DFSM | undefined)?.getState() ??\n\t\t\tJumper2DState.Grounded,\n\t\tisJumping: () =>\n\t\t\t(ref.fsm as Jumper2DFSM | undefined)?.isJumping() ?? false,\n\t\tgetJumpsUsed: () =>\n\t\t\t(ref.fsm as Jumper2DFSM | undefined)?.getJumpsUsed() ?? 0,\n\t\tgetJumpsRemaining: () => {\n\t\t\tconst maxJumps = ref.options.maxJumps ?? 1;\n\t\t\tconst used =\n\t\t\t\t(ref.fsm as Jumper2DFSM | undefined)?.getJumpsUsed() ?? 0;\n\t\t\treturn maxJumps - used;\n\t\t},\n\t}),\n});\n"],"mappings":"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","names":["Jumper2DTickEvent","Jumper2DState","Jumper2DEvent","result","t","centerY"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { S as SyncStateMachine } from '../sync-state-machine-CZyspBpj.js';
|
|
2
|
+
import { c as BehaviorDescriptor } from '../behavior-descriptor-BXnVR8Ki.js';
|
|
3
|
+
import 'typescript-fsm';
|
|
3
4
|
import 'bitecs';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -29,6 +30,8 @@ interface Platformer3DMovementComponent {
|
|
|
29
30
|
jumpCutMultiplier: number;
|
|
30
31
|
/** Time in seconds before multi-jump becomes available (0 = after button release) */
|
|
31
32
|
multiJumpWindowTime: number;
|
|
33
|
+
/** Enable ground-ray debug visualization */
|
|
34
|
+
debugGroundProbe: boolean;
|
|
32
35
|
}
|
|
33
36
|
declare function createPlatformer3DMovementComponent(options?: Partial<Platformer3DMovementComponent>): Platformer3DMovementComponent;
|
|
34
37
|
interface Platformer3DInputComponent {
|
|
@@ -138,7 +141,7 @@ interface Platformer3DContext {
|
|
|
138
141
|
*/
|
|
139
142
|
declare class Platformer3DFSM {
|
|
140
143
|
private ctx;
|
|
141
|
-
machine:
|
|
144
|
+
machine: SyncStateMachine<Platformer3DState, Platformer3DEvent, never>;
|
|
142
145
|
constructor(ctx: Platformer3DContext);
|
|
143
146
|
/**
|
|
144
147
|
* Get the current state
|
|
@@ -196,17 +199,8 @@ interface Platformer3DEntity {
|
|
|
196
199
|
declare class Platformer3DBehavior$1 {
|
|
197
200
|
private world;
|
|
198
201
|
private scene;
|
|
199
|
-
private
|
|
200
|
-
private debugLines;
|
|
202
|
+
private groundProbe;
|
|
201
203
|
constructor(world: any, scene: any);
|
|
202
|
-
/**
|
|
203
|
-
* Detect if entity is on the ground using raycasting
|
|
204
|
-
*/
|
|
205
|
-
/**
|
|
206
|
-
* Detect if entity is on the ground using raycasting (multi-sample: center + 4 corners)
|
|
207
|
-
*/
|
|
208
|
-
private detectGround;
|
|
209
|
-
private updateDebugLines;
|
|
210
204
|
/**
|
|
211
205
|
* Apply horizontal movement based on input
|
|
212
206
|
*/
|
|
@@ -227,7 +221,11 @@ declare class Platformer3DBehavior$1 {
|
|
|
227
221
|
*/
|
|
228
222
|
private updateState;
|
|
229
223
|
/**
|
|
230
|
-
* Update
|
|
224
|
+
* Update one platformer entity.
|
|
225
|
+
*/
|
|
226
|
+
updateEntity(entity: any, delta: number): void;
|
|
227
|
+
/**
|
|
228
|
+
* Update all platformer entities.
|
|
231
229
|
*/
|
|
232
230
|
update(delta: number): void;
|
|
233
231
|
/**
|
|
@@ -252,6 +250,8 @@ interface Platformer3DBehaviorOptions {
|
|
|
252
250
|
gravity?: number;
|
|
253
251
|
/** Ray length for ground detection (default: 1.0) */
|
|
254
252
|
groundRayLength?: number;
|
|
253
|
+
/** Enable debug visualization for ground probe rays (default: false) */
|
|
254
|
+
debugGroundProbe?: boolean;
|
|
255
255
|
}
|
|
256
256
|
/**
|
|
257
257
|
* Platformer3DBehavior - typed descriptor for 3D platformer movement
|