@hology/core 0.0.252 → 0.0.254

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/effects/sequence/sequencer.js +1 -1
  2. package/dist/gameplay/actors/actor.d.ts +9 -0
  3. package/dist/gameplay/actors/actor.js +1 -1
  4. package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +2 -0
  5. package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
  6. package/dist/gameplay/actors/controller/actor-controller.d.ts +21 -0
  7. package/dist/gameplay/actors/controller/actor-controller.js +1 -1
  8. package/dist/gameplay/actors/controller/game-state.d.ts +8 -0
  9. package/dist/gameplay/actors/controller/game-state.js +4 -0
  10. package/dist/gameplay/actors/index.d.ts +1 -0
  11. package/dist/gameplay/actors/index.js +1 -1
  12. package/dist/gameplay/game-mode.d.ts +34 -0
  13. package/dist/gameplay/game-mode.js +4 -0
  14. package/dist/gameplay/index.d.ts +8 -1
  15. package/dist/gameplay/index.js +1 -1
  16. package/dist/gameplay/initiate.d.ts +180 -85
  17. package/dist/gameplay/initiate.js +1 -1
  18. package/dist/gameplay/net/browser/index.d.ts +4 -1
  19. package/dist/gameplay/net/browser/index.js +1 -1
  20. package/dist/gameplay/net/index.d.ts +3 -0
  21. package/dist/gameplay/net/index.js +1 -1
  22. package/dist/gameplay/net/net-connection.d.ts +4 -0
  23. package/dist/gameplay/net/net-session.d.ts +3 -0
  24. package/dist/gameplay/net/player-session.d.ts +40 -0
  25. package/dist/gameplay/net/player-session.js +4 -0
  26. package/dist/gameplay/net/service/net-decorator.js +1 -1
  27. package/dist/gameplay/net/service/net-serializer.js +1 -1
  28. package/dist/gameplay/net/service/net-service.d.ts +41 -0
  29. package/dist/gameplay/net/service/net-service.js +1 -1
  30. package/dist/gameplay/network-travel-coordinator.d.ts +27 -0
  31. package/dist/gameplay/network-travel-coordinator.js +4 -0
  32. package/dist/gameplay/player-lifecycle-coordinator.d.ts +29 -0
  33. package/dist/gameplay/player-lifecycle-coordinator.js +4 -0
  34. package/dist/gameplay/player-runtime.d.ts +24 -0
  35. package/dist/gameplay/player-runtime.js +4 -0
  36. package/dist/gameplay/rendering-host.d.ts +40 -0
  37. package/dist/gameplay/rendering-host.js +4 -0
  38. package/dist/gameplay/services/physics/physics-system.js +1 -1
  39. package/dist/gameplay/services/render.d.ts +1 -1
  40. package/dist/gameplay/services/render.js +1 -1
  41. package/dist/gameplay/services/scene-transition.d.ts +19 -0
  42. package/dist/gameplay/services/scene-transition.js +4 -0
  43. package/dist/gameplay/services/world.d.ts +16 -6
  44. package/dist/gameplay/services/world.js +1 -1
  45. package/dist/index.d.ts +1 -0
  46. package/dist/index.js +1 -1
  47. package/dist/rendering/graphics-runtime.d.ts +8 -0
  48. package/dist/rendering/graphics-runtime.js +4 -0
  49. package/dist/rendering/intersection-observer.d.ts +5 -0
  50. package/dist/rendering/intersection-observer.js +4 -0
  51. package/dist/rendering/webgpu-experimental-backend.d.ts +12 -1
  52. package/dist/rendering/webgpu-experimental-backend.js +1 -1
  53. package/dist/rendering.d.ts +18 -3
  54. package/dist/rendering.js +1 -1
  55. package/dist/scene/bootstrap.d.ts +2 -0
  56. package/dist/scene/bootstrap.js +1 -1
  57. package/dist/scene/custom-param-runtime-types.js +1 -1
  58. package/dist/scene/materializer.d.ts +3 -1
  59. package/dist/scene/materializer.js +1 -1
  60. package/dist/scene/model.d.ts +2 -1
  61. package/dist/scene/model.js +1 -1
  62. package/dist/scene/objects/prefab.d.ts +3 -0
  63. package/dist/scene/objects/prefab.js +1 -1
  64. package/dist/scene/scene-ref.d.ts +18 -0
  65. package/dist/scene/scene-ref.js +4 -0
  66. package/dist/shader/parameter.d.ts +2 -1
  67. package/dist/test/graphics-runtime.test.d.ts +2 -0
  68. package/dist/test/graphics-runtime.test.js +4 -0
  69. package/dist/test/intersection-observer.test.d.ts +2 -0
  70. package/dist/test/intersection-observer.test.js +4 -0
  71. package/dist/test/net-player-registry.test.d.ts +2 -0
  72. package/dist/test/net-player-registry.test.js +4 -0
  73. package/dist/test/net-serializer.test.d.ts +2 -0
  74. package/dist/test/net-serializer.test.js +4 -0
  75. package/dist/test/player-controller.test.d.ts +2 -0
  76. package/dist/test/player-controller.test.js +4 -0
  77. package/dist/test/rendering-host.test.d.ts +2 -0
  78. package/dist/test/rendering-host.test.js +4 -0
  79. package/dist/test/world-lifecycle.test.js +1 -1
  80. package/dist/test/world-prefab-spawn.test.js +1 -1
  81. package/package.json +1 -1
  82. package/tsconfig.tsbuildinfo +1 -1
@@ -50,7 +50,8 @@ export declare enum SerializedParamType {
50
50
  Sequence = 28,
51
51
  Struct = 29,
52
52
  DataAsset = 30,
53
- SequenceData = 31
53
+ SequenceData = 31,
54
+ Scene = 32
54
55
  }
55
56
  export type VfxInputBinding = {
56
57
  type: 'vfxInput';
@@ -1,4 +1,4 @@
1
- export var DetailTier;!function(e){e[e.low=0]="low",e[e.medium=1]="medium",e[e.high=2]="high"}(DetailTier||(DetailTier={}));export var SerializedParamType;!function(e){e[e.FloatNode=0]="FloatNode",e[e.Number=1]="Number",e[e.Texture=2]="Texture",e[e.Sampler2DNode=3]="Sampler2DNode",e[e.Boolean=4]="Boolean",e[e.BooleanNode=5]="BooleanNode",e[e.Vector2=6]="Vector2",e[e.Vec2Node=7]="Vec2Node",e[e.Vector3=8]="Vector3",e[e.Vec3Node=9]="Vec3Node",e[e.Color=10]="Color",e[e.RgbNode=11]="RgbNode",e[e.String=12]="String",e[e.BaseActor=13]="BaseActor",e[e.Euler=14]="Euler",e[e.Object3D=15]="Object3D",e[e.Material=16]="Material",e[e.AudioBuffer=17]="AudioBuffer",e[e.Vector4=18]="Vector4",e[e.Vec4Node=19]="Vec4Node",e[e.VisualEffect=20]="VisualEffect",e[e.Array=21]="Array",e[e.Curve=22]="Curve",e[e.ColorLayer=23]="ColorLayer",e[e.MaskLayer=24]="MaskLayer",e[e.Prefab=25]="Prefab",e[e.PrefabActor=26]="PrefabActor",e[e.AnimationClip=27]="AnimationClip",e[e.Sequence=28]="Sequence",e[e.Struct=29]="Struct",e[e.DataAsset=30]="DataAsset",e[e.SequenceData=31]="SequenceData"}(SerializedParamType||(SerializedParamType={}));/*
1
+ export var DetailTier;!function(e){e[e.low=0]="low",e[e.medium=1]="medium",e[e.high=2]="high"}(DetailTier||(DetailTier={}));export var SerializedParamType;!function(e){e[e.FloatNode=0]="FloatNode",e[e.Number=1]="Number",e[e.Texture=2]="Texture",e[e.Sampler2DNode=3]="Sampler2DNode",e[e.Boolean=4]="Boolean",e[e.BooleanNode=5]="BooleanNode",e[e.Vector2=6]="Vector2",e[e.Vec2Node=7]="Vec2Node",e[e.Vector3=8]="Vector3",e[e.Vec3Node=9]="Vec3Node",e[e.Color=10]="Color",e[e.RgbNode=11]="RgbNode",e[e.String=12]="String",e[e.BaseActor=13]="BaseActor",e[e.Euler=14]="Euler",e[e.Object3D=15]="Object3D",e[e.Material=16]="Material",e[e.AudioBuffer=17]="AudioBuffer",e[e.Vector4=18]="Vector4",e[e.Vec4Node=19]="Vec4Node",e[e.VisualEffect=20]="VisualEffect",e[e.Array=21]="Array",e[e.Curve=22]="Curve",e[e.ColorLayer=23]="ColorLayer",e[e.MaskLayer=24]="MaskLayer",e[e.Prefab=25]="Prefab",e[e.PrefabActor=26]="PrefabActor",e[e.AnimationClip=27]="AnimationClip",e[e.Sequence=28]="Sequence",e[e.Struct=29]="Struct",e[e.DataAsset=30]="DataAsset",e[e.SequenceData=31]="SequenceData",e[e.Scene=32]="Scene"}(SerializedParamType||(SerializedParamType={}));/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,6 +1,7 @@
1
1
  import type { Object3D } from "three";
2
2
  import type { BaseActor } from "../../gameplay/actors/actor.js";
3
3
  import type { Asset } from "../model.js";
4
+ import { ActorLifetime } from "../../gameplay/actors/actor.js";
4
5
  export declare class Prefab {
5
6
  asset: Asset;
6
7
  }
@@ -8,6 +9,8 @@ export declare class PrefabInstance {
8
9
  object: Object3D;
9
10
  actors: BaseActor[];
10
11
  mainActor: BaseActor | null;
12
+ /** All actors in a runtime prefab travel and are destroyed as one lifetime unit. */
13
+ lifetime: ActorLifetime;
11
14
  }
12
15
  export declare class PrefabOf<T extends BaseActor> {
13
16
  readonly prefab: Prefab;
@@ -1,4 +1,4 @@
1
- export class Prefab{constructor(s){this.asset=s}}export class PrefabInstance{constructor(){this.destroyed=!1}}export class PrefabOf{constructor(s){this.prefab=s}}/*
1
+ import{ActorLifetime as s}from"../../gameplay/actors/actor.js";export class Prefab{constructor(s){this.asset=s}}export class PrefabInstance{constructor(){this.lifetime=s.scene,this.destroyed=!1}}export class PrefabOf{constructor(s){this.prefab=s}}/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -0,0 +1,18 @@
1
+ declare const sceneIdBrand: unique symbol;
2
+ /** Stable identity of a project scene. */
3
+ export type SceneId = string & {
4
+ readonly [sceneIdBrand]: true;
5
+ };
6
+ export declare function sceneId(value: string): SceneId;
7
+ /**
8
+ * An immutable, serializable reference to a project scene.
9
+ * `id` is authoritative; `name` is only a human-readable snapshot.
10
+ */
11
+ export declare class SceneRef {
12
+ readonly id: SceneId;
13
+ readonly name?: string;
14
+ constructor(id: string, name?: string);
15
+ toString(): string;
16
+ }
17
+ export {};
18
+ //# sourceMappingURL=scene-ref.d.ts.map
@@ -0,0 +1,4 @@
1
+ export function sceneId(e){return e}export class SceneRef{constructor(e,t){this.id=sceneId(e),this.name=t}toString(){return this.name||this.id}}/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -6,11 +6,12 @@ import type { BooleanNode, FloatNode, RgbNode, Sampler2DNode, Vec2Node, Vec3Node
6
6
  import type { VisualEffect } from '../effects/vfx/vfx-param.js';
7
7
  import type { Prefab, PrefabOf } from '../scene/objects/prefab.js';
8
8
  import type { DataAssetRef } from '../scene/objects/data-asset.js';
9
+ import type { SceneRef } from '../scene/scene-ref.js';
9
10
  import type { Curve2 } from '../utils/curve.js';
10
11
  import type { ColorLayer, MaskLayer } from './color-layer.js';
11
12
  import type { Sequence } from '../effects/sequence/sequence-data.js';
12
13
  import type { ShaderGraphTarget } from './graph/model.js';
13
- export type KnownParameterType = Type<FloatNode | Number | Texture | Sampler2DNode | Boolean | BooleanNode | Vector2 | Vec2Node | Vector3 | Vec3Node | Vector4 | Vec4Node | Color | RgbNode | String | BaseActor | Euler | Object3D | Material | AnimationClip | VisualEffect | Sequence | Prefab | PrefabOf<BaseActor> | DataAssetRef | Curve2 | ColorLayer | MaskLayer>;
14
+ export type KnownParameterType = Type<FloatNode | Number | Texture | Sampler2DNode | Boolean | BooleanNode | Vector2 | Vec2Node | Vector3 | Vec3Node | Vector4 | Vec4Node | Color | RgbNode | String | BaseActor | Euler | Object3D | Material | AnimationClip | VisualEffect | Sequence | Prefab | PrefabOf<BaseActor> | DataAssetRef | SceneRef | Curve2 | ColorLayer | MaskLayer>;
14
15
  export type ParameterType = Type<any> | AbstractType<any>;
15
16
  export type ParameterTypeResolver = () => ParameterType;
16
17
  export type ParameterOption<T> = {
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=graphics-runtime.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{describe as e,expect as a,it as t,vi as i}from"vitest";import{GraphicsRuntime as n}from"../rendering/graphics-runtime.js";e("GraphicsRuntime",()=>{t("shares a backend until the final view releases it",async()=>{const e=new n,t={id:1},l=i.fn(async()=>t),r=i.fn(),s=await e.acquire("webgpu","default",l),u=await e.acquire("webgpu","default",l);a(s).toBe(t),a(u).toBe(t),a(l).toHaveBeenCalledOnce(),e.release("webgpu","default",r),a(r).not.toHaveBeenCalled(),e.release("webgpu","default",r),a(r).toHaveBeenCalledWith(t)})});/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=intersection-observer.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{afterEach as e,describe as t,expect as n,it as o,vi as s}from"vitest";async function i(){let e;const t=s.fn(),n=s.fn();s.stubGlobal("IntersectionObserver",class{constructor(o){this.observe=t,this.unobserve=n,e=o}});const{observeElementIntersection:o}=await import("../rendering/intersection-observer.js");return{observeElementIntersection:o,observe:t,unobserve:n,notify:(t,n)=>e([{target:t,isIntersecting:n}],{})}}e(()=>{s.unstubAllGlobals(),s.resetModules()}),t("shared container visibility",()=>{o("passes existing visibility to a new view without another observer notification",async()=>{const e=await i(),t=document.createElement("div"),o=s.fn(),r=s.fn();e.observeElementIntersection(t,o),e.notify(t,!0),e.observeElementIntersection(t,r),n(r).toHaveBeenLastCalledWith(!0),n(e.observe).toHaveBeenCalledTimes(1),e.notify(t,!1),n(o).toHaveBeenLastCalledWith(!1),n(r).toHaveBeenLastCalledWith(!1)}),o("keeps observing a replacement view when the old view finishes shutting down",async()=>{const e=await i(),t=document.createElement("div"),o=s.fn(),r=s.fn(),a=e.observeElementIntersection(t,o),l=e.observeElementIntersection(t,r);a(),n(e.unobserve).not.toHaveBeenCalled(),e.notify(t,!0),n(o).not.toHaveBeenCalled(),n(r).toHaveBeenCalledWith(!0),l(),n(e.unobserve).toHaveBeenCalledTimes(1),e.observeElementIntersection(t,s.fn()),a(),l(),n(e.unobserve).toHaveBeenCalledTimes(1),n(e.observe).toHaveBeenCalledTimes(2)}),o("allows rendering in hosts without IntersectionObserver",async()=>{s.stubGlobal("IntersectionObserver",void 0);const{observeElementIntersection:e}=await import("../rendering/intersection-observer.js"),t=s.fn(),o=e(document.createElement("div"),t);n(t).toHaveBeenCalledWith(!0),n(()=>o()).not.toThrow()})});/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=net-player-registry.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{Subject as e}from"rxjs";import{describe as t,expect as n,it as a}from"vitest";import{NetPlayerRegistry as o}from"../gameplay/net/player-session.js";import{NetMode as r}from"../gameplay/net/net-session.js";function s(e,t){return{id:e,player:{id:t}}}function l(e,t,n,a,o){return{id:"test",mode:e,clients:t,localPlayer:o,playerJoined:n,playerLeft:a,server:null,reconnect(){},disconnect(){},sendMessage(){},hasMessage:()=>0,readMessage:()=>null}}t("NetPlayerRegistry",()=>{a("uses NetPlayerInfo.id as stable identity across connection replacement",()=>{const t=new e,a=new e,c=s(10,"player-a"),i=l(r.dedicatedServer,[c],t,a),d=new o;d.start(i);const p=d.get("player-a");p.controller={},a.next(c),n(p.status).toBe("disconnected");const y=s(99,"player-a");t.next(y),n(d.get("player-a")).toBe(p),n(p.connection).toBe(y),n(p.controller).toBeDefined(),n(p.status).toBe("active")}),a("registers a listen server local player without a transport connection",()=>{const t=new e,a=new e,s=l(r.listenServer,[],t,a,{id:"host"}),c=new o;c.start(s),n(c.get("host")).toMatchObject({connection:void 0,localPlayerIndex:0,status:"joining"})}),a("registers a standalone local player for the GameMode lifecycle",()=>{const t=new o;t.start(l(r.none,[],new e,new e,{id:"single-player"})),n(t.values).toHaveLength(1),n(t.get("single-player")).toMatchObject({localPlayerIndex:0,status:"joining"})}),a("adopts a player state replicated with a controller",()=>{const t=new e,a=new e,s=new o;s.start(l(r.client,[],t,a,{id:"local"}));const c={},i={playerState:c};s.attachController("local",i),n(s.get("local")?.playerState).toBe(c),n(i.playerState).toBe(c)})});/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=net-serializer.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{expect as e,test as s,vi as o}from"vitest";o.mock("../gameplay/services/world.js",()=>({World:class{}})),o.mock("../gameplay/services/asset-loader.js",()=>({AssetLoader:class{}})),o.mock("../gameplay/actors/actor.js",()=>({BaseActor:class{}})),o.mock("../scene/objects/data-asset.js",()=>({DataAssetRef:class{}}));import{DecodeResult as a,NetSerializer as r}from"../gameplay/net/service/net-serializer.js";s("net serializer preserves undefined values",()=>{const s=Object.create(r.prototype),o=new a,t=s.encode({owner:void 0}),c=s.decode(t,o);e(t).not.toBe(""),e(Object.hasOwn(c,"owner")).toBe(!0),e(c.owner).toBeUndefined(),e(o.error).toBe(!1)});/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=player-controller.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{__decorate as s}from"tslib";import{expect as o,test as e,vi as l}from"vitest";l.mock("../gameplay/services/render.js",()=>({ViewController:class{}}));import{Actor as t,ActorLifetime as a,BaseActor as c,getActorOptions as r}from"../gameplay/actors/actor.js";import{BasePlayerController as n}from"../gameplay/actors/controller/actor-controller.js";e("becoming locally controlled after possession activates local possession once",()=>{const s=new p,e=new i;s.possess(e),o(s.localPossessions).toBe(0),s.setLocallyControlled(!0),s.setLocallyControlled(!0),o(s.localPossessions).toBe(1),s.setLocallyControlled(!1),o(s.localUnpossessions).toBe(1)}),e("player controller subclasses inherit required actor options",()=>{o(r(p)).toMatchObject({lifetime:a.game,replicate:!0,relevancy:{ownerOnly:!0}})}),e("actor decorator merges subclass options with inherited options",()=>{o(r(m)).toMatchObject({lifetime:a.game,replicate:!0,relevancy:{ownerOnly:!0},spatial:!1})});class i extends c{}class p extends n{constructor(){super(...arguments),this.localPossessions=0,this.localUnpossessions=0}onLocalPossess(){this.localPossessions++}onLocalUnpossess(){this.localUnpossessions++}}let m=class extends n{};m=s([t({spatial:!1})],m);/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rendering-host.test.d.ts.map
@@ -0,0 +1,4 @@
1
+ import{describe as e,expect as t,it as n,vi as a}from"vitest";import{RenderingHost as s}from"../gameplay/rendering-host.js";function o(){let e;return{simulationTime:12,webGpuDevice:{label:"device"},loop:a.fn(e=>e(.25)),stop:a.fn(),stopAnimationLoop:a.fn(),suspendPresentation:a.fn(),activatePresentation:a.fn(),registerWebGpuPresentationExtension:a.fn(t=>(e=t,a.fn())),get extension(){return e}}}e("RenderingHost",()=>{n("owns frame scheduling and preserves a caller-owned view on shutdown",()=>{const e=o(),n=new s(e,!1,()=>o()),i=a.fn();n.start(i),n.shutdown(),n.shutdown(),t(i).toHaveBeenCalledWith(.25),t(e.suspendPresentation).toHaveBeenCalledOnce(),t(e.stop).not.toHaveBeenCalled()}),n("disposes a host-owned view",()=>{const e=o();new s(e,!0,()=>o()).shutdown(),t(e.stop).toHaveBeenCalledOnce()}),n("creates and switches distinct scene views",()=>{const e=o(),n=o(),a=new s(e,!1,()=>n);a.start(()=>{});const i=a.createView();t(i).toBe(n),t(n.suspendPresentation).toHaveBeenCalledOnce(),a.activate(i),t(e.suspendPresentation).toHaveBeenCalledOnce(),t(n.activatePresentation).toHaveBeenCalledOnce(),a.activate(e),a.releaseView(i),t(n.stop).toHaveBeenCalledOnce()}),n("adds a persistent native-resolution presentation pass with frame timing",()=>{const e=o(),n=new s(e,!1,()=>o());n.start(()=>{});const i=a.fn();n.registerStage(i);const r={},d={device:{},encoder:{},targetView:r,targetFormat:"bgra8unorm",presentationWidth:1920,presentationHeight:1080};e.extension(d),t(i).toHaveBeenCalledWith(t.objectContaining({deltaTime:.25,elapsedTime:12,targetView:r,targetFormat:"bgra8unorm",presentationWidth:1920}))})});/*
2
+ * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
+ * See the LICENSE.md file for details.
4
+ */
@@ -1,4 +1,4 @@
1
- import{__decorate as t}from"tslib";import"reflect-metadata";import{expect as e,test as o,vi as n}from"vitest";n.mock("../gameplay/services/render.js",()=>({ViewController:class{}})),n.mock("../gameplay/services/physics/physics-system.js",()=>({PhysicsSystem:class{}})),n.mock("../rendering.js",()=>({RenderingView:class{}}));import{Scene as i}from"three";import{Subject as r}from"rxjs";import{Container as s}from"typedi";import{Actor as d,BaseActor as a}from"../gameplay/actors/actor.js";import{ActorComponent as c,Component as l}from"../gameplay/actors/component.js";import{ActorFactory as m}from"../gameplay/actors/factory.js";import{World as y}from"../gameplay/services/world.js";function u(t){const e=Object.create(y.prototype);return e.actorFactory=t,e.physics={removeActor(){}},e.actors=[],e.actorAdded=new r,e.actorRemoved=new r,e.scene=new i,e}o("world begin and end play skip runtime-only components in editor",async()=>{const t=new m(s.of("world-lifecycle-editor"),{inEditor:!0}),o=await t.create(p),n=u(t);n.addActor(o),n.removeActor(o),e(o.beginCount).toBe(1),e(o.endCount).toBe(1),e(o.runtimeOnly.beginCount).toBe(0),e(o.runtimeOnly.endCount).toBe(0),e(o.runtimeOnly.actor).toBeUndefined(),e(o.inEditor.beginCount).toBe(1),e(o.inEditor.endCount).toBe(1),e(o.inEditor.actor).toBe(o),e(o.editorOnly.beginCount).toBe(1),e(o.editorOnly.endCount).toBe(1),e(o.editorOnly.actor).toBe(o)}),o("world begin and end play skip editor-only components at runtime",async()=>{const t=new m(s.of("world-lifecycle-runtime"),{inEditor:!1}),o=await t.create(p),n=u(t);n.addActor(o),n.removeActor(o),e(o.beginCount).toBe(1),e(o.endCount).toBe(1),e(o.runtimeOnly.beginCount).toBe(1),e(o.runtimeOnly.endCount).toBe(1),e(o.runtimeOnly.actor).toBe(o),e(o.inEditor.beginCount).toBe(1),e(o.inEditor.endCount).toBe(1),e(o.inEditor.actor).toBe(o),e(o.editorOnly.beginCount).toBe(0),e(o.editorOnly.endCount).toBe(0),e(o.editorOnly.actor).toBeUndefined()});let p=class extends a{constructor(){super(...arguments),this.beginCount=0,this.endCount=0,this.runtimeOnly=this.attach(g),this.inEditor=this.attach(B),this.editorOnly=this.attach(h)}onBeginPlay(){this.beginCount++}onEndPlay(){this.endCount++}};p=t([d()],p);class C extends c{constructor(){super(...arguments),this.beginCount=0,this.endCount=0}onBeginPlay(){this.beginCount++}onEndPlay(){this.endCount++}}let g=class extends C{};g=t([l()],g);let B=class extends C{};B=t([l({inEditor:!0})],B);let h=class extends C{};h=t([l({inEditor:!0,editorOnly:!0})],h);/*
1
+ import{__decorate as t}from"tslib";import"reflect-metadata";import{expect as e,test as n,vi as o}from"vitest";o.mock("../gameplay/services/render.js",()=>({ViewController:class{}})),o.mock("../gameplay/services/physics/physics-system.js",()=>({PhysicsSystem:class{}})),o.mock("../rendering.js",()=>({RenderingView:class{}}));import{Scene as r}from"three";import{Subject as i}from"rxjs";import{Container as s}from"typedi";import{Actor as a,BaseActor as c}from"../gameplay/actors/actor.js";import{ActorComponent as d,Component as l}from"../gameplay/actors/component.js";import{ActorFactory as m}from"../gameplay/actors/factory.js";import{World as y}from"../gameplay/services/world.js";function u(t){const e=Object.create(y.prototype);return e.actorFactory=t,e.physics={removeActor(){}},e.actors=[],e.actorLifetimes=new Map,e.actorPrefabInstances=new Map,e.prefabInstances=new Set,e.sceneEventGraphs=new Map,e.sceneEventGraphSubscriptions=[],e.actorAdded=new i,e.actorRemoved=new i,e.scene=new r,e}n("world begin and end play skip runtime-only components in editor",async()=>{const t=new m(s.of("world-lifecycle-editor"),{inEditor:!0}),n=await t.create(p),o=u(t);o.addActor(n),o.removeActor(n),e(n.beginCount).toBe(1),e(n.endCount).toBe(1),e(n.runtimeOnly.beginCount).toBe(0),e(n.runtimeOnly.endCount).toBe(0),e(n.runtimeOnly.actor).toBeUndefined(),e(n.inEditor.beginCount).toBe(1),e(n.inEditor.endCount).toBe(1),e(n.inEditor.actor).toBe(n),e(n.editorOnly.beginCount).toBe(1),e(n.editorOnly.endCount).toBe(1),e(n.editorOnly.actor).toBe(n)}),n("world begin and end play skip editor-only components at runtime",async()=>{const t=new m(s.of("world-lifecycle-runtime"),{inEditor:!1}),n=await t.create(p),o=u(t);o.addActor(n),o.removeActor(n),e(n.beginCount).toBe(1),e(n.endCount).toBe(1),e(n.runtimeOnly.beginCount).toBe(1),e(n.runtimeOnly.endCount).toBe(1),e(n.runtimeOnly.actor).toBe(n),e(n.inEditor.beginCount).toBe(1),e(n.inEditor.endCount).toBe(1),e(n.inEditor.actor).toBe(n),e(n.editorOnly.beginCount).toBe(0),e(n.editorOnly.endCount).toBe(0),e(n.editorOnly.actor).toBeUndefined()});let p=class extends c{constructor(){super(...arguments),this.beginCount=0,this.endCount=0,this.runtimeOnly=this.attach(g),this.inEditor=this.attach(h),this.editorOnly=this.attach(B)}onBeginPlay(){this.beginCount++}onEndPlay(){this.endCount++}};p=t([a()],p);class C extends d{constructor(){super(...arguments),this.beginCount=0,this.endCount=0}onBeginPlay(){this.beginCount++}onEndPlay(){this.endCount++}}let g=class extends C{};g=t([l()],g);let h=class extends C{};h=t([l({inEditor:!0})],h);let B=class extends C{};B=t([l({inEditor:!0,editorOnly:!0})],B);/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
@@ -1,4 +1,4 @@
1
- import{describe as e,expect as t,test as n,vi as o}from"vitest";import{Euler as a,Group as s,Scene as r,Vector3 as i}from"three";o.hoisted(()=>{if("undefined"==typeof HTMLCanvasElement)return;const e=new Proxy({},{get:(e,t)=>(t in e||(e[t]=o.fn()),e[t]),set:(e,t,n)=>(e[t]=n,!0)});Object.defineProperty(HTMLCanvasElement.prototype,"getContext",{configurable:!0,value:()=>e})}),o.mock("../rendering.js",()=>({RenderingView:class{}})),o.mock("../gameplay/services/physics/physics-system.js",()=>({PhysicsSystem:class{}}));import{World as c}from"../gameplay/services/world.js";e("World.spawnPrefab",()=>{n("makes the requested transform available while prefab actors initialize",async()=>{const e=new r,n=new r,p=new s;p.position.set(1,0,0);const d=new s;let f,l=n;const m={id:"prefab-a",type:"prefab",prefab:{objects:[]},revision:2},y={inEditor:!0,setScene:o.fn(e=>{l=e}),createFromPrefabAsset:o.fn(async(e,t,n)=>(n.add(d),d.add(p),y.inEditor||l.attach(p),f=p.position.clone(),{object:d,actors:[],mainActor:null,instanceId:"runtime-instance"})),unregisterLivePrefabInstance:o.fn()},b=Object.create(c.prototype);b.scene=e,b.materializer=y,b.actorFactory={inEditor:!1},b.physics={addFromScene:o.fn(),removeRemoved:o.fn()},b.assetsProvider={getAsset:o.fn(async()=>m)};const v=new i(10,2,5),w=new a(0,Math.PI/2,0),h=new s,u=new s;h.position.copy(v),h.rotation.copy(w),u.position.set(1,0,0),h.add(u),h.updateWorldMatrix(!0,!0);const P=u.getWorldPosition(new i),g=await b.spawnPrefab({asset:{id:"prefab-a",type:"prefab",prefab:{objects:[]}}},v,w);t(f).toEqual(P),t(y.setScene).toHaveBeenCalledWith(e),t(y.inEditor).toBe(!1),t(p.parent).toBe(e),t(g?.object.parent).toBe(e),t(g?.object.position).toEqual(v),t(g?.object.rotation.y).toBeCloseTo(w.y),t(y.createFromPrefabAsset).toHaveBeenCalledWith(m,t.anything(),t.any(s),void 0,!1),b.removePrefab(g),t(y.unregisterLivePrefabInstance).toHaveBeenCalledWith("runtime-instance")})});/*
1
+ import{describe as e,expect as t,test as n,vi as o}from"vitest";import{Euler as a,Group as r,Scene as s,Vector3 as c}from"three";import{Subject as i}from"rxjs";o.hoisted(()=>{if("undefined"==typeof HTMLCanvasElement)return;const e=new Proxy({},{get:(e,t)=>(t in e||(e[t]=o.fn()),e[t]),set:(e,t,n)=>(e[t]=n,!0)});Object.defineProperty(HTMLCanvasElement.prototype,"getContext",{configurable:!0,value:()=>e})}),o.mock("../rendering.js",()=>({RenderingView:class{}})),o.mock("../gameplay/services/physics/physics-system.js",()=>({PhysicsSystem:class{}}));import{World as d}from"../gameplay/services/world.js";import{ActorLifetime as p}from"../gameplay/actors/actor.js";e("World.spawnPrefab",()=>{n("makes the requested transform available while prefab actors initialize",async()=>{const e=new s,n=new s,f=new r;f.position.set(1,0,0);const m={object:f,disposed:new i,attachedComponents:[],onBeginPlay:o.fn(),onEndPlay:o.fn(),constructor:Object},l=new r;let w,y=n;const b={id:"prefab-a",type:"prefab",prefab:{objects:[]},revision:2},v={inEditor:!0,setScene:o.fn(e=>{y=e}),createFromPrefabAsset:o.fn(async(e,t,n)=>(n.add(l),l.add(f),v.inEditor||y.attach(f),w=f.position.clone(),{object:l,actors:[m],mainActor:m,instanceId:"runtime-instance"})),unregisterLivePrefabInstance:o.fn()},j=Object.create(d.prototype);j.scene=e,j.materializer=v,j.actorFactory={inEditor:!1},j.physics={addFromScene:o.fn(),removeRemoved:o.fn(),removeActor:o.fn()},j.assetsProvider={getAsset:o.fn(async()=>b)},j.actorLifetimes=new Map,j.actorPrefabInstances=new Map,j.prefabInstances=new Set,j.sceneEventGraphs=new Map,j.actorAdded=new i,j.actorRemoved=new i,j.actors=[];const P=new c(10,2,5),g=new a(0,Math.PI/2,0),h=new r,B=new r;h.position.copy(P),h.rotation.copy(g),B.position.set(1,0,0),h.add(B),h.updateWorldMatrix(!0,!0);const u=B.getWorldPosition(new c),E=await j.spawnPrefab({asset:{id:"prefab-a",type:"prefab",prefab:{objects:[]}}},P,g);t(w).toEqual(u),t(v.setScene).toHaveBeenCalledWith(e),t(v.inEditor).toBe(!1),t(f.parent).toBe(e),t(E?.object.parent).toBe(e),t(E?.object.position).toEqual(P),t(E?.object.rotation.y).toBeCloseTo(g.y),t(E?.lifetime).toBe(p.scene),t(j.getActorLifetime(m)).toBe(E?.lifetime),t(v.createFromPrefabAsset).toHaveBeenCalledWith(b,t.anything(),t.any(r),void 0,!1),j.removePrefab(E),t(v.unregisterLivePrefabInstance).toHaveBeenCalledWith("runtime-instance")})}),n("scene cleanup uses explicit actor lifetime instead of spawn origin",()=>{const e=Object.create(d.prototype);e.scene=new s,e.actors=[],e.actorLifetimes=new Map,e.actorPrefabInstances=new Map,e.prefabInstances=new Set,e.sceneEventGraphs=new Map,e.physics={removeActor:o.fn()},e.actorFactory={inEditor:!1},e.actorAdded=new i,e.actorRemoved=new i;const n=new r;e.scene.add(n);const a=()=>({object:new r,disposed:new i,attachedComponents:[],onBeginPlay:o.fn(),onEndPlay:o.fn(),constructor:Object}),c=a(),f=a();n.add(c.object,f.object),e.addActor(c),e.addActor(f,void 0,void 0,p.game);const m=e.removeSceneLifetimeActors([n]);t(e.actors).toEqual([f]),t(m.has(f)).toBe(!0),t(f.object.parent).toBe(e.scene),t(c.onEndPlay).toHaveBeenCalledOnce(),t(f.onEndPlay).not.toHaveBeenCalled()}),n("spawnActorSync applies explicit owner and lifetime",()=>{const e=Object.create(d.prototype),n={id:1},a={object:new r,disposed:new i,attachedComponents:[],onBeginPlay:o.fn(),onEndPlay:o.fn(),constructor:Object};e.actorFactory={inEditor:!1,createSync:o.fn(()=>a)},e.actors=[],e.actorLifetimes=new Map,e.actorPrefabInstances=new Map,e.actorAdded=new i,e.scene=new s;const c=e.spawnActorSync(Object,void 0,void 0,{owner:n,lifetime:p.game});t(c).toBe(a),t(a.owner).toBe(n),t(e.getActorLifetime(a)).toBe(p.game)});/*
2
2
  * Copyright (©) 2026 Hology Interactive AB. All rights reserved.
3
3
  * See the LICENSE.md file for details.
4
4
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hology/core",
3
- "version": "0.0.252",
3
+ "version": "0.0.254",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",