@hytopia.com/examples 1.0.45 → 1.0.48
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/big-world/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/big-world/assets/blocks/.atlas/atlas.json +3377 -0
- package/big-world/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/big-world/assets/blocks/.atlas/atlas.png +0 -0
- package/big-world/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/big-world/assets/models/players/.optimized/player/player.glb +0 -0
- package/big-world/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/big-world/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/big-world/assets/models/players/player.gltf +1 -0
- package/big-world/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/big-world/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/big-world/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/big-world/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/big-world/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/big-world/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/block-entity/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/block-entity/assets/blocks/.atlas/atlas.json +3377 -0
- package/block-entity/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/block-entity/assets/blocks/.atlas/atlas.png +0 -0
- package/block-entity/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/block-entity/assets/models/players/.optimized/player/player.glb +0 -0
- package/block-entity/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/block-entity/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/block-entity/assets/models/players/player.gltf +1 -0
- package/block-entity/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/block-entity/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/block-entity/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/block-entity/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/block-entity/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/block-entity/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/child-entity/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/child-entity/assets/blocks/.atlas/atlas.json +3377 -0
- package/child-entity/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/child-entity/assets/blocks/.atlas/atlas.png +0 -0
- package/child-entity/assets/models/items/.optimized/sword/sword-named-nodes.glb +0 -0
- package/child-entity/assets/models/items/.optimized/sword/sword.glb +0 -0
- package/child-entity/assets/models/items/.optimized/sword/sword.gltf.data.json +1 -0
- package/child-entity/assets/models/items/.optimized/sword/sword.gltf.md5 +1 -0
- package/child-entity/assets/models/items/sword.gltf +1 -0
- package/child-entity/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/child-entity/assets/models/players/.optimized/player/player.glb +0 -0
- package/child-entity/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/child-entity/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/child-entity/assets/models/players/player.gltf +1 -0
- package/child-entity/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/child-entity/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/child-entity/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/child-entity/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/child-entity/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/child-entity/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/child-entity/index.ts +4 -2
- package/custom-ui/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/custom-ui/assets/blocks/.atlas/atlas.json +3377 -0
- package/custom-ui/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/custom-ui/assets/blocks/.atlas/atlas.png +0 -0
- package/custom-ui/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/custom-ui/assets/models/players/.optimized/player/player.glb +0 -0
- package/custom-ui/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/custom-ui/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/custom-ui/assets/models/players/player.gltf +1 -0
- package/custom-ui/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/custom-ui/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/custom-ui/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/custom-ui/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/custom-ui/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/custom-ui/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/entity-animations/assets/blocks/.atlas/atlas.json +3377 -0
- package/entity-animations/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/entity-animations/assets/blocks/.atlas/atlas.png +0 -0
- package/entity-animations/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/entity-animations/assets/models/players/.optimized/player/player.glb +0 -0
- package/entity-animations/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/entity-animations/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/entity-animations/assets/models/players/player.gltf +1 -0
- package/entity-animations/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/entity-animations/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/entity-animations/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/entity-animations/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/entity-animations/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/entity-animations/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/entity-animations/index.ts +0 -1
- package/entity-controller/MyEntityController.ts +495 -148
- package/entity-controller/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/entity-controller/assets/blocks/.atlas/atlas.json +3377 -0
- package/entity-controller/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/entity-controller/assets/blocks/.atlas/atlas.png +0 -0
- package/entity-controller/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/entity-controller/assets/models/players/.optimized/player/player.glb +0 -0
- package/entity-controller/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/entity-controller/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/entity-controller/assets/models/players/player.gltf +1 -0
- package/entity-controller/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/entity-controller/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/entity-controller/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/entity-controller/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/entity-controller/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/entity-controller/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/entity-spawn/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/entity-spawn/assets/blocks/.atlas/atlas.json +3377 -0
- package/entity-spawn/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/entity-spawn/assets/blocks/.atlas/atlas.png +0 -0
- package/entity-spawn/assets/models/npcs/.optimized/spider/spider-named-nodes.glb +0 -0
- package/entity-spawn/assets/models/npcs/.optimized/spider/spider.glb +0 -0
- package/entity-spawn/assets/models/npcs/.optimized/spider/spider.gltf.data.json +1 -0
- package/entity-spawn/assets/models/npcs/.optimized/spider/spider.gltf.md5 +1 -0
- package/entity-spawn/assets/models/npcs/spider.gltf +1 -0
- package/entity-spawn/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/entity-spawn/assets/models/players/.optimized/player/player.glb +0 -0
- package/entity-spawn/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/entity-spawn/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/entity-spawn/assets/models/players/player.gltf +1 -0
- package/entity-spawn/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/entity-spawn/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/entity-spawn/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/entity-spawn/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/entity-spawn/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/entity-spawn/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/frontiers-rpg-game/assets/audio/music/cave-theme-looping.mp3 +0 -0
- package/frontiers-rpg-game/assets/audio/music/hytopia-main-theme.mp3 +0 -0
- package/frontiers-rpg-game/assets/audio/music/jungle-theme-looping.mp3 +0 -0
- package/frontiers-rpg-game/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/frontiers-rpg-game/assets/models/items/.optimized/snowball/snowball-named-nodes.glb +0 -0
- package/frontiers-rpg-game/assets/models/items/.optimized/snowball/snowball.glb +0 -0
- package/frontiers-rpg-game/assets/models/items/.optimized/snowball/snowball.gltf.data.json +1 -0
- package/frontiers-rpg-game/assets/models/items/.optimized/snowball/snowball.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/items/.optimized/sword-wooden/sword-wooden-named-nodes.glb +0 -0
- package/frontiers-rpg-game/assets/models/items/.optimized/sword-wooden/sword-wooden.glb +0 -0
- package/frontiers-rpg-game/assets/models/items/.optimized/sword-wooden/sword-wooden.gltf.data.json +1 -0
- package/frontiers-rpg-game/assets/models/items/.optimized/sword-wooden/sword-wooden.gltf.md5 +1 -0
- package/frontiers-rpg-game/assets/models/items/snowball.gltf +1 -0
- package/frontiers-rpg-game/assets/models/items/sword-wooden.gltf +1 -0
- package/frontiers-rpg-game/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/frontiers-rpg-game/assets/models/players/.optimized/player/player.glb +0 -0
- package/frontiers-rpg-game/assets/models/players/.optimized/player/player.gltf.data.json +1 -1
- package/frontiers-rpg-game/assets/models/players/.optimized/player/player.gltf.md5 +1 -1
- package/frontiers-rpg-game/assets/models/players/player.gltf +1 -1
- package/frontiers-rpg-game/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/frontiers-rpg-game/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/frontiers-rpg-game/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/frontiers-rpg-game/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/frontiers-rpg-game/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/frontiers-rpg-game/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/frontiers-rpg-game/dev/persistence/player-player-1.json +1 -1
- package/frontiers-rpg-game/dev/persistence/player-player-12.json +1 -0
- package/frontiers-rpg-game/dev/persistence/player-player-13.json +1 -0
- package/frontiers-rpg-game/dev/persistence/player-player-15.json +1 -0
- package/frontiers-rpg-game/dev/persistence/player-player-16.json +1 -0
- package/frontiers-rpg-game/dev/persistence/player-player-4.json +1 -0
- package/frontiers-rpg-game/dev/persistence/player-player-5.json +1 -0
- package/frontiers-rpg-game/dev/persistence/player-player-8.json +1 -0
- package/hole-in-wall-game/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/hole-in-wall-game/assets/blocks/.atlas/atlas.json +3377 -0
- package/hole-in-wall-game/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/hole-in-wall-game/assets/blocks/.atlas/atlas.png +0 -0
- package/hole-in-wall-game/assets/icons/jump.png +0 -0
- package/hole-in-wall-game/assets/models/npcs/.optimized/mindflayer/mindflayer-named-nodes.glb +0 -0
- package/hole-in-wall-game/assets/models/npcs/.optimized/mindflayer/mindflayer.glb +0 -0
- package/hole-in-wall-game/assets/models/npcs/.optimized/mindflayer/mindflayer.gltf.data.json +1 -0
- package/hole-in-wall-game/assets/models/npcs/.optimized/mindflayer/mindflayer.gltf.md5 +1 -0
- package/hole-in-wall-game/assets/models/npcs/mindflayer.gltf +1 -0
- package/hole-in-wall-game/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/hole-in-wall-game/assets/models/players/.optimized/player/player.glb +0 -0
- package/hole-in-wall-game/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/hole-in-wall-game/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/hole-in-wall-game/assets/models/players/player.gltf +1 -0
- package/hole-in-wall-game/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/hole-in-wall-game/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/hole-in-wall-game/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/hole-in-wall-game/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/hole-in-wall-game/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/hole-in-wall-game/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/huntcraft/assets/blocks/.atlas/atlas.json +2155 -0
- package/huntcraft/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/huntcraft/assets/blocks/.atlas/atlas.png +0 -0
- package/hygrounds/assets/audio/sfx/dig/dig-stone.mp3 +0 -0
- package/hygrounds/assets/audio/sfx/player/player-swing-woosh.mp3 +0 -0
- package/hygrounds/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/hygrounds/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/hygrounds/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/hygrounds/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/hygrounds/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/hygrounds/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/hygrounds/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/lighting/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/lighting/assets/blocks/.atlas/atlas.json +3377 -0
- package/lighting/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/lighting/assets/blocks/.atlas/atlas.png +0 -0
- package/lighting/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/lighting/assets/models/players/.optimized/player/player.glb +0 -0
- package/lighting/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/lighting/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/lighting/assets/models/players/player.gltf +1 -0
- package/lighting/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/lighting/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/lighting/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/lighting/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/lighting/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/lighting/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/mobile-controls/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/mobile-controls/assets/blocks/.atlas/atlas.json +3377 -0
- package/mobile-controls/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/mobile-controls/assets/blocks/.atlas/atlas.png +0 -0
- package/mobile-controls/assets/icons/jump.png +0 -0
- package/mobile-controls/assets/icons/target.png +0 -0
- package/mobile-controls/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/mobile-controls/assets/models/players/.optimized/player/player.glb +0 -0
- package/mobile-controls/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/mobile-controls/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/mobile-controls/assets/models/players/player.gltf +1 -0
- package/mobile-controls/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/mobile-controls/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/mobile-controls/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/mobile-controls/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/mobile-controls/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/mobile-controls/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/package.json +1 -1
- package/particles/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/particles/assets/blocks/.atlas/atlas.json +3377 -0
- package/particles/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/particles/assets/blocks/.atlas/atlas.png +0 -0
- package/particles/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/particles/assets/models/players/.optimized/player/player.glb +0 -0
- package/particles/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/particles/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/particles/assets/models/players/player.gltf +1 -0
- package/particles/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/particles/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/particles/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/particles/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/particles/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/particles/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/pathfinding/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/pathfinding/assets/blocks/.atlas/atlas.json +3377 -0
- package/pathfinding/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/pathfinding/assets/blocks/.atlas/atlas.png +0 -0
- package/pathfinding/assets/models/items/.optimized/cookie/cookie-named-nodes.glb +0 -0
- package/pathfinding/assets/models/items/.optimized/cookie/cookie.glb +0 -0
- package/pathfinding/assets/models/items/.optimized/cookie/cookie.gltf.data.json +1 -0
- package/pathfinding/assets/models/items/.optimized/cookie/cookie.gltf.md5 +1 -0
- package/pathfinding/assets/models/items/cookie.gltf +1 -0
- package/pathfinding/assets/models/npcs/.optimized/zombie/zombie-named-nodes.glb +0 -0
- package/pathfinding/assets/models/npcs/.optimized/zombie/zombie.glb +0 -0
- package/pathfinding/assets/models/npcs/.optimized/zombie/zombie.gltf.data.json +1 -0
- package/pathfinding/assets/models/npcs/.optimized/zombie/zombie.gltf.md5 +1 -0
- package/pathfinding/assets/models/npcs/zombie.gltf +1 -0
- package/pathfinding/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/pathfinding/assets/models/players/.optimized/player/player.glb +0 -0
- package/pathfinding/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/pathfinding/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/pathfinding/assets/models/players/player.gltf +1 -0
- package/pathfinding/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/pathfinding/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/pathfinding/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/pathfinding/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/pathfinding/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/pathfinding/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/payload-game/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/payload-game/assets/blocks/.atlas/atlas.json +3377 -0
- package/payload-game/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/payload-game/assets/blocks/.atlas/atlas.png +0 -0
- package/payload-game/assets/models/npcs/.optimized/spider/spider-named-nodes.glb +0 -0
- package/payload-game/assets/models/npcs/.optimized/spider/spider.glb +0 -0
- package/payload-game/assets/models/npcs/.optimized/spider/spider.gltf.data.json +1 -0
- package/payload-game/assets/models/npcs/.optimized/spider/spider.gltf.md5 +1 -0
- package/payload-game/assets/models/npcs/spider.gltf +1 -0
- package/payload-game/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/payload-game/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/payload-game/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/payload-game/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/payload-game/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/payload-game/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/player-persistence/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/player-persistence/assets/blocks/.atlas/atlas.json +3377 -0
- package/player-persistence/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/player-persistence/assets/blocks/.atlas/atlas.png +0 -0
- package/player-persistence/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/player-persistence/assets/models/players/.optimized/player/player.glb +0 -0
- package/player-persistence/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/player-persistence/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/player-persistence/assets/models/players/player.gltf +1 -0
- package/player-persistence/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/player-persistence/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/player-persistence/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/player-persistence/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/player-persistence/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/player-persistence/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/scheduled-notifications/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/scheduled-notifications/assets/blocks/.atlas/atlas.json +3377 -0
- package/scheduled-notifications/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/scheduled-notifications/assets/blocks/.atlas/atlas.png +0 -0
- package/scheduled-notifications/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/scheduled-notifications/assets/models/players/.optimized/player/player.glb +0 -0
- package/scheduled-notifications/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/scheduled-notifications/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/scheduled-notifications/assets/models/players/player.gltf +1 -0
- package/scheduled-notifications/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/scheduled-notifications/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/scheduled-notifications/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/scheduled-notifications/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/scheduled-notifications/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/scheduled-notifications/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/wall-dodge-game/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/wall-dodge-game/assets/blocks/.atlas/atlas.json +3377 -0
- package/wall-dodge-game/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/wall-dodge-game/assets/blocks/.atlas/atlas.png +0 -0
- package/wall-dodge-game/assets/icons/jump.png +0 -0
- package/wall-dodge-game/assets/models/npcs/.optimized/mindflayer/mindflayer-named-nodes.glb +0 -0
- package/wall-dodge-game/assets/models/npcs/.optimized/mindflayer/mindflayer.glb +0 -0
- package/wall-dodge-game/assets/models/npcs/.optimized/mindflayer/mindflayer.gltf.data.json +1 -0
- package/wall-dodge-game/assets/models/npcs/.optimized/mindflayer/mindflayer.gltf.md5 +1 -0
- package/wall-dodge-game/assets/models/npcs/mindflayer.gltf +1 -0
- package/wall-dodge-game/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/wall-dodge-game/assets/models/players/.optimized/player/player.glb +0 -0
- package/wall-dodge-game/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/wall-dodge-game/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/wall-dodge-game/assets/models/players/player.gltf +1 -0
- package/wall-dodge-game/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/wall-dodge-game/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/wall-dodge-game/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/wall-dodge-game/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/wall-dodge-game/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/wall-dodge-game/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/world-switching/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
- package/world-switching/assets/blocks/.atlas/atlas.json +3377 -0
- package/world-switching/assets/blocks/.atlas/atlas.ktx2 +0 -0
- package/world-switching/assets/blocks/.atlas/atlas.png +0 -0
- package/world-switching/assets/models/players/.optimized/player/player-named-nodes.glb +0 -0
- package/world-switching/assets/models/players/.optimized/player/player.glb +0 -0
- package/world-switching/assets/models/players/.optimized/player/player.gltf.data.json +1 -0
- package/world-switching/assets/models/players/.optimized/player/player.gltf.md5 +1 -0
- package/world-switching/assets/models/players/player.gltf +1 -0
- package/world-switching/assets/models/projectiles/.optimized/energy-orb-projectile/energy-orb-projectile-named-nodes.glb +0 -0
- package/world-switching/assets/models/projectiles/.optimized/energy-orb-projectile/energy-orb-projectile.glb +0 -0
- package/world-switching/assets/models/projectiles/.optimized/energy-orb-projectile/energy-orb-projectile.gltf.data.json +1 -0
- package/world-switching/assets/models/projectiles/.optimized/energy-orb-projectile/energy-orb-projectile.gltf.md5 +1 -0
- package/world-switching/assets/models/projectiles/energy-orb-projectile.gltf +1 -0
- package/world-switching/assets/skyboxes/partly-cloudy/+x.png +0 -0
- package/world-switching/assets/skyboxes/partly-cloudy/+y.png +0 -0
- package/world-switching/assets/skyboxes/partly-cloudy/+z.png +0 -0
- package/world-switching/assets/skyboxes/partly-cloudy/-x.png +0 -0
- package/world-switching/assets/skyboxes/partly-cloudy/-y.png +0 -0
- package/world-switching/assets/skyboxes/partly-cloudy/-z.png +0 -0
- package/zombies-fps/assets/audio/sfx/step/stone/stone-step-04.mp3 +0 -0
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
CoefficientCombineRule,
|
|
6
6
|
CollisionGroup,
|
|
7
7
|
Entity,
|
|
8
|
+
EntityEvent,
|
|
9
|
+
ErrorHandler,
|
|
8
10
|
PlayerEntity,
|
|
9
11
|
BlockType,
|
|
10
12
|
} from 'hytopia';
|
|
@@ -12,99 +14,305 @@ import {
|
|
|
12
14
|
import type {
|
|
13
15
|
PlayerInput,
|
|
14
16
|
PlayerCameraOrientation,
|
|
17
|
+
Vector3Like,
|
|
15
18
|
} from 'hytopia';
|
|
16
19
|
|
|
17
20
|
/** Options for creating a MyEntityController instance. @public */
|
|
18
21
|
export interface MyEntityControllerOptions {
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/** The normalized horizontal velocity applied to the entity when it runs. */
|
|
23
|
-
runVelocity?: number;
|
|
22
|
+
/** Whether to apply directional rotations to the entity while moving, defaults to true. */
|
|
23
|
+
applyDirectionalMovementRotations?: boolean;
|
|
24
24
|
|
|
25
|
-
/**
|
|
26
|
-
|
|
25
|
+
/** Whether to automatically cancel left click input after first processed tick, defaults to true. */
|
|
26
|
+
autoCancelMouseLeftClick?: boolean;
|
|
27
27
|
|
|
28
28
|
/** A function allowing custom logic to determine if the entity can jump. */
|
|
29
29
|
canJump?: () => boolean;
|
|
30
30
|
|
|
31
|
+
/** A function allowing custom logic to determine if the entity can run. */
|
|
32
|
+
canRun?: () => boolean;
|
|
33
|
+
|
|
34
|
+
/** A function allowing custom logic to determine if the entity can swim. */
|
|
35
|
+
canSwim?: () => boolean;
|
|
36
|
+
|
|
31
37
|
/** A function allowing custom logic to determine if the entity can walk. */
|
|
32
38
|
canWalk?: () => boolean;
|
|
33
39
|
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
/** Whether to face forward when the entity stops moving. */
|
|
41
|
+
faceForwardOnStop?: boolean;
|
|
42
|
+
|
|
43
|
+
/** Overrides the animation(s) that will play when the entity is idle. */
|
|
44
|
+
idleLoopedAnimations?: string[];
|
|
45
|
+
|
|
46
|
+
/** Overrides the animation(s) that will play when the entity interacts (left click) */
|
|
47
|
+
interactOneshotAnimations?: string[];
|
|
48
|
+
|
|
49
|
+
/** Overrides the animation(s) that will play when the entity is jumping. */
|
|
50
|
+
jumpOneshotAnimations?: string[];
|
|
51
|
+
|
|
52
|
+
/** Overrides the animation(s) that will play when the entity lands with a high velocity. */
|
|
53
|
+
jumpLandHeavyOneshotAnimations?: string[];
|
|
54
|
+
|
|
55
|
+
/** Overrides the animation(s) that will play when the entity lands after jumping or being airborne. */
|
|
56
|
+
jumpLandLightOneshotAnimations?: string[];
|
|
37
57
|
|
|
38
|
-
/**
|
|
39
|
-
* A custom entity controller implementation.
|
|
40
|
-
*
|
|
41
|
-
* @remarks
|
|
42
|
-
* This class extends {@link BaseEntityController}
|
|
43
|
-
* and implements the default movement logic for a
|
|
44
|
-
* entity.
|
|
45
|
-
*
|
|
46
|
-
* @public
|
|
47
|
-
*/
|
|
48
|
-
export default class MyEntityController extends BaseEntityController {
|
|
49
58
|
/** The upward velocity applied to the entity when it jumps. */
|
|
50
|
-
|
|
59
|
+
jumpVelocity?: number;
|
|
51
60
|
|
|
52
61
|
/** The normalized horizontal velocity applied to the entity when it runs. */
|
|
53
|
-
|
|
62
|
+
runVelocity?: number;
|
|
63
|
+
|
|
64
|
+
/** Overrides the animation(s) that will play when the entity is running. */
|
|
65
|
+
runLoopedAnimations?: string[];
|
|
66
|
+
|
|
67
|
+
/** Whether the entity sticks to platforms, defaults to true. */
|
|
68
|
+
sticksToPlatforms?: boolean;
|
|
69
|
+
|
|
70
|
+
/** The normalized horizontal velocity applied to the entity when it swims fast (equivalent to running). */
|
|
71
|
+
swimFastVelocity?: number;
|
|
72
|
+
|
|
73
|
+
/** The gravity modifier applied to the entity when swimming. */
|
|
74
|
+
swimGravity?: number;
|
|
75
|
+
|
|
76
|
+
/** The maximum downward velocity that the entity can reach when affected by gravity while swimming. */
|
|
77
|
+
swimMaxGravityVelocity?: number;
|
|
78
|
+
|
|
79
|
+
/** The looped animation(s) that will play when the entity is swimming in any direction. */
|
|
80
|
+
swimLoopedAnimations?: string[];
|
|
81
|
+
|
|
82
|
+
/** The looped animation(s) that will play when the entity is not moving while swimming. */
|
|
83
|
+
swimIdleLoopedAnimations?: string[];
|
|
84
|
+
|
|
85
|
+
/** The normalized horizontal velocity applied to the entity when it swims slowly (equivalent to walking). */
|
|
86
|
+
swimSlowVelocity?: number;
|
|
87
|
+
|
|
88
|
+
/** The upward velocity applied to the entity when swimming. */
|
|
89
|
+
swimUpwardVelocity?: number;
|
|
90
|
+
|
|
91
|
+
/** Overrides the animation(s) that will play when the entity is walking. */
|
|
92
|
+
walkLoopedAnimations?: string[];
|
|
54
93
|
|
|
55
94
|
/** The normalized horizontal velocity applied to the entity when it walks. */
|
|
56
|
-
|
|
95
|
+
walkVelocity?: number;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default class MyEntityController extends BaseEntityController {
|
|
99
|
+
// These constants are based on a model scale of 1, and will scale relative to the entity.modelScale
|
|
100
|
+
private static readonly BASE_ENTITY_HEIGHT = 1.5;
|
|
101
|
+
private static readonly GROUND_SENSOR_HEIGHT_SCALE = 0.125;
|
|
102
|
+
private static readonly GROUND_SENSOR_RADIUS_SCALE = 0.23;
|
|
103
|
+
private static readonly JUMP_LAND_HEAVY_VELOCITY_THRESHOLD = -12;
|
|
104
|
+
private static readonly WALL_COLLIDER_HEIGHT_SCALE = 0.33;
|
|
105
|
+
private static readonly WALL_COLLIDER_RADIUS_SCALE = 0.40;
|
|
106
|
+
|
|
107
|
+
// Movement rotation lookup (static to avoid per-tick allocation)
|
|
108
|
+
private static readonly MOVEMENT_ROTATIONS: Record<string, number> = {
|
|
109
|
+
'wa': Math.PI / 4,
|
|
110
|
+
'wd': -Math.PI / 4,
|
|
111
|
+
'sa': Math.PI - Math.PI / 4,
|
|
112
|
+
'sd': Math.PI + Math.PI / 4,
|
|
113
|
+
's': Math.PI,
|
|
114
|
+
'asd': Math.PI, // Special case for a+s+d without w
|
|
115
|
+
'a': Math.PI / 2,
|
|
116
|
+
'd': -Math.PI / 2,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Physics constants
|
|
120
|
+
private static readonly EXTERNAL_IMPULSE_DECAY_RATE = 0.253;
|
|
121
|
+
private static readonly SWIM_UPWARD_COOLDOWN_MS = 600;
|
|
122
|
+
private static readonly SWIMMING_DRAG_FACTOR = 0.05;
|
|
123
|
+
private static readonly WATER_ENTRY_SINKING_FACTOR = 0.8;
|
|
124
|
+
private static readonly WATER_ENTRY_SINKING_MS = 250;
|
|
125
|
+
|
|
126
|
+
/** Whether to apply directional rotations to the entity while moving, defaults to true. */
|
|
127
|
+
public applyDirectionalMovementRotations: boolean = true;
|
|
128
|
+
|
|
129
|
+
/** Whether to automatically cancel left click input after first processed tick, defaults to true. */
|
|
130
|
+
public autoCancelMouseLeftClick: boolean = true;
|
|
57
131
|
|
|
58
132
|
/**
|
|
59
|
-
* A function allowing custom logic to determine if the entity can
|
|
60
|
-
* @param
|
|
61
|
-
* @returns Whether the entity of the entity controller can
|
|
133
|
+
* A function allowing custom logic to determine if the entity can jump.
|
|
134
|
+
* @param controller - The default player entity controller instance.
|
|
135
|
+
* @returns Whether the entity of the entity controller can jump.
|
|
62
136
|
*/
|
|
63
|
-
public
|
|
137
|
+
public canJump: (controller: MyEntityController) => boolean = () => true;
|
|
64
138
|
|
|
65
139
|
/**
|
|
66
140
|
* A function allowing custom logic to determine if the entity can run.
|
|
67
|
-
* @param
|
|
141
|
+
* @param controller - The default player entity controller instance.
|
|
68
142
|
* @returns Whether the entity of the entity controller can run.
|
|
69
143
|
*/
|
|
70
|
-
public canRun: (
|
|
144
|
+
public canRun: (controller: MyEntityController) => boolean = () => true;
|
|
71
145
|
|
|
72
146
|
/**
|
|
73
|
-
* A function allowing custom logic to determine if the entity can
|
|
74
|
-
* @param
|
|
75
|
-
* @returns Whether the entity of the entity controller can
|
|
147
|
+
* A function allowing custom logic to determine if the entity can swim.
|
|
148
|
+
* @param controller - The default player entity controller instance.
|
|
149
|
+
* @returns Whether the entity of the entity controller can swim.
|
|
150
|
+
*/
|
|
151
|
+
public canSwim: (controller: MyEntityController) => boolean = () => true;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* A function allowing custom logic to determine if the entity can walk.
|
|
155
|
+
* @param controller - The default player entity controller instance.
|
|
156
|
+
* @returns Whether the entity of the entity controller can walk.
|
|
76
157
|
*/
|
|
77
|
-
public
|
|
158
|
+
public canWalk: (controller: MyEntityController) => boolean = () => true;
|
|
159
|
+
|
|
160
|
+
/** Whether to face forward when the entity stops moving. */
|
|
161
|
+
public faceForwardOnStop: boolean = true;
|
|
162
|
+
|
|
163
|
+
/** The looped animation(s) that will play when the entity is idle. */
|
|
164
|
+
public idleLoopedAnimations: string[] = [ 'idle-upper', 'idle-lower' ];
|
|
165
|
+
|
|
166
|
+
/** The oneshot animation(s) that will play when the entity interacts (left click) */
|
|
167
|
+
public interactOneshotAnimations: string[] = [ 'simple-interact' ];
|
|
168
|
+
|
|
169
|
+
/** The oneshot animation(s) that will play when the entity lands with a high velocity. */
|
|
170
|
+
public jumpLandHeavyOneshotAnimations: string[] = [ 'jump-post-heavy' ];
|
|
171
|
+
|
|
172
|
+
/** The oneshot animation(s) that will play when the entity lands after jumping or being airborne. */
|
|
173
|
+
public jumpLandLightOneshotAnimations: string[] = [ 'jump-post-light' ];
|
|
174
|
+
|
|
175
|
+
/** The oneshot animation(s) that will play when the entity is jumping. */
|
|
176
|
+
public jumpOneshotAnimations: string[] = [ 'jump-loop' ];
|
|
177
|
+
|
|
178
|
+
/** The upward velocity applied to the entity when it jumps. */
|
|
179
|
+
public jumpVelocity: number = 10;
|
|
180
|
+
|
|
181
|
+
/** The looped animation(s) that will play when the entity is running. */
|
|
182
|
+
public runLoopedAnimations: string[] = [ 'run-upper', 'run-lower' ];
|
|
183
|
+
|
|
184
|
+
/** The normalized horizontal velocity applied to the entity when it runs. */
|
|
185
|
+
public runVelocity: number = 8;
|
|
186
|
+
|
|
187
|
+
/** Whether the entity sticks to platforms. */
|
|
188
|
+
public sticksToPlatforms: boolean = true;
|
|
189
|
+
|
|
190
|
+
/** The normalized horizontal velocity applied to the entity when it swims fast (equivalent to running). */
|
|
191
|
+
public swimFastVelocity: number = 5;
|
|
192
|
+
|
|
193
|
+
/** The gravity modifier applied to the entity when swimming. */
|
|
194
|
+
public swimGravity: number = 0;
|
|
195
|
+
|
|
196
|
+
/** The looped animation(s) that will play when the entity is not moving while swimming. */
|
|
197
|
+
public swimIdleLoopedAnimations: string[] = [ 'swim-idle' ];
|
|
198
|
+
|
|
199
|
+
/** The looped animation(s) that will play when the entity is swimming in any direction. */
|
|
200
|
+
public swimLoopedAnimations: string[] = [ 'swim-forward' ];
|
|
201
|
+
|
|
202
|
+
/** The maximum downward velocity that the entity can reach when affected by gravity while swimming. */
|
|
203
|
+
public swimMaxGravityVelocity: number = -1;
|
|
204
|
+
|
|
205
|
+
/** The normalized horizontal velocity applied to the entity when it swims slowly (equivalent to walking). */
|
|
206
|
+
public swimSlowVelocity: number = 3;
|
|
207
|
+
|
|
208
|
+
/** The upward velocity applied to the entity when swimming. */
|
|
209
|
+
public swimUpwardVelocity: number = 2;
|
|
210
|
+
|
|
211
|
+
/** The looped animation(s) that will play when the entity is walking. */
|
|
212
|
+
public walkLoopedAnimations: string[] = [ 'walk-upper', 'walk-lower' ];
|
|
213
|
+
|
|
214
|
+
/** The normalized horizontal velocity applied to the entity when it walks. */
|
|
215
|
+
public walkVelocity: number = 4;
|
|
78
216
|
|
|
79
217
|
/** @internal */
|
|
80
|
-
private
|
|
218
|
+
private readonly _externalVelocity = { x: 0, y: 0, z: 0 };
|
|
219
|
+
|
|
220
|
+
/** @internal */
|
|
221
|
+
private _magnitudeYTracker: number = 0;
|
|
81
222
|
|
|
82
223
|
/** @internal */
|
|
83
224
|
private _groundContactCount: number = 0;
|
|
84
225
|
|
|
226
|
+
/** @internal */
|
|
227
|
+
private _internalApplyImpulse: (impulse: Vector3Like) => void = () => {};
|
|
228
|
+
|
|
229
|
+
/** @internal */
|
|
230
|
+
private _isActivelyMoving: boolean = false;
|
|
231
|
+
|
|
232
|
+
/** @internal */
|
|
233
|
+
private _isFullySubmerged: boolean = false;
|
|
234
|
+
|
|
235
|
+
/** @internal */
|
|
236
|
+
private _justSubmergedUntil: number = 0;
|
|
237
|
+
|
|
238
|
+
/** @internal */
|
|
239
|
+
private _liquidContactCount: number = 0;
|
|
240
|
+
|
|
85
241
|
/** @internal */
|
|
86
242
|
private _platform: Entity | undefined;
|
|
87
243
|
|
|
244
|
+
/** @internal - Reusable vector for impulse calculation to avoid per-tick allocation */
|
|
245
|
+
private readonly _reusableImpulse = { x: 0, y: 0, z: 0 };
|
|
246
|
+
|
|
247
|
+
/** @internal - Reusable vector for platform velocity fallback to avoid per-tick allocation */
|
|
248
|
+
private readonly _reusablePlatformVelocity = { x: 0, y: 0, z: 0 };
|
|
249
|
+
|
|
250
|
+
/** @internal - Reusable vector for target velocities to avoid per-tick allocation */
|
|
251
|
+
private readonly _reusableTargetVelocities = { x: 0, y: 0, z: 0 };
|
|
252
|
+
|
|
253
|
+
/** @internal - Reusable vector for velocity clamping to avoid per-tick allocation */
|
|
254
|
+
private readonly _reusableVelocityClamp = { x: 0, y: 0, z: 0 };
|
|
255
|
+
|
|
256
|
+
/** @internal */
|
|
257
|
+
private _stepAudio: Audio | undefined;
|
|
258
|
+
|
|
259
|
+
/** @internal */
|
|
260
|
+
private _swimUpwardCooldownAt: number = 0;
|
|
261
|
+
|
|
88
262
|
/**
|
|
89
263
|
* @param options - Options for the controller.
|
|
90
264
|
*/
|
|
91
265
|
public constructor(options: MyEntityControllerOptions = {}) {
|
|
92
266
|
super();
|
|
93
267
|
|
|
268
|
+
// Basic behavior options
|
|
269
|
+
this.applyDirectionalMovementRotations = options.applyDirectionalMovementRotations ?? this.applyDirectionalMovementRotations;
|
|
270
|
+
this.autoCancelMouseLeftClick = options.autoCancelMouseLeftClick ?? this.autoCancelMouseLeftClick;
|
|
271
|
+
this.faceForwardOnStop = options.faceForwardOnStop ?? this.faceForwardOnStop;
|
|
272
|
+
this.sticksToPlatforms = options.sticksToPlatforms ?? this.sticksToPlatforms;
|
|
273
|
+
|
|
274
|
+
// Capability functions
|
|
275
|
+
this.canJump = options.canJump ?? this.canJump;
|
|
276
|
+
this.canRun = options.canRun ?? this.canRun;
|
|
277
|
+
this.canSwim = options.canSwim ?? this.canSwim;
|
|
278
|
+
this.canWalk = options.canWalk ?? this.canWalk;
|
|
279
|
+
|
|
280
|
+
// Movement velocities
|
|
94
281
|
this.jumpVelocity = options.jumpVelocity ?? this.jumpVelocity;
|
|
95
282
|
this.runVelocity = options.runVelocity ?? this.runVelocity;
|
|
96
283
|
this.walkVelocity = options.walkVelocity ?? this.walkVelocity;
|
|
97
|
-
this.
|
|
98
|
-
this.
|
|
99
|
-
this.
|
|
284
|
+
this.swimFastVelocity = options.swimFastVelocity ?? this.swimFastVelocity;
|
|
285
|
+
this.swimSlowVelocity = options.swimSlowVelocity ?? this.swimSlowVelocity;
|
|
286
|
+
this.swimUpwardVelocity = options.swimUpwardVelocity ?? this.swimUpwardVelocity;
|
|
287
|
+
|
|
288
|
+
// Swimming physics
|
|
289
|
+
this.swimGravity = options.swimGravity ?? this.swimGravity;
|
|
290
|
+
this.swimMaxGravityVelocity = options.swimMaxGravityVelocity ?? this.swimMaxGravityVelocity;
|
|
291
|
+
|
|
292
|
+
// Animation overrides
|
|
293
|
+
this.idleLoopedAnimations = options.idleLoopedAnimations ?? this.idleLoopedAnimations;
|
|
294
|
+
this.interactOneshotAnimations = options.interactOneshotAnimations ?? this.interactOneshotAnimations;
|
|
295
|
+
this.jumpOneshotAnimations = options.jumpOneshotAnimations ?? this.jumpOneshotAnimations;
|
|
296
|
+
this.jumpLandHeavyOneshotAnimations = options.jumpLandHeavyOneshotAnimations ?? this.jumpLandHeavyOneshotAnimations;
|
|
297
|
+
this.jumpLandLightOneshotAnimations = options.jumpLandLightOneshotAnimations ?? this.jumpLandLightOneshotAnimations;
|
|
298
|
+
this.runLoopedAnimations = options.runLoopedAnimations ?? this.runLoopedAnimations;
|
|
299
|
+
this.swimLoopedAnimations = options.swimLoopedAnimations ?? this.swimLoopedAnimations;
|
|
300
|
+
this.swimIdleLoopedAnimations = options.swimIdleLoopedAnimations ?? this.swimIdleLoopedAnimations;
|
|
301
|
+
this.walkLoopedAnimations = options.walkLoopedAnimations ?? this.walkLoopedAnimations;
|
|
100
302
|
}
|
|
101
303
|
|
|
304
|
+
/** Whether the entity is moving from player inputs. */
|
|
305
|
+
public get isActivelyMoving(): boolean { return this._isActivelyMoving; }
|
|
306
|
+
|
|
102
307
|
/** Whether the entity is grounded. */
|
|
103
308
|
public get isGrounded(): boolean { return this._groundContactCount > 0; }
|
|
104
309
|
|
|
105
310
|
/** Whether the entity is on a platform, a platform is any entity with a kinematic rigid body. */
|
|
106
311
|
public get isOnPlatform(): boolean { return !!this._platform; }
|
|
107
312
|
|
|
313
|
+
/** Whether the entity is swimming, this is determined by if the entity is in a liquid block. */
|
|
314
|
+
public get isSwimming(): boolean { return this._liquidContactCount > 0; }
|
|
315
|
+
|
|
108
316
|
/** The platform the entity is on, if any. */
|
|
109
317
|
public get platform(): Entity | undefined { return this._platform; }
|
|
110
318
|
|
|
@@ -112,54 +320,111 @@ export default class MyEntityController extends BaseEntityController {
|
|
|
112
320
|
* Called when the controller is attached to an entity.
|
|
113
321
|
* @param entity - The entity to attach the controller to.
|
|
114
322
|
*/
|
|
115
|
-
public attach(entity: Entity) {
|
|
323
|
+
public override attach(entity: Entity) {
|
|
324
|
+
super.attach(entity);
|
|
325
|
+
|
|
326
|
+
// Alter applyImpulse to handle external velocities within internal movement velocity conflicts.
|
|
327
|
+
this._internalApplyImpulse = entity.applyImpulse.bind(entity);
|
|
328
|
+
entity.applyImpulse = (impulse: Vector3Like) => {
|
|
329
|
+
// Convert impulses to velocity (impulse = mass * velocity)
|
|
330
|
+
const mass = entity.mass || 1;
|
|
331
|
+
this._externalVelocity.x += impulse.x / mass;
|
|
332
|
+
this._externalVelocity.y += impulse.y / mass;
|
|
333
|
+
this._externalVelocity.z += impulse.z / mass;
|
|
334
|
+
};
|
|
335
|
+
|
|
116
336
|
this._stepAudio = new Audio({
|
|
117
337
|
uri: 'audio/sfx/step/stone/stone-step-04.mp3',
|
|
118
338
|
loop: true,
|
|
119
339
|
volume: 0.1,
|
|
340
|
+
referenceDistance: 2,
|
|
341
|
+
cutoffDistance: 15,
|
|
120
342
|
attachedToEntity: entity,
|
|
121
343
|
});
|
|
122
344
|
|
|
345
|
+
entity.setCcdEnabled(true);
|
|
123
346
|
entity.lockAllRotations(); // prevent physics from applying rotation to the entity, we can still explicitly set it.
|
|
124
|
-
|
|
347
|
+
|
|
348
|
+
// Handle swimming when in contact with a liquid block
|
|
349
|
+
entity.on(EntityEvent.BLOCK_COLLISION, ({ blockType, started }) => {
|
|
350
|
+
if (!blockType.isLiquid || !this.canSwim(this)) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Slow the linear velocity of the entity when
|
|
355
|
+
// first entering the liquid to feel more natural
|
|
356
|
+
if (this._liquidContactCount <= 0 && started) {
|
|
357
|
+
const currentLinearVelocity = entity.linearVelocity;
|
|
358
|
+
entity.setLinearVelocity({
|
|
359
|
+
x: currentLinearVelocity.x * this.swimGravity,
|
|
360
|
+
y: currentLinearVelocity.y * this.swimGravity,
|
|
361
|
+
z: currentLinearVelocity.z * this.swimGravity,
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
this._liquidContactCount += started ? 1 : -1;
|
|
366
|
+
|
|
367
|
+
if (this._liquidContactCount > 0) {
|
|
368
|
+
entity.setGravityScale(this.swimGravity);
|
|
369
|
+
entity.stopAllModelLoopedAnimations(this.swimLoopedAnimations);
|
|
370
|
+
this._swimUpwardCooldownAt = performance.now() + MyEntityController.SWIM_UPWARD_COOLDOWN_MS;
|
|
371
|
+
} else {
|
|
372
|
+
entity.setGravityScale(1);
|
|
373
|
+
entity.stopModelAnimations(this.swimLoopedAnimations);
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}
|
|
125
377
|
|
|
126
378
|
/**
|
|
127
379
|
* Called when the controlled entity is spawned.
|
|
128
|
-
* In
|
|
380
|
+
* In DefaultPlayerEntityController, this function is used to create
|
|
129
381
|
* the colliders for the entity for wall and ground detection.
|
|
130
382
|
* @param entity - The entity that is spawned.
|
|
131
383
|
*/
|
|
132
|
-
public spawn(entity: Entity) {
|
|
384
|
+
public spawn(entity: Entity): void {
|
|
133
385
|
if (!entity.isSpawned) {
|
|
134
|
-
|
|
386
|
+
return ErrorHandler.error('MyEntityController.spawn(): Entity is not spawned!');
|
|
135
387
|
}
|
|
136
388
|
|
|
137
389
|
// Ground sensor
|
|
138
390
|
entity.createAndAddChildCollider({
|
|
139
391
|
shape: ColliderShape.CYLINDER,
|
|
140
|
-
radius:
|
|
141
|
-
halfHeight:
|
|
392
|
+
radius: MyEntityController.GROUND_SENSOR_RADIUS_SCALE * (entity.height / MyEntityController.BASE_ENTITY_HEIGHT),
|
|
393
|
+
halfHeight: MyEntityController.GROUND_SENSOR_HEIGHT_SCALE * (entity.height / MyEntityController.BASE_ENTITY_HEIGHT),
|
|
142
394
|
collisionGroups: {
|
|
143
395
|
belongsTo: [ CollisionGroup.ENTITY_SENSOR ],
|
|
144
|
-
collidesWith: [ CollisionGroup.BLOCK, CollisionGroup.ENTITY ],
|
|
396
|
+
collidesWith: [ CollisionGroup.BLOCK, CollisionGroup.ENTITY, CollisionGroup.ENVIRONMENT_ENTITY ],
|
|
145
397
|
},
|
|
146
398
|
isSensor: true,
|
|
147
|
-
relativePosition: { x: 0, y: -
|
|
399
|
+
relativePosition: { x: 0, y: -entity.height / 2, z: 0 },
|
|
148
400
|
tag: 'groundSensor',
|
|
149
401
|
onCollision: (_other: BlockType | Entity, started: boolean) => {
|
|
402
|
+
if (!entity.isSpawned) { return; }
|
|
403
|
+
|
|
150
404
|
// Ground contact
|
|
151
|
-
|
|
405
|
+
if (!(_other instanceof BlockType) || !_other.isLiquid) {
|
|
406
|
+
// Landing detection: check before updating ground count
|
|
407
|
+
if (started && this._groundContactCount === 0 && entity.linearVelocity.y < -1) {
|
|
408
|
+
if (entity.linearVelocity.y < MyEntityController.JUMP_LAND_HEAVY_VELOCITY_THRESHOLD) {
|
|
409
|
+
entity.startModelOneshotAnimations(this.jumpLandHeavyOneshotAnimations);
|
|
410
|
+
} else {
|
|
411
|
+
entity.startModelOneshotAnimations(this.jumpLandLightOneshotAnimations);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
this._groundContactCount += started ? 1 : -1;
|
|
416
|
+
}
|
|
152
417
|
|
|
153
|
-
if (!this._groundContactCount) {
|
|
154
|
-
entity.startModelOneshotAnimations(
|
|
418
|
+
if (!this._groundContactCount && !this.isSwimming) {
|
|
419
|
+
entity.startModelOneshotAnimations(this.jumpOneshotAnimations);
|
|
155
420
|
} else {
|
|
156
|
-
entity.stopModelAnimations(
|
|
421
|
+
entity.stopModelAnimations(this.jumpOneshotAnimations);
|
|
157
422
|
}
|
|
158
423
|
|
|
159
424
|
// Platform contact
|
|
160
|
-
if (!(_other instanceof Entity)
|
|
425
|
+
if (!(_other instanceof Entity)) return;
|
|
161
426
|
|
|
162
|
-
if (started) {
|
|
427
|
+
if (started && this.sticksToPlatforms) {
|
|
163
428
|
this._platform = _other;
|
|
164
429
|
} else if (_other === this._platform && !started) {
|
|
165
430
|
this._platform = undefined;
|
|
@@ -167,25 +432,26 @@ export default class MyEntityController extends BaseEntityController {
|
|
|
167
432
|
},
|
|
168
433
|
});
|
|
169
434
|
|
|
170
|
-
|
|
171
435
|
// Wall collider
|
|
172
436
|
entity.createAndAddChildCollider({
|
|
173
437
|
shape: ColliderShape.CAPSULE,
|
|
174
|
-
halfHeight:
|
|
175
|
-
radius:
|
|
438
|
+
halfHeight: MyEntityController.WALL_COLLIDER_HEIGHT_SCALE * (entity.height / MyEntityController.BASE_ENTITY_HEIGHT),
|
|
439
|
+
radius: MyEntityController.WALL_COLLIDER_RADIUS_SCALE * (entity.height / MyEntityController.BASE_ENTITY_HEIGHT),
|
|
176
440
|
collisionGroups: {
|
|
177
441
|
belongsTo: [ CollisionGroup.ENTITY_SENSOR ],
|
|
178
|
-
collidesWith: [ CollisionGroup.BLOCK ],
|
|
442
|
+
collidesWith: [ CollisionGroup.BLOCK, CollisionGroup.ENTITY, CollisionGroup.ENVIRONMENT_ENTITY ],
|
|
179
443
|
},
|
|
180
444
|
friction: 0,
|
|
181
445
|
frictionCombineRule: CoefficientCombineRule.Min,
|
|
182
446
|
tag: 'wallCollider',
|
|
183
447
|
});
|
|
184
|
-
}
|
|
448
|
+
}
|
|
185
449
|
|
|
186
450
|
/**
|
|
187
451
|
* Ticks the player movement for the entity controller,
|
|
188
|
-
* overriding the default implementation.
|
|
452
|
+
* overriding the default implementation. If the entity to tick
|
|
453
|
+
* is a child entity, only the event will be emitted but the default
|
|
454
|
+
* movement logic will not be applied.
|
|
189
455
|
*
|
|
190
456
|
* @param entity - The entity to tick.
|
|
191
457
|
* @param input - The current input state of the player.
|
|
@@ -196,128 +462,209 @@ export default class MyEntityController extends BaseEntityController {
|
|
|
196
462
|
if (!entity.isSpawned || !entity.world) return;
|
|
197
463
|
|
|
198
464
|
super.tickWithPlayerInput(entity, input, cameraOrientation, deltaTimeMs);
|
|
465
|
+
if (entity.parent) return;
|
|
199
466
|
|
|
200
|
-
|
|
467
|
+
// Input and state setup
|
|
468
|
+
const { w, a, s, d, c, sp, sh, ml, jd } = input;
|
|
201
469
|
const { yaw } = cameraOrientation;
|
|
202
470
|
const currentVelocity = entity.linearVelocity;
|
|
203
|
-
const targetVelocities = { x: 0, y: 0, z: 0 };
|
|
204
|
-
const isRunning = sh;
|
|
205
|
-
|
|
206
|
-
// Temporary, animations
|
|
207
|
-
if (this.isGrounded && (w || a || s || d)) {
|
|
208
|
-
if (isRunning) {
|
|
209
|
-
const runAnimations = [ 'run_upper', 'run_lower' ];
|
|
210
|
-
entity.stopModelAnimations(Array.from(entity.modelLoopedAnimations).filter(v => !runAnimations.includes(v)));
|
|
211
|
-
entity.startModelLoopedAnimations(runAnimations);
|
|
212
|
-
this._stepAudio?.setPlaybackRate(0.81);
|
|
213
|
-
} else {
|
|
214
|
-
const walkAnimations = [ 'walk_upper', 'walk_lower' ];
|
|
215
|
-
entity.stopModelAnimations(Array.from(entity.modelLoopedAnimations).filter(v => !walkAnimations.includes(v)));
|
|
216
|
-
entity.startModelLoopedAnimations(walkAnimations);
|
|
217
|
-
this._stepAudio?.setPlaybackRate(0.55);
|
|
218
|
-
}
|
|
219
471
|
|
|
472
|
+
// Reset reusable target velocities
|
|
473
|
+
this._reusableTargetVelocities.x = 0;
|
|
474
|
+
this._reusableTargetVelocities.y = 0;
|
|
475
|
+
this._reusableTargetVelocities.z = 0;
|
|
476
|
+
|
|
477
|
+
const hasJoystickInput = typeof jd === 'number';
|
|
478
|
+
this._isActivelyMoving = hasJoystickInput || !!(w || a || s || d);
|
|
479
|
+
const isFastMovement = sh;
|
|
480
|
+
const hasConflictingInputs = !hasJoystickInput && ((a && d && !w && !s) || (w && s && !a && !d));
|
|
481
|
+
const canMove = (isFastMovement && this.canRun(this)) || (!isFastMovement && this.canWalk(this));
|
|
482
|
+
|
|
483
|
+
// Update swimming state and handle water entry sinking
|
|
484
|
+
if (this.isSwimming && !this._isFullySubmerged) {
|
|
485
|
+
this._isFullySubmerged = true;
|
|
486
|
+
this._justSubmergedUntil = performance.now() + MyEntityController.WATER_ENTRY_SINKING_MS;
|
|
487
|
+
} else if (!this.isSwimming) {
|
|
488
|
+
this._isFullySubmerged = false;
|
|
489
|
+
this._justSubmergedUntil = 0;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Handle movement animations and audio
|
|
493
|
+
if (this.isGrounded && !this.isSwimming && this._isActivelyMoving && !hasConflictingInputs && canMove) {
|
|
494
|
+
// Ground movement animations
|
|
495
|
+
const animations = isFastMovement ? this.runLoopedAnimations : this.walkLoopedAnimations;
|
|
496
|
+
entity.stopAllModelLoopedAnimations(animations);
|
|
497
|
+
entity.startModelLoopedAnimations(animations);
|
|
498
|
+
this._stepAudio?.setPlaybackRate(isFastMovement ? 0.75 : 0.51);
|
|
220
499
|
this._stepAudio?.play(entity.world, !this._stepAudio?.isPlaying);
|
|
500
|
+
} else if (this._isFullySubmerged && this.canSwim(this)) {
|
|
501
|
+
this._stepAudio?.pause();
|
|
502
|
+
if (this._isActivelyMoving) {
|
|
503
|
+
entity.stopAllModelLoopedAnimations(this.swimLoopedAnimations);
|
|
504
|
+
entity.startModelLoopedAnimations(this.swimLoopedAnimations);
|
|
505
|
+
} else {
|
|
506
|
+
entity.stopAllModelLoopedAnimations(this.swimIdleLoopedAnimations);
|
|
507
|
+
entity.startModelLoopedAnimations(this.swimIdleLoopedAnimations);
|
|
508
|
+
}
|
|
221
509
|
} else {
|
|
510
|
+
// Idle animations
|
|
222
511
|
this._stepAudio?.pause();
|
|
223
|
-
|
|
224
|
-
entity.
|
|
225
|
-
entity.startModelLoopedAnimations(idleAnimations);
|
|
512
|
+
entity.stopAllModelLoopedAnimations(this.idleLoopedAnimations);
|
|
513
|
+
entity.startModelLoopedAnimations(this.idleLoopedAnimations);
|
|
226
514
|
}
|
|
227
515
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
516
|
+
// Calculate movement rotation for character facing (avoid string concatenation)
|
|
517
|
+
let movementDiagonalRotation: number | undefined;
|
|
518
|
+
if (this.applyDirectionalMovementRotations && canMove) {
|
|
519
|
+
if (hasJoystickInput) {
|
|
520
|
+
// Joystick: face the exact joystick direction
|
|
521
|
+
movementDiagonalRotation = jd;
|
|
522
|
+
} else {
|
|
523
|
+
// WASD: use discrete directional rotations
|
|
524
|
+
if (w && a && !d && !s) movementDiagonalRotation = MyEntityController.MOVEMENT_ROTATIONS.wa;
|
|
525
|
+
else if (w && d && !a && !s) movementDiagonalRotation = MyEntityController.MOVEMENT_ROTATIONS.wd;
|
|
526
|
+
else if (s && a && !w && !d) movementDiagonalRotation = MyEntityController.MOVEMENT_ROTATIONS.sa;
|
|
527
|
+
else if (s && d && !w && !a) movementDiagonalRotation = MyEntityController.MOVEMENT_ROTATIONS.sd;
|
|
528
|
+
else if ((s && !w && !a && !d) || (a && s && d && !w)) movementDiagonalRotation = MyEntityController.MOVEMENT_ROTATIONS.s;
|
|
529
|
+
else if (a && !w && !s && !d) movementDiagonalRotation = MyEntityController.MOVEMENT_ROTATIONS.a;
|
|
530
|
+
else if (d && !w && !a && !s) movementDiagonalRotation = MyEntityController.MOVEMENT_ROTATIONS.d;
|
|
242
531
|
}
|
|
243
|
-
|
|
244
|
-
input.ml = false;
|
|
245
532
|
}
|
|
246
533
|
|
|
247
|
-
//
|
|
248
|
-
if (
|
|
249
|
-
|
|
534
|
+
// Handle interaction input
|
|
535
|
+
if (ml) {
|
|
536
|
+
entity.startModelOneshotAnimations(this.interactOneshotAnimations);
|
|
537
|
+
input.ml = !this.autoCancelMouseLeftClick;
|
|
538
|
+
}
|
|
250
539
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
540
|
+
// Calculate horizontal movement velocities
|
|
541
|
+
if (canMove) {
|
|
542
|
+
const velocity = !this.isSwimming
|
|
543
|
+
? isFastMovement ? this.runVelocity : this.walkVelocity
|
|
544
|
+
: isFastMovement ? this.swimFastVelocity : this.swimSlowVelocity;
|
|
545
|
+
|
|
546
|
+
if (hasJoystickInput) {
|
|
547
|
+
// Joystick movement: exact direction relative to camera (jd: 0=forward)
|
|
548
|
+
const movementAngle = yaw + jd;
|
|
549
|
+
this._reusableTargetVelocities.x = -velocity * Math.sin(movementAngle);
|
|
550
|
+
this._reusableTargetVelocities.z = -velocity * Math.cos(movementAngle);
|
|
551
|
+
} else {
|
|
552
|
+
// WASD movement: discrete directions relative to camera
|
|
553
|
+
const sinYaw = Math.sin(yaw);
|
|
554
|
+
const cosYaw = Math.cos(yaw);
|
|
555
|
+
|
|
556
|
+
if (w) { this._reusableTargetVelocities.x -= velocity * sinYaw; this._reusableTargetVelocities.z -= velocity * cosYaw; }
|
|
557
|
+
if (s) { this._reusableTargetVelocities.x += velocity * sinYaw; this._reusableTargetVelocities.z += velocity * cosYaw; }
|
|
558
|
+
if (a) { this._reusableTargetVelocities.x -= velocity * cosYaw; this._reusableTargetVelocities.z += velocity * sinYaw; }
|
|
559
|
+
if (d) { this._reusableTargetVelocities.x += velocity * cosYaw; this._reusableTargetVelocities.z -= velocity * sinYaw; }
|
|
560
|
+
|
|
561
|
+
// Normalize diagonal movement to prevent speed boost
|
|
562
|
+
const horizontalSpeed = Math.sqrt(this._reusableTargetVelocities.x * this._reusableTargetVelocities.x + this._reusableTargetVelocities.z * this._reusableTargetVelocities.z);
|
|
563
|
+
if (horizontalSpeed > velocity) {
|
|
564
|
+
const factor = velocity / horizontalSpeed;
|
|
565
|
+
this._reusableTargetVelocities.x *= factor;
|
|
566
|
+
this._reusableTargetVelocities.z *= factor;
|
|
567
|
+
}
|
|
259
568
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Handle swimming physics and vertical movement
|
|
572
|
+
if (this.isSwimming) {
|
|
573
|
+
// Clamp swimming velocities (avoid object spread allocation)
|
|
574
|
+
if (currentVelocity.y < this.swimMaxGravityVelocity) {
|
|
575
|
+
this._reusableVelocityClamp.x = currentVelocity.x;
|
|
576
|
+
this._reusableVelocityClamp.y = this.swimMaxGravityVelocity;
|
|
577
|
+
this._reusableVelocityClamp.z = currentVelocity.z;
|
|
578
|
+
entity.setLinearVelocity(this._reusableVelocityClamp);
|
|
264
579
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
580
|
+
if (currentVelocity.y > this.swimUpwardVelocity * 2) {
|
|
581
|
+
this._reusableVelocityClamp.x = currentVelocity.x;
|
|
582
|
+
this._reusableVelocityClamp.y = this.swimUpwardVelocity * 2;
|
|
583
|
+
this._reusableVelocityClamp.z = currentVelocity.z;
|
|
584
|
+
entity.setLinearVelocity(this._reusableVelocityClamp);
|
|
269
585
|
}
|
|
270
586
|
|
|
271
|
-
//
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
587
|
+
// Handle diving and water entry sinking
|
|
588
|
+
if (c) {
|
|
589
|
+
this._reusableTargetVelocities.y = -this.swimUpwardVelocity;
|
|
590
|
+
} else if (performance.now() < this._justSubmergedUntil) {
|
|
591
|
+
this._reusableTargetVelocities.y = -this.swimUpwardVelocity * MyEntityController.WATER_ENTRY_SINKING_FACTOR;
|
|
592
|
+
} else if (!sp) {
|
|
593
|
+
this._reusableTargetVelocities.y = -currentVelocity.y * MyEntityController.SWIMMING_DRAG_FACTOR;
|
|
277
594
|
}
|
|
278
595
|
}
|
|
279
596
|
|
|
280
|
-
//
|
|
597
|
+
// Handle jumping and swimming upward
|
|
281
598
|
if (sp && this.canJump(this)) {
|
|
282
|
-
if (this.isGrounded && currentVelocity.y > -0.001 && currentVelocity.y <= 3) {
|
|
283
|
-
|
|
599
|
+
if (this.isGrounded && !this.isSwimming && currentVelocity.y > -0.001 && currentVelocity.y <= 3) {
|
|
600
|
+
this._reusableTargetVelocities.y = this.jumpVelocity;
|
|
601
|
+
} else if (this.isSwimming && performance.now() > this._swimUpwardCooldownAt) {
|
|
602
|
+
this._reusableTargetVelocities.y = this.swimUpwardVelocity;
|
|
284
603
|
}
|
|
285
604
|
}
|
|
286
605
|
|
|
287
|
-
// Apply
|
|
288
|
-
const platformVelocity = this._platform
|
|
289
|
-
const deltaVelocities = {
|
|
290
|
-
x: targetVelocities.x - currentVelocity.x + platformVelocity.x,
|
|
291
|
-
y: targetVelocities.y + platformVelocity.y,
|
|
292
|
-
z: targetVelocities.z - currentVelocity.z + platformVelocity.z,
|
|
293
|
-
};
|
|
606
|
+
// Apply physics impulses (avoid platform velocity object allocation)
|
|
607
|
+
const platformVelocity = this._platform?.linearVelocity ?? this._reusablePlatformVelocity;
|
|
294
608
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
609
|
+
if (this._externalVelocity.y !== 0) {
|
|
610
|
+
this._magnitudeYTracker += this._externalVelocity.y;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// Process external impulses if they exist
|
|
614
|
+
if (this._externalVelocity.x !== 0 || this._externalVelocity.y !== 0 || this._externalVelocity.z !== 0) {
|
|
615
|
+
// Only decay horizontal impulses when grounded (physics doesn't decay horizontal velocity in air)
|
|
616
|
+
if (this.isGrounded) {
|
|
617
|
+
// Apply decay to external impulses while preserving direction
|
|
618
|
+
const magnitude = Math.sqrt(
|
|
619
|
+
this._externalVelocity.x * this._externalVelocity.x +
|
|
620
|
+
this._magnitudeYTracker * this._magnitudeYTracker +
|
|
621
|
+
this._externalVelocity.z * this._externalVelocity.z,
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
if (magnitude > 0.01) {
|
|
625
|
+
// Decay the magnitude
|
|
626
|
+
const newMagnitude = Math.max(0, magnitude - MyEntityController.EXTERNAL_IMPULSE_DECAY_RATE);
|
|
627
|
+
const scale = newMagnitude / magnitude;
|
|
628
|
+
|
|
629
|
+
// Apply the scale to preserve direction
|
|
630
|
+
this._externalVelocity.x *= scale;
|
|
631
|
+
this._magnitudeYTracker *= scale; // Also scale the Y tracker
|
|
632
|
+
this._externalVelocity.z *= scale;
|
|
633
|
+
} else {
|
|
634
|
+
// Clear very small values
|
|
635
|
+
this._externalVelocity.x = 0;
|
|
636
|
+
this._externalVelocity.y = 0;
|
|
637
|
+
this._magnitudeYTracker = 0; // Clear the Y tracker
|
|
638
|
+
this._externalVelocity.z = 0;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
299
642
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
643
|
+
// Calculate total target velocity (player input + external + platform)
|
|
644
|
+
const deltaX = this._reusableTargetVelocities.x + this._externalVelocity.x - currentVelocity.x + platformVelocity.x;
|
|
645
|
+
const deltaY = this._reusableTargetVelocities.y + this._externalVelocity.y + platformVelocity.y;
|
|
646
|
+
const deltaZ = this._reusableTargetVelocities.z + this._externalVelocity.z - currentVelocity.z + platformVelocity.z;
|
|
303
647
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
648
|
+
this._externalVelocity.y = 0;
|
|
649
|
+
|
|
650
|
+
if (deltaX !== 0 || deltaY !== 0 || deltaZ !== 0) {
|
|
651
|
+
const mass = entity.mass;
|
|
652
|
+
this._reusableImpulse.x = deltaX * mass;
|
|
653
|
+
this._reusableImpulse.y = deltaY * mass;
|
|
654
|
+
this._reusableImpulse.z = deltaZ * mass;
|
|
655
|
+
this._internalApplyImpulse(this._reusableImpulse);
|
|
310
656
|
}
|
|
311
657
|
|
|
312
|
-
// Apply rotation
|
|
313
|
-
if (yaw !== undefined) {
|
|
314
|
-
const
|
|
658
|
+
// Apply character rotation
|
|
659
|
+
if (yaw !== undefined && (this.faceForwardOnStop || this.isActivelyMoving)) {
|
|
660
|
+
const finalYaw = movementDiagonalRotation !== undefined ? yaw + movementDiagonalRotation : yaw;
|
|
661
|
+
const halfFinalYaw = finalYaw * 0.5;
|
|
315
662
|
|
|
316
663
|
entity.setRotation({
|
|
317
664
|
x: 0,
|
|
318
|
-
y: Math.
|
|
665
|
+
y: Math.sin(halfFinalYaw),
|
|
319
666
|
z: 0,
|
|
320
|
-
w: Math.
|
|
667
|
+
w: Math.cos(halfFinalYaw),
|
|
321
668
|
});
|
|
322
669
|
}
|
|
323
670
|
}
|