@hology/core 0.0.211 → 0.0.213
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/effects/sequence/index.d.ts +1 -0
- package/dist/effects/sequence/index.js +1 -1
- package/dist/effects/sequence/sequence-action.d.ts +5 -0
- package/dist/effects/sequence/sequence-actor.d.ts +7 -0
- package/dist/effects/sequence/sequence-actor.js +1 -1
- package/dist/effects/sequence/sequence-animation-retiming.js +1 -1
- package/dist/effects/sequence/sequence-data.d.ts +9 -0
- package/dist/effects/sequence/sequence-data.js +1 -1
- package/dist/effects/sequence/sequence-player.d.ts +12 -1
- package/dist/effects/sequence/sequence-player.js +1 -1
- package/dist/effects/sequence/sequence-transform.d.ts +10 -0
- package/dist/effects/sequence/sequence-transform.js +4 -0
- package/dist/effects/sequence/sequence-value-lane.d.ts +2 -0
- package/dist/effects/sequence/sequence-value-lane.js +1 -1
- package/dist/effects/vfx/initializsers.d.ts +8 -1
- package/dist/effects/vfx/initializsers.js +1 -1
- package/dist/effects/vfx/vfx-actor.d.ts +5 -0
- package/dist/effects/vfx/vfx-actor.js +1 -1
- package/dist/effects/vfx/vfx-asset.d.ts +2 -1
- package/dist/effects/vfx/vfx-asset.js +1 -1
- package/dist/effects/vfx/vfx-collision-behaviour.js +1 -1
- package/dist/effects/vfx/vfx-defs.d.ts +10 -1
- package/dist/effects/vfx/vfx-defs.js +1 -1
- package/dist/effects/vfx/vfx-materializer.js +1 -1
- package/dist/effects/vfx/vfx-renderers.d.ts +2 -0
- package/dist/effects/vfx/vfx-renderers.js +1 -1
- package/dist/gameplay/actors/actor.d.ts +21 -1
- package/dist/gameplay/actors/actor.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-animation.d.ts +3 -0
- package/dist/gameplay/actors/builtin/components/character/character-animation.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/character-movement-like.d.ts +25 -0
- package/dist/gameplay/actors/builtin/components/character/character-movement-like.js +4 -0
- package/dist/gameplay/actors/builtin/components/character/character-movement-policy.d.ts +26 -0
- package/dist/gameplay/actors/builtin/components/character/character-movement-policy.js +4 -0
- package/dist/gameplay/actors/builtin/components/character/character-movement.d.ts +158 -55
- package/dist/gameplay/actors/builtin/components/character/character-movement.js +1 -1
- package/dist/gameplay/actors/builtin/components/character/net-character-movement-protocol.d.ts +128 -0
- package/dist/gameplay/actors/builtin/components/character/net-character-movement-protocol.js +4 -0
- package/dist/gameplay/actors/builtin/components/character/old-character-movement.d.ts +100 -0
- package/dist/gameplay/actors/builtin/components/character/old-character-movement.js +4 -0
- package/dist/gameplay/actors/builtin/components/index.d.ts +2 -0
- package/dist/gameplay/actors/builtin/components/index.js +1 -1
- package/dist/gameplay/actors/builtin/components/mesh-component.d.ts +1 -0
- package/dist/gameplay/actors/builtin/components/mesh-component.js +1 -1
- package/dist/gameplay/actors/builtin/components/tween-component.js +1 -1
- package/dist/gameplay/actors/builtin/navmesh-actor.d.ts +2 -0
- package/dist/gameplay/actors/builtin/navmesh-actor.js +1 -1
- package/dist/gameplay/actors/builtin/trigger-volume.d.ts +3 -3
- package/dist/gameplay/actors/builtin/trigger-volume.js +1 -1
- package/dist/gameplay/actors/camera/camera-component.d.ts +1 -3
- package/dist/gameplay/actors/camera/camera-component.js +1 -1
- package/dist/gameplay/actors/camera/third-person-camera-component.d.ts +3 -0
- package/dist/gameplay/actors/camera/third-person-camera-component.js +1 -1
- package/dist/gameplay/actors/component.d.ts +3 -0
- package/dist/gameplay/actors/component.js +1 -1
- package/dist/gameplay/actors/controller/actor-controller.d.ts +16 -0
- package/dist/gameplay/actors/controller/actor-controller.js +4 -0
- package/dist/gameplay/actors/factory.d.ts +3 -0
- package/dist/gameplay/actors/factory.js +1 -1
- package/dist/gameplay/actors/index.d.ts +4 -0
- package/dist/gameplay/actors/index.js +1 -1
- package/dist/gameplay/actors/internal/component-init.js +1 -1
- package/dist/gameplay/actors/type-registry.d.ts +10 -0
- package/dist/gameplay/actors/type-registry.js +4 -0
- package/dist/gameplay/ai/behavior-tree/move.d.ts +2 -2
- package/dist/gameplay/animation/retarget.d.ts +50 -0
- package/dist/gameplay/animation/retarget.js +4 -0
- package/dist/gameplay/animation/root-motion.js +1 -1
- package/dist/gameplay/event-graph/actor-transform-properties.d.ts +6 -0
- package/dist/gameplay/event-graph/actor-transform-properties.js +4 -0
- package/dist/gameplay/event-graph/asset-actor-types.d.ts +3 -0
- package/dist/gameplay/event-graph/asset-actor-types.js +4 -0
- package/dist/gameplay/event-graph/asset-references.d.ts +12 -0
- package/dist/gameplay/event-graph/asset-references.js +4 -0
- package/dist/gameplay/event-graph/compiler.d.ts +107 -0
- package/dist/gameplay/event-graph/compiler.js +4 -0
- package/dist/gameplay/event-graph/decorators.d.ts +74 -0
- package/dist/gameplay/event-graph/decorators.js +4 -0
- package/dist/gameplay/event-graph/document-compiler.d.ts +107 -0
- package/dist/gameplay/event-graph/document-compiler.js +4 -0
- package/dist/gameplay/event-graph/event-graph-demo.d.ts +2 -0
- package/dist/gameplay/event-graph/event-graph-demo.js +4 -0
- package/dist/gameplay/event-graph/graph.d.ts +106 -0
- package/dist/gameplay/event-graph/graph.js +4 -0
- package/dist/gameplay/event-graph/index.d.ts +13 -0
- package/dist/gameplay/event-graph/index.js +4 -0
- package/dist/gameplay/event-graph/model.d.ts +71 -0
- package/dist/gameplay/event-graph/model.js +4 -0
- package/dist/gameplay/event-graph/nodes/execution-nodes.d.ts +115 -0
- package/dist/gameplay/event-graph/nodes/execution-nodes.js +4 -0
- package/dist/gameplay/event-graph/nodes/gameplay-nodes.d.ts +208 -0
- package/dist/gameplay/event-graph/nodes/gameplay-nodes.js +4 -0
- package/dist/gameplay/event-graph/nodes/index.d.ts +4 -0
- package/dist/gameplay/event-graph/nodes/index.js +4 -0
- package/dist/gameplay/event-graph/nodes/value-nodes.d.ts +53 -0
- package/dist/gameplay/event-graph/nodes/value-nodes.js +4 -0
- package/dist/gameplay/event-graph/registry.d.ts +33 -0
- package/dist/gameplay/event-graph/registry.js +4 -0
- package/dist/gameplay/event-graph/runtime-assets.d.ts +21 -0
- package/dist/gameplay/event-graph/runtime-assets.js +4 -0
- package/dist/gameplay/event-graph/runtime.d.ts +160 -0
- package/dist/gameplay/event-graph/runtime.js +4 -0
- package/dist/gameplay/event-graph/type-inference.d.ts +41 -0
- package/dist/gameplay/event-graph/type-inference.js +4 -0
- package/dist/gameplay/event-graph/types.d.ts +77 -0
- package/dist/gameplay/event-graph/types.js +4 -0
- package/dist/gameplay/index.d.ts +17 -2
- package/dist/gameplay/index.js +1 -1
- package/dist/gameplay/initiate.d.ts +4 -0
- package/dist/gameplay/initiate.js +1 -1
- package/dist/gameplay/input/input.d.ts +22 -17
- package/dist/gameplay/input/input.js +1 -1
- package/dist/gameplay/net/browser/index.d.ts +147 -0
- package/dist/gameplay/net/browser/index.js +4 -0
- package/dist/gameplay/net/index.d.ts +7 -0
- package/dist/gameplay/net/index.js +4 -0
- package/dist/gameplay/net/net-connection.d.ts +25 -0
- package/dist/gameplay/net/net-connection.js +4 -0
- package/dist/gameplay/net/net-session.d.ts +70 -0
- package/dist/gameplay/net/net-session.js +4 -0
- package/dist/gameplay/net/service/net-actor-role.d.ts +12 -0
- package/dist/gameplay/net/service/net-actor-role.js +4 -0
- package/dist/gameplay/net/service/net-decorator.d.ts +29 -0
- package/dist/gameplay/net/service/net-decorator.js +4 -0
- package/dist/gameplay/net/service/net-serializer.d.ts +15 -0
- package/dist/gameplay/net/service/net-serializer.js +4 -0
- package/dist/gameplay/net/service/net-service.d.ts +171 -0
- package/dist/gameplay/net/service/net-service.js +4 -0
- package/dist/gameplay/net/service/net-utils.d.ts +8 -0
- package/dist/gameplay/net/service/net-utils.js +4 -0
- package/dist/gameplay/net/service/replication.d.ts +31 -0
- package/dist/gameplay/net/service/replication.js +4 -0
- package/dist/gameplay/net/service/rpc-decorator.d.ts +21 -0
- package/dist/gameplay/net/service/rpc-decorator.js +4 -0
- package/dist/gameplay/net/service/rpc.d.ts +35 -0
- package/dist/gameplay/net/service/rpc.js +4 -0
- package/dist/gameplay/services/asset-loader.d.ts +10 -2
- package/dist/gameplay/services/asset-loader.js +1 -1
- package/dist/gameplay/services/physics/physics-system.d.ts +16 -1
- package/dist/gameplay/services/physics/physics-system.js +1 -1
- package/dist/gameplay/services/world.d.ts +25 -2
- package/dist/gameplay/services/world.js +1 -1
- package/dist/rendering/color-pass.js +1 -1
- package/dist/rendering.d.ts +2 -0
- package/dist/rendering.js +1 -1
- package/dist/scene/asset-resource-loader.d.ts +7 -1
- package/dist/scene/asset-resource-loader.js +1 -1
- package/dist/scene/batched-mesh-2.d.ts +9 -0
- package/dist/scene/batched-mesh-2.js +1 -1
- package/dist/scene/bootstrap.d.ts +2 -0
- package/dist/scene/bootstrap.js +1 -1
- package/dist/scene/custom-param-deserialize.js +1 -1
- package/dist/scene/custom-param-runtime-types.js +1 -1
- package/dist/scene/materializer.d.ts +29 -0
- package/dist/scene/materializer.js +1 -1
- package/dist/scene/model.d.ts +114 -2
- package/dist/scene/model.js +1 -1
- package/dist/scene/objects/prefab.js +1 -1
- package/dist/scene/storage/storage.d.ts +1 -1
- package/dist/scene/storage/storage.js +1 -1
- package/dist/shader/builtin/standard-shader.js +1 -1
- package/dist/shader/builtin/toon-shader.js +1 -1
- package/dist/shader/builtin/unlit-shader.js +1 -1
- package/dist/shader/color-layer.js +1 -1
- package/dist/shader/graph/compiler.d.ts +3 -0
- package/dist/shader/graph/compiler.js +1 -1
- package/dist/shader/graph/model.d.ts +1 -1
- package/dist/shader/graph/registry.js +1 -1
- package/dist/shader/parameter.d.ts +1 -1
- package/dist/shader/parameter.js +1 -1
- package/dist/shader-nodes/depth.js +1 -1
- package/dist/shader-nodes/scene-sample.js +1 -1
- package/dist/test/animation-retarget.test.d.ts +2 -0
- package/dist/test/animation-retarget.test.js +4 -0
- package/dist/test/batched-mesh-2.test.d.ts +2 -0
- package/dist/test/batched-mesh-2.test.js +4 -0
- package/dist/test/browser-net-session.test.d.ts +2 -0
- package/dist/test/browser-net-session.test.js +4 -0
- package/dist/test/event-graph-generated-code.test.d.ts +2 -0
- package/dist/test/event-graph-generated-code.test.js +4 -0
- package/dist/test/event-graph-types.test.d.ts +2 -0
- package/dist/test/event-graph-types.test.js +4 -0
- package/dist/test/event-graph.test.d.ts +2 -0
- package/dist/test/event-graph.test.js +4 -0
- package/dist/test/first-person-camera-component.test.js +1 -1
- package/dist/test/input.test.d.ts +2 -0
- package/dist/test/input.test.js +4 -0
- package/dist/test/net-character-movement.test.d.ts +2 -0
- package/dist/test/net-character-movement.test.js +4 -0
- package/dist/test/net-property-snapshot.test.d.ts +2 -0
- package/dist/test/net-property-snapshot.test.js +4 -0
- package/dist/test/prefab-instance-params.test.js +1 -1
- package/dist/test/sequence-animation-retiming.test.js +1 -1
- package/dist/test/sequence-camera-control.test.js +1 -1
- package/dist/test/sequence-scene-binding.test.d.ts +2 -0
- package/dist/test/sequence-scene-binding.test.js +4 -0
- package/dist/test/sequence-transform.test.d.ts +2 -0
- package/dist/test/sequence-transform.test.js +4 -0
- package/dist/test/shader-graph.test.js +1 -1
- package/dist/test/vfx-random-color-initializer.test.d.ts +2 -0
- package/dist/test/vfx-random-color-initializer.test.js +4 -0
- package/dist/test/world-prefab-spawn.test.d.ts +2 -0
- package/dist/test/world-prefab-spawn.test.js +4 -0
- package/dist/utils/three/placeholder-texture.d.ts +3 -0
- package/dist/utils/three/placeholder-texture.js +4 -0
- package/package.json +18 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Observable } from "rxjs";
|
|
2
|
+
import { NetConnection } from "./net-connection.js";
|
|
3
|
+
export declare enum NetMode {
|
|
4
|
+
/**
|
|
5
|
+
* Game is played locally so it has authority but no other clients are connected.
|
|
6
|
+
* This game be supported by NetSession implmentations that support later connecting
|
|
7
|
+
* to a game hosting a server.
|
|
8
|
+
*/
|
|
9
|
+
none = 1,
|
|
10
|
+
/**
|
|
11
|
+
* The server runs the game but has no po player
|
|
12
|
+
*/
|
|
13
|
+
dedicatedServer = 2,
|
|
14
|
+
/**
|
|
15
|
+
* One client's game acts as a server and other clients are connected
|
|
16
|
+
* via P2P.
|
|
17
|
+
*/
|
|
18
|
+
listenServer = 3,
|
|
19
|
+
/**
|
|
20
|
+
* A client is connected to a server and doesn't have authority.
|
|
21
|
+
* Should be sending inputs to the server to affect important state.
|
|
22
|
+
*/
|
|
23
|
+
client = 4
|
|
24
|
+
}
|
|
25
|
+
export interface NetSession {
|
|
26
|
+
/**
|
|
27
|
+
* A unique ID for this sessions
|
|
28
|
+
*/
|
|
29
|
+
id: string;
|
|
30
|
+
/**
|
|
31
|
+
* The network mode from this player's point of view.
|
|
32
|
+
*/
|
|
33
|
+
readonly mode: NetMode;
|
|
34
|
+
/**
|
|
35
|
+
* The server holds connections to all other clients.
|
|
36
|
+
*/
|
|
37
|
+
readonly clients: NetConnection[];
|
|
38
|
+
/**
|
|
39
|
+
* Clients hold a connection to the server
|
|
40
|
+
*/
|
|
41
|
+
readonly server: NetConnection;
|
|
42
|
+
/**
|
|
43
|
+
* Attempt to reconnect back to a session.
|
|
44
|
+
*/
|
|
45
|
+
reconnect(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Leave the session and disonnect from other clients/server
|
|
48
|
+
*/
|
|
49
|
+
disconnect(): void;
|
|
50
|
+
sendMessage(receiver: NetConnection, reliable: boolean, buffer: ArrayBufferLike): void;
|
|
51
|
+
/**
|
|
52
|
+
* Use this method to check if there is any messages to read.
|
|
53
|
+
* Returns the number of messages available.
|
|
54
|
+
*/
|
|
55
|
+
hasMessage(): number;
|
|
56
|
+
/**
|
|
57
|
+
* Consumes a received message and removes it.
|
|
58
|
+
* Messages should be consumed at an appropriate time rather than randomly whenever received.
|
|
59
|
+
* For example, avoid using the render loop to read messages as its order is not deterministic.
|
|
60
|
+
* You may want to process all messages at a single point in time before any other processing.
|
|
61
|
+
*/
|
|
62
|
+
readMessage(): NetReceivedMessage | null;
|
|
63
|
+
readonly playerLeft: Observable<NetConnection>;
|
|
64
|
+
readonly playerJoined: Observable<NetConnection>;
|
|
65
|
+
}
|
|
66
|
+
export type NetReceivedMessage = {
|
|
67
|
+
from: NetConnection;
|
|
68
|
+
buffer: ArrayBufferLike;
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=net-session.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export var NetMode;!function(e){e[e.none=1]="none",e[e.dedicatedServer=2]="dedicatedServer",e[e.listenServer=3]="listenServer",e[e.client=4]="client"}(NetMode||(NetMode={}));/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The NetRole is sent by the server and set on actors so that
|
|
3
|
+
* they can understan what control they have on the actor without
|
|
4
|
+
* knowing the connection ownership.
|
|
5
|
+
*/
|
|
6
|
+
export declare enum NetRole {
|
|
7
|
+
authority = 0,// Server's authoritative instance
|
|
8
|
+
autonomousProxy = 1,// Client-owned instance (owner's client)
|
|
9
|
+
simulatedProxy = 2,// Non-owner client instance
|
|
10
|
+
none = 3
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=net-actor-role.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export var NetRole;!function(o){o[o.authority=0]="authority",o[o.autonomousProxy=1]="autonomousProxy",o[o.simulatedProxy=2]="simulatedProxy",o[o.none=3]="none"}(NetRole||(NetRole={}));/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ReplOn } from "./replication.js";
|
|
2
|
+
/**
|
|
3
|
+
* Ensures that this function is only executed if on the server.
|
|
4
|
+
* This can be used to prevent executing something on the client
|
|
5
|
+
* in response to some other game play event that requires authority.
|
|
6
|
+
*
|
|
7
|
+
* Example:
|
|
8
|
+
* - An explosion does a random amount of damage to all actors nearby. A function is called
|
|
9
|
+
* on the actor to respond to the damage. The explosion also happens
|
|
10
|
+
* on clients but we don't know the exact amount of damage to apply because it is random.
|
|
11
|
+
* We instead want to let the server handle this and inform clients after.
|
|
12
|
+
*/
|
|
13
|
+
export declare function RunIfServer(): (originalMethod: Function, context: ClassMethodDecoratorContext) => (this: any, ...args: any[]) => any;
|
|
14
|
+
/**
|
|
15
|
+
* Ensures that this function is only executed if on the client.
|
|
16
|
+
* Note that this only includes those that are not also servers like standalone and listen servers.
|
|
17
|
+
*/
|
|
18
|
+
export declare function RunIfClient(): (originalMethod: Function, context: ClassMethodDecoratorContext) => (this: any, ...args: any[]) => any;
|
|
19
|
+
/**
|
|
20
|
+
* Ensures that this function is only executed if on an instance of the game with a player
|
|
21
|
+
* Useful for logic that should only run on the client, such as UI updates, visual effects, playing sound.
|
|
22
|
+
*/
|
|
23
|
+
export declare function RunIfNotDedicatedServer(): (originalMethod: Function, context: ClassMethodDecoratorContext) => (this: any, ...args: any[]) => any;
|
|
24
|
+
/**
|
|
25
|
+
* Marks a property to be automatically replicated to clients.
|
|
26
|
+
* This is a placeholder; actual replication logic would be handled by the networking system.
|
|
27
|
+
*/
|
|
28
|
+
export declare function Replicated(replicatedOn?: ReplOn, reliable?: boolean): (target: undefined, context: ClassMemberDecoratorContext) => void;
|
|
29
|
+
//# sourceMappingURL=net-decorator.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{BaseActor as t}from"../../actors/actor.js";import{NetService as e}from"./net-service.js";import{inject as n}from"../../inject.js";import{ReplOn as r}from"./replication.js";import{isSignalLike as i}from"./net-utils.js";import{ActorComponent as o}from"../../actors/component.js";export function RunIfServer(){return function(r,i){let o;return i.addInitializer(function(){this instanceof t?o=n(e):console.warn("RunIfServer should not be defined on a non actor")}),function(...t){if(o.isServer)return r.apply(this,t)}}}export function RunIfClient(){return function(r,i){let o;return i.addInitializer(function(){this instanceof t?o=n(e):console.warn("RunIfClient should not be defined on a non actor")}),function(...t){if(!o.isServer)return r.apply(this,t)}}}export function RunIfNotDedicatedServer(){return function(r,i){let o;return i.addInitializer(function(){this instanceof t?o=n(e):console.warn("RunIfClient should not be defined on a non actor")}),function(...t){if(!o.isDedicatedServer)return r.apply(this,t)}}}export function Replicated(s=r.all,c=!0){return function(r,a){let f;a.addInitializer(function(){if(!(this instanceof t||this instanceof o))return void console.warn("RunIfClient should not only be used on actors and actor components");let r,u;if(this instanceof t)r=this;else if(this instanceof o&&(r=this.actor,u=this,null==r))return;f=n(e),f.registerReplicatedProperty(s,c,r,a.name.toString(),this,u);const l=this[a.name];if(i(l)){const t=l.subscribe(t=>{if(f.isServer){if(null==r.__netid)return;f.handlePropertySet(s,c,r,a.name.toString(),t,u)}});return void r.disposed.subscribe(()=>{t()})}let d=l;Object.defineProperty(this,a.name,{set:t=>{f.isServer&&f.handlePropertySet(s,c,r,a.name.toString(),t,u),d=t},get:()=>d})})}}export function makePropertyReplicated(t,e,n,r,i){n.registerReplicatedProperty(i,r,t,e,this,null);let o=t[e];Object.defineProperty(t,e,{set:s=>{n.isServer&&n.handlePropertySet(i,r,t,e,s,null),o=s},get:()=>o})}/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class NetSerializer {
|
|
2
|
+
private world;
|
|
3
|
+
private assetLoader;
|
|
4
|
+
encode(data: unknown): string;
|
|
5
|
+
decode(data: string, result: DecodeResult): unknown;
|
|
6
|
+
private wrapObject;
|
|
7
|
+
private unwrapObject;
|
|
8
|
+
/**
|
|
9
|
+
* Mutates the result from decode to resolve all assets
|
|
10
|
+
* but leaving already decoded values as they are.
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
decodeAssets(obj: unknown): Promise<unknown>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=net-serializer.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{__decorate as r}from"tslib";import{World as t}from"../../services/world.js";import{inject as e}from"../../inject.js";import{Service as s}from"typedi";import{BaseActor as n}from"../../actors/actor.js";import{Euler as o,Quaternion as i,Vector2 as a,Vector3 as c,Vector4 as f}from"three";import{DataAssetRef as u}from"../../../scene/objects/data-asset.js";import{AssetLoader as l}from"../../services/asset-loader.js";const p="-a",m="-v2",d="-v3",w="-v4",y="-e",A="-q",h="-s",j="-m",b="-dar";export class DecodeResult{constructor(){this.error=!1,this.requiresAssetLookups=!1}reset(){this.error=!1,this.missingActorId=void 0,this.requiresAssetLookups=!1}}let O=class{constructor(){this.world=e(t),this.assetLoader=e(l)}encode(r){return JSON.stringify(this.wrapObject(r))}decode(r,t){t.reset();const e=JSON.parse(r);return this.unwrapObject(e,t)}wrapObject(r){if(null!=r&&"object"==typeof r){if(Array.isArray(r))return r.map(r=>this.wrapObject(r));if(r instanceof n){if(null!=r.__netid)return{[p]:r.__netid};console.warn("Missing netid on actor",r)}else{if(r instanceof a)return{[m]:r.toArray([])};if(r instanceof c)return{[d]:r.toArray([])};if(r instanceof f)return{[w]:r.toArray([])};if(r instanceof o)return{[y]:r.toArray([])};if(r instanceof i)return{[A]:r.toArray([])};if(r instanceof Map)return{[j]:Array.from(r.entries()).map(([r,t])=>[r,this.wrapObject(t)])};if(r instanceof Set)return{[h]:Array.from(r.values()).map(r=>this.wrapObject(r))};if(r instanceof u)return{[b]:r.id}}const t={};for(const e of Object.keys(r))t[e]=this.wrapObject(r[e]);return t}return r}unwrapObject(r,t){if(null!=r&&"object"==typeof r){if(Array.isArray(r))return r.map(r=>this.unwrapObject(r,t));{if(null!=r[p]){const e=r[p],s=this.world.actors.find(r=>r.__netid===e);return null==s&&(t.error=!0,t.missingActorId=e,console.warn(`Failed to find replicated actor with netid "${e}"`)),s}if(null!=r[m]){const t=r[m];return(new a).fromArray(t)}if(null!=r[d]){const t=r[d];return(new c).fromArray(t)}if(null!=r[w]){const t=r[w];return(new f).fromArray(t)}if(null!=r[y]){const t=r[y];return(new o).fromArray(t)}if(null!=r[A]){const t=r[A];return(new i).fromArray(t)}if(null!=r[j]){const e=r[j];return new Map(e.map(([r,e])=>[r,this.unwrapObject(e,t)]))}if(null!=r[h]){const e=r[h];return new Set(e.map(r=>this.unwrapObject(r,t)))}if(null!=r[b])return t.requiresAssetLookups=!0,r;const e={};for(const s of Object.keys(r))e[s]=this.unwrapObject(r[s],t);return e}}return r}async decodeAssets(r){if(null!=r&&"object"==typeof r){if(Array.isArray(r))return await Promise.all(r.map(r=>this.decodeAssets(r)));if(r instanceof Map){const t=await Promise.all(Array.from(r.entries()).map(async([r,t])=>[r,await this.decodeAssets(t)]));r.clear();for(const[e,s]of t)r.set(e,s);return r}if(r instanceof Set){const t=await Promise.all(Array.from(r.values()).map(r=>this.decodeAssets(r)));r.clear();for(const e of t)r.add(e);return r}{const t=r;if(null!=t[b])return await this.assetLoader.getDataAssetById(t[b]);for(const r of Object.keys(t))t[r]=await this.decodeAssets(t[r]);return t}}return r}};O=r([s()],O);export{O as NetSerializer};new a,new c,new f,new o,new i;/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { ActorOptions, BaseActor } from '../../actors/actor.js';
|
|
2
|
+
import { ActorComponent } from '../../actors/component.js';
|
|
3
|
+
import { NetConnection } from '../net-connection.js';
|
|
4
|
+
import { NetMode, NetSession } from '../net-session.js';
|
|
5
|
+
import { ReplOn } from "./replication.js";
|
|
6
|
+
import { RunsOn } from './rpc.js';
|
|
7
|
+
export declare class NetService {
|
|
8
|
+
session?: NetSession;
|
|
9
|
+
/**
|
|
10
|
+
* For connection ownership to be determined, actors have
|
|
11
|
+
* to be registerd with their owning connection.
|
|
12
|
+
* You might just have a single actor per player with a connection.
|
|
13
|
+
* For many games, most actors are owned by the server. The player might
|
|
14
|
+
* just have a single playable character as its owned actor.
|
|
15
|
+
* For example, if the character enters a car, the player should start controlling
|
|
16
|
+
* that car and the car's ownership should be to the player.
|
|
17
|
+
* A player controller migth be a good solution for this because
|
|
18
|
+
* we need to somehow inform the client that it entered the car?
|
|
19
|
+
* This could be done on the player character as well though and the client
|
|
20
|
+
* will need to check if the player character is in a car and adjust the input controls
|
|
21
|
+
* and camera accordingly.
|
|
22
|
+
*
|
|
23
|
+
* Spawning controllers from the server might also be a solution.
|
|
24
|
+
* You can then define inputs on the client when the game starts using the input service.
|
|
25
|
+
* This might be a nice abstraction but it is not required.
|
|
26
|
+
*
|
|
27
|
+
* When the server spawns a player character or controller, it will set the
|
|
28
|
+
* connection on the NetService.
|
|
29
|
+
*/
|
|
30
|
+
private readonly actorConnection;
|
|
31
|
+
private destroyed;
|
|
32
|
+
get mode(): NetMode;
|
|
33
|
+
private world;
|
|
34
|
+
private serializer;
|
|
35
|
+
private serverTimeOffset;
|
|
36
|
+
/**
|
|
37
|
+
* Convenience function to check if mode === NetworkRole.client
|
|
38
|
+
*/
|
|
39
|
+
get isClient(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Convenience function to check if you are authoritative
|
|
42
|
+
*/
|
|
43
|
+
get isServer(): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Convenience function to check if mode === NetworkRole.dedicatedServer
|
|
46
|
+
*/
|
|
47
|
+
get isDedicatedServer(): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* A queue of messages is kept for recently spawned actors so
|
|
50
|
+
* any RPC or property replication on this actor is not sent
|
|
51
|
+
* until we got a confirmation on the client that the actor is spawned.
|
|
52
|
+
*
|
|
53
|
+
* This is not perfect though.
|
|
54
|
+
* If a message contains a reference to an actor
|
|
55
|
+
*/
|
|
56
|
+
private actorPreSpawnMessageBuffer;
|
|
57
|
+
/**
|
|
58
|
+
* If we receive a message with a reference to an actor
|
|
59
|
+
* that currently does not exist, we should queue it.
|
|
60
|
+
* This can happen if the server sends an RPC or property replication
|
|
61
|
+
* for an actor that we have not yet finished spawning.
|
|
62
|
+
* This is only relevant for reliable messages.
|
|
63
|
+
*/
|
|
64
|
+
private actorRefMissingMessageQueue;
|
|
65
|
+
private netStartupActorSpawnQueue;
|
|
66
|
+
private spawningActorNetIds;
|
|
67
|
+
start(): void;
|
|
68
|
+
stop(): void;
|
|
69
|
+
private configureMaterializedActorRole;
|
|
70
|
+
shouldReplicate(actor: BaseActor): boolean;
|
|
71
|
+
setReplicate(actor: BaseActor, replicate: any): void;
|
|
72
|
+
/**
|
|
73
|
+
* Ensure that we only replicate an actor for spawn, properties and RPC
|
|
74
|
+
* to connections for which it is relevant. This includes checking
|
|
75
|
+
* if it is only relevant to owner and possibly other relevancy
|
|
76
|
+
* logic.
|
|
77
|
+
* @param actor
|
|
78
|
+
* @param connection
|
|
79
|
+
* @returns
|
|
80
|
+
*/
|
|
81
|
+
isRelevant(actor: BaseActor, connection: NetConnection): boolean;
|
|
82
|
+
getRelevancyOptions(actor: BaseActor): Partial<ActorOptions['relevancy']> | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Actors are normally sent to clients as soon as they
|
|
85
|
+
* are spawned on the server. If a client joins after this
|
|
86
|
+
* has happened, then they have to know which ones to spawn.
|
|
87
|
+
*/
|
|
88
|
+
private spawnOnLateClient;
|
|
89
|
+
private processMessages;
|
|
90
|
+
private processMessage;
|
|
91
|
+
private processServerTime;
|
|
92
|
+
private getActorRefMissingMessageQueue;
|
|
93
|
+
private processRpc;
|
|
94
|
+
private processProp;
|
|
95
|
+
private processPropSnapshot;
|
|
96
|
+
private applyReplicatedProperties;
|
|
97
|
+
private processSpawn;
|
|
98
|
+
private readOptionalSceneId;
|
|
99
|
+
private findMaterializedNetStartupActor;
|
|
100
|
+
private applySpawnNetInfo;
|
|
101
|
+
private getNetStartupActorSpawnQueue;
|
|
102
|
+
private processQueuedNetStartupActorSpawns;
|
|
103
|
+
private processQueuedActorMessages;
|
|
104
|
+
sendActorReady(actor: BaseActor): void;
|
|
105
|
+
/**
|
|
106
|
+
* Processes an actor ready message from a client.
|
|
107
|
+
* @param from The connection the message is from.
|
|
108
|
+
* @param buffer The message buffer.
|
|
109
|
+
*/
|
|
110
|
+
private processActorReady;
|
|
111
|
+
sendRpc(runsOn: RunsOn, reliable: boolean, actor: BaseActor, fname: string, args: any[], component?: ActorComponent): void;
|
|
112
|
+
private sendWithQueue;
|
|
113
|
+
private findQueuedActorsInData;
|
|
114
|
+
handlePropertySet(replOn: ReplOn, reliable: boolean, actor: BaseActor, property: string, value: unknown, component?: ActorComponent): void;
|
|
115
|
+
sendProperty(replOn: ReplOn, reliable: boolean, actor: BaseActor, property: string, propertyBuffer: ArrayBufferLike, component?: ActorComponent): void;
|
|
116
|
+
private nextNetId;
|
|
117
|
+
/**
|
|
118
|
+
* Generate a uniqe id for the network to be used for replication and
|
|
119
|
+
* to not collide with the existing actor id
|
|
120
|
+
*/
|
|
121
|
+
private defineNetId;
|
|
122
|
+
private shouldReplicateMap;
|
|
123
|
+
private replicatedActors;
|
|
124
|
+
private replicatedProperties;
|
|
125
|
+
private replicatedPropertyRegistry;
|
|
126
|
+
sendActorSpawn(actor: BaseActor, connections?: NetConnection[]): void;
|
|
127
|
+
/**
|
|
128
|
+
* Sends a message to remove an actor with the given id to all relevant connections.
|
|
129
|
+
* @param actor The actor to remove.
|
|
130
|
+
*/
|
|
131
|
+
sendActorRemove(actor: BaseActor): void;
|
|
132
|
+
/**
|
|
133
|
+
* Processes a remove actor message.
|
|
134
|
+
* @param from The connection the message is from.
|
|
135
|
+
* @param buffer The message buffer.
|
|
136
|
+
*/
|
|
137
|
+
private processRemoveActor;
|
|
138
|
+
setOwningConnection(actor: BaseActor, connection: NetConnection): void;
|
|
139
|
+
getOwningConnection(actor: BaseActor): NetConnection;
|
|
140
|
+
getActorsByOwningConnection(connection: NetConnection): BaseActor[];
|
|
141
|
+
private isLocallyControlled;
|
|
142
|
+
/**
|
|
143
|
+
* See if an actor is locally owned.
|
|
144
|
+
* This relies on role and player controller
|
|
145
|
+
*/
|
|
146
|
+
isLocalOwner(actor: BaseActor): boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Sends the current server time (Date.now()) to the specified NetConnection.
|
|
149
|
+
* The time is sent as an 8-byte (BigInt) value.
|
|
150
|
+
*/
|
|
151
|
+
sendServerTime(connection: NetConnection): void;
|
|
152
|
+
/**
|
|
153
|
+
* Parses a server time message buffer and returns the timestamp (number).
|
|
154
|
+
* Expects the buffer to be at least 9 bytes: 1 byte type, 8 bytes timestamp.
|
|
155
|
+
*/
|
|
156
|
+
parseServerTime(buffer: ArrayBufferLike): number;
|
|
157
|
+
private getConnectionKey;
|
|
158
|
+
private getPreSpawnMessageQueue;
|
|
159
|
+
private shouldQueueMessageUntilActorReady;
|
|
160
|
+
private isPropertyMessage;
|
|
161
|
+
private getReplicatedPropertyKey;
|
|
162
|
+
private sendPropertySnapshot;
|
|
163
|
+
private buildPropertySnapshotEntries;
|
|
164
|
+
private shouldReplicatePropertyToConnection;
|
|
165
|
+
private readReplicatedPropertyValue;
|
|
166
|
+
private createPropertySnapshotBuffer;
|
|
167
|
+
private decodeReplicatedValue;
|
|
168
|
+
private applyReplicatedProperty;
|
|
169
|
+
private callRepNotify;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=net-service.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{__decorate as e}from"tslib";import{delay as t,interval as n,Subject as r,takeUntil as s,tap as o}from"rxjs";import{Euler as i,Vector3 as c}from"three";import{Service as a}from"typedi";import{$actorOptions as l,BaseActor as d,getActorClassById as p}from"../../actors/actor.js";import{ActorComponent as u}from"../../actors/component.js";import{$actorComponents as f}from"../../actors/internal/component-init.js";import{inject as h}from"../../inject.js";import{World as g}from"../../services/world.js";import{NetMode as y}from"../net-session.js";import{NetRole as w}from"./net-actor-role.js";import{DecodeResult as m,NetSerializer as v}from"./net-serializer.js";import{isSignalLike as A}from"./net-utils.js";import{ReplOn as b}from"./replication.js";import{getRpcMethodId as R,getRpcMethodName as _,RunsOn as S}from"./rpc.js";import{ActorController as U,BasePlayerController as M}from"../../actors/controller/actor-controller.js";import{makePropertyReplicated as C}from"./net-decorator.js";var P;!function(e){e[e.rpc=1]="rpc",e[e.prop=2]="prop",e[e.spawn=3]="spawn",e[e.removeActor=4]="removeActor",e[e.rpcComponent=5]="rpcComponent",e[e.propComponent=6]="propComponent",e[e.rpcBinary=21]="rpcBinary",e[e.rpcComponentBinary=25]="rpcComponentBinary",e[e.actorReady=7]="actorReady",e[e.propSnapshot=8]="propSnapshot",e[e.serverTime=100]="serverTime"}(P||(P={}));var $;!function(e){e[e.actor=0]="actor",e[e.component=1]="component"}($||($={}));let L=class{constructor(){this.actorConnection=new Map,this.destroyed=new r,this.world=h(g),this.serializer=h(v),this.serverTimeOffset=0,this.actorPreSpawnMessageBuffer=new Map,this.actorRefMissingMessageQueue=new Map,this.netStartupActorSpawnQueue=new Map,this.spawningActorNetIds=new Set,this.nextNetId=1,this.shouldReplicateMap=new Map,this.replicatedActors=new Map,this.replicatedProperties=new Map,this.replicatedPropertyRegistry=new Map}get mode(){return this.session?.mode??y.none}get isClient(){return this.mode===y.client}get isServer(){return this.mode<y.client}get isDedicatedServer(){return this.mode===y.dedicatedServer}start(){if(this.stop(),this.destroyed=new r,this.isServer)for(const e of this.session.clients)this.sendServerTime(e);n(15).pipe(s(this.destroyed)).subscribe(()=>{this.processMessages()}),this.world.actorAdded.pipe(s(this.destroyed),o(e=>{this.configureMaterializedActorRole(e),this.isServer?this.defineNetId(e):this.processQueuedNetStartupActorSpawns(e)}),t(8)).subscribe(e=>{this.shouldReplicate(e)&&(C(e,"owner",this,!0,b.all),this.sendActorSpawn(e))}),this.world.actorRemoved.pipe(s(this.destroyed),t(10)).subscribe(e=>{this.sendActorRemove(e),this.replicatedActors.delete(e),this.replicatedProperties.delete(e),this.replicatedPropertyRegistry.delete(e),this.actorPreSpawnMessageBuffer.delete(e)}),this.session.playerJoined.pipe(s(this.destroyed)).subscribe(e=>{this.sendServerTime(e),this.isServer&&this.replicatedActors.size>0&&this.spawnOnLateClient(e)})}stop(){this.destroyed.next(null),this.destroyed.complete()}configureMaterializedActorRole(e){null!=e.__netSceneId&&this.mode!==y.none&&(this.shouldReplicate(e)?e.netRole=this.isServer?w.authority:w.simulatedProxy:this.isServer||(e.netRole=w.none))}shouldReplicate(e){const t=this.shouldReplicateMap.get(e);if(null==t){const t=e.constructor[l],n=!0===t?.replicate;return this.shouldReplicateMap.set(e,n),n}return!0===t}setReplicate(e,t){this.shouldReplicateMap.set(e,t)}isRelevant(e,t){const n=this.getRelevancyOptions(e);return!(!0===n?.ownerOnly)||this.resolveActorConnection(e)?.id===t.id}getRelevancyOptions(e){return e.constructor[l].relevancy}spawnOnLateClient(e){const t=[e];for(const e of this.replicatedActors.keys())this.sendActorSpawn(e,t)}async processMessages(){const e=this.session.hasMessage();for(let t=0;t<e;t++){const e=this.session.readMessage();null!=e&&await this.processMessage(e)}}async processMessage(e){try{switch(new DataView(e.buffer).getUint8(0)){case P.rpc:case P.rpcComponent:case P.rpcBinary:case P.rpcComponentBinary:this.processRpc(e.from,e.buffer);break;case P.prop:case P.propComponent:this.processProp(e.from,e.buffer);break;case P.propSnapshot:this.processPropSnapshot(e.from,e.buffer);break;case P.spawn:await this.processSpawn(e.from,e.buffer);break;case P.removeActor:this.processRemoveActor(e.from,e.buffer);break;case P.serverTime:this.processServerTime(e.from,e.buffer);break;case P.actorReady:this.processActorReady(e.from,e.buffer)}}catch(e){console.error("Failed to process message",e)}}processServerTime(e,t){if(this.isServer||this.session.server?.id!==e.id)return;const n=this.parseServerTime(t);this.serverTimeOffset=Date.now()-n}getActorRefMissingMessageQueue(e){let t=this.actorRefMissingMessageQueue.get(e);return null==t&&(t=[],this.actorRefMissingMessageQueue.set(e,t)),t}processRpc(e,t){let n=0;const r=new DataView(t),s=r.getUint8(n);n+=1;const o=r.getUint32(n,!0);n+=4;const i=r.getUint8(n);n+=1;const c=s===P.rpcBinary||s===P.rpcComponentBinary;let a,l,d="";if(c){const e=r.getUint32(n,!0);n+=4,l=new Uint8Array(t,n,e),n+=e}else{const e=r.getUint16(n,!0);n+=2,d=O(t,n,e),n+=e;try{a=this.serializer.decode(d,F)}catch(e){return void console.warn("Failed to parse RPC args JSON",d,e)}}if(!c&&F.error){if(null!=F.missingActorId){const n=this.getActorRefMissingMessageQueue(F.missingActorId);console.debug(`Missing referenced actor ${F.missingActorId}. Queueing message for later`),n.push({from:e,buffer:t})}else console.log("Unknown decode error",d);return}const p=this.world.actors.find(e=>e.__netid===o);if(null==p){return this.getActorRefMissingMessageQueue(o).push({from:e,buffer:t}),void console.debug(`Missing actor ${o}. Queueing message for later`)}let u;if(s===P.rpcComponent||s===P.rpcComponentBinary){const e=r.getUint8(n),t=p[f];if(null!=t&&(u=t.find(t=>t.__netid===e)),null==u)return void console.error(`RPC failed: Failed to find component with netid ${e} on actor with netid ${o}`)}if(this.isServer){if(!this.session.clients.some(t=>t.id==e.id))return void console.warn("Received RCP from non client");const t=this.resolveActorConnection(p);if(null==t)return void console.error("Received server RPC for actor without owner which can't be processed");if(t.id!==e.id)return void console.warn(`Received RPC for actor net id ${p.__netid} from connection ${e.id}, but this connection is not the owner. Can't process.`)}else{if(!(this.session.server?.id===e.id))return void console.warn("Received RCP from non server which is not allowed")}const h=u??p,g=_(h,i);if(null!=g)if("function"==typeof h[g])if(c)h[g](l);else{if(F.requiresAssetLookups)return this.serializer.decodeAssets(a).then(e=>{h[g](...e)}).catch(e=>{console.warn(`Failed to decode asset references for RPC '${g}' on actor net id ${p.__netid}`,e)});h[g](...a)}else console.error(`RPC function '${g}' not found on actor net id ${p.__netid}`+(null!=u?` and component net id ${u.__netid}`:""));else console.error(`RPC method id ${i} not found on actor net id ${p.__netid}`+(null!=u?` and component net id ${u.__netid}`:""))}processProp(e,t){if(this.session.server?.id!==e.id)return void console.warn(`Received property replication from non-server connection (id: ${e.id}), ignoring.`);let n=0;const r=new DataView(t),s=r.getUint8(n);n+=1;const o=r.getUint32(n,!0);n+=4;const i=r.getUint8(n);n+=1;let c="";for(let e=0;e<i;e++)c+=String.fromCharCode(r.getUint8(n+e));n+=i;const a=r.getUint16(n,!0);n+=2;const l=t.slice(n,n+a);n+=a;const d=this.world.actors.find(e=>e.__netid===o);if(!d){return this.getActorRefMissingMessageQueue(o).push({from:e,buffer:t}),void console.error("Failed to process property replication. No actor found with id",o,c)}let p;if(s===P.propComponent){const e=r.getUint8(n),t=d[f];if(null!=t&&(p=t.find(t=>t.__netid===e)),null==p)return void console.error(`Failed to find component with netid ${e} on actor with netid ${o}`)}const u=p??d;try{const n=this.decodeReplicatedValue(l);if(F.error){if(null!=F.missingActorId){let n=this.getActorRefMissingMessageQueue(F.missingActorId);console.debug(`Missing referenced actor ${F.missingActorId}. Queueing message for later`),n.push({from:e,buffer:t})}return}if(F.requiresAssetLookups)return this.serializer.decodeAssets(n).then(e=>{this.applyReplicatedProperty(u,c,e),this.callRepNotify(u,c)}).catch(e=>{console.warn(`Failed to decode asset references for replicated property '${c}' on actor id ${o}`,e)});this.applyReplicatedProperty(u,c,n),this.callRepNotify(u,c)}catch(e){console.warn(`Failed to decode replicated property '${c}' on actor id ${o}`,e)}}processPropSnapshot(e,t){if(this.session.server?.id!==e.id)return void console.warn(`Received property snapshot from non-server connection (id: ${e.id}), ignoring.`);let n=0;const r=new DataView(t);n+=1;const s=r.getUint32(n,!0);n+=4;const o=this.world.actors.find(e=>e.__netid===s);if(null==o){return this.getActorRefMissingMessageQueue(s).push({from:e,buffer:t}),void console.debug(`Missing actor ${s}. Queueing property snapshot for later`)}const i=r.getUint16(n,!0);n+=2;const c=[];for(let a=0;a<i;a++){const i=r.getUint8(n);n+=1;let a=o;if(i===$.component){const e=r.getUint8(n);n+=1;const t=o[f];if(a=t?.find(t=>t.__netid===e),null==a)return void console.error(`Failed to process property snapshot. No component found with netid ${e} on actor with netid ${s}`)}else if(i!==$.actor)return void console.error(`Failed to process property snapshot. Unknown target kind ${i}`);const l=r.getUint8(n);n+=1;let d="";for(let e=0;e<l;e++)d+=String.fromCharCode(r.getUint8(n+e));n+=l;const p=r.getUint32(n,!0);n+=4;const u=t.slice(n,n+p);n+=p;try{const n=this.decodeReplicatedValue(u);if(F.error){if(null!=F.missingActorId){this.getActorRefMissingMessageQueue(F.missingActorId).push({from:e,buffer:t}),console.debug(`Missing referenced actor ${F.missingActorId}. Queueing property snapshot for later`)}else console.warn(`Unknown decode error in property snapshot for actor ${s}`);return}c.push({target:a,property:d,value:n,requiresAssetLookups:F.requiresAssetLookups})}catch(e){return void console.warn(`Failed to decode replicated property snapshot entry '${d}' on actor id ${s}`,e)}}if(c.some(e=>e.requiresAssetLookups))return Promise.all(c.map(async e=>{e.requiresAssetLookups&&(e.value=await this.serializer.decodeAssets(e.value))})).then(()=>{this.applyReplicatedProperties(c)}).catch(e=>{console.warn(`Failed to decode asset references for property snapshot on actor id ${s}`,e)});this.applyReplicatedProperties(c)}applyReplicatedProperties(e){for(const t of e)this.applyReplicatedProperty(t.target,t.property,t.value);for(const t of e)this.callRepNotify(t.target,t.property)}async processSpawn(e,t){if(this.isServer)return;const n=new DataView(t);let r=0;r+=1;const s=n.getUint32(r,!0);r+=4;const o=n.getUint8(r);r+=1;let i="";for(let e=0;e<o;e++)i+=String.fromCharCode(n.getUint8(r+e));r+=o,Q.set(n.getFloat32(r,!0),n.getFloat32(r+4,!0),n.getFloat32(r+8,!0)),r+=12,B.set(n.getFloat32(r,!0),n.getFloat32(r+4,!0),n.getFloat32(r+8,!0)),r+=12;const c=n.getUint8(r);r+=1;const a=n.getUint32(r);r+=4;const l=this.readOptionalSceneId(t,r);console.log("Spawning "+i);const d=p(i);if(!d)return void console.error(`Failed to spawn actor: unknown actor type '${i}'`);const u=this.world.actors.find(e=>e.__netid===s);if(null!=u)return void this.applySpawnNetInfo(u,s,c,a);if(this.spawningActorNetIds.has(s))return void console.log("Actor was already spawned",null!=u);const f=this.findMaterializedNetStartupActor(l,i,s);if(null!=f)return this.applySpawnNetInfo(f,s,c,a),this.processQueuedActorMessages(s),void this.sendActorReady(f);if(null==l){this.spawningActorNetIds.add(s);try{const e=await this.world.spawnActorWithNetInfo(d,s,c,a,Q,B);this.processQueuedActorMessages(s),this.sendActorReady(e)}catch(e){return void console.error("Spawning replicated actor on client failed",e)}finally{this.spawningActorNetIds.delete(s)}}else this.getNetStartupActorSpawnQueue(l).push({from:e,buffer:t})}readOptionalSceneId(e,t){if(t+2>e.byteLength)return;const n=new DataView(e).getUint16(t,!0);return t+=2,0===n||t+n>e.byteLength?void 0:O(e,t,n)}findMaterializedNetStartupActor(e,t,n){if(null!=e)return this.world.actors.find(r=>{if(r.__netSceneId!==e)return!1;if(null!=r.__netid&&r.__netid!==n)return!1;return(r.constructor.__actorId??r.constructor.name)===t})}applySpawnNetInfo(e,t,n,r){if(e.__netid=t,e.netRole=n,0===r)e.owner=void 0;else{const t=this.world.actors.find(e=>e.__netid===r);null!=t&&(e.owner=t)}e instanceof M&&(e.isLocallyControlled=n===w.autonomousProxy)}getNetStartupActorSpawnQueue(e){let t=this.netStartupActorSpawnQueue.get(e);return null==t&&(t=[],this.netStartupActorSpawnQueue.set(e,t)),t}processQueuedNetStartupActorSpawns(e){if(null==e.__netSceneId)return;const t=this.netStartupActorSpawnQueue.get(e.__netSceneId);if(null!=t){this.netStartupActorSpawnQueue.delete(e.__netSceneId);for(const e of t)this.processMessage(e)}}processQueuedActorMessages(e){const t=this.actorRefMissingMessageQueue.get(e);if(null!=t){console.log(`Processing queued messages for actor ${e}`),this.actorRefMissingMessageQueue.delete(e);for(const e of t)this.processMessage(e)}}sendActorReady(e){if(this.mode===y.none)return;if(!e||null==e.__netid)return void console.warn("sendActorReady: actor or actor.__netid is undefined");if(this.isServer)return;const t=new ArrayBuffer(5),n=new DataView(t);let r=0;n.setUint8(r,P.actorReady),r+=1,n.setUint32(r,e.__netid,!0),this.session.server&&this.session.sendMessage(this.session.server,!0,t)}processActorReady(e,t){if(!this.isServer)return;const n=new DataView(t).getUint32(1,!0),r=this.world.actors.find(e=>e.__netid===n);if(!r)return void console.warn(`processActorReady: No actor found with net id ${n}`);const s=this.actorPreSpawnMessageBuffer.get(r),o=this.getConnectionKey(e),i=s?.get(o);if(null!=i){this.sendPropertySnapshot(r,e);const t=i.filter(e=>!this.isPropertyMessage(e.buffer));if(t.length>0){console.log(`Sending ${t.length} queued messages for actor ${r.__netid}`);for(const e of t)this.session.sendMessage(e.connection,e.reliable,e.buffer)}s.delete(o),0===s.size&&this.actorPreSpawnMessageBuffer.delete(r)}}sendRpc(e,t,n,r,s,o){if(this.mode==y.none)return;if(!this.shouldReplicate(n))return;const i=n.__netid;if(null==i)return void console.warn("No __netid defined on actor. Actor must be repliated for RPC");const c=this.resolveActorConnection(n),a=[];if(this.isServer)switch(e){case S.all:a.push(...this.session.clients.filter(e=>this.isRelevant(n,e)));break;case S.client:null!=c&&a.push(c);break;case S.notOwner:a.push(...this.session.clients.filter(e=>e.id!==c?.id&&this.isRelevant(n,e)));case S.server:}else switch(e){case S.all:case S.client:case S.notOwner:break;case S.server:a.push(this.session.server)}if(0==a.length)return;if(null!=o&&null==o.__netid)return void console.warn("No __netid defined on component. Component must be initialized for RPC",o);const l=null!=o,d=o??n,p=R(d,r);if(null==p)return void console.warn(`RPC function '${r}' is not registered on ${d.constructor?.name??"target"}`);const u=1===s.length?function(e){if(e instanceof Uint8Array)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if("undefined"!=typeof SharedArrayBuffer&&e instanceof SharedArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);return null}(s[0]):null;if(null!=u){let e=10+u.byteLength;l&&(e+=1);const r=new ArrayBuffer(e),s=new DataView(r);let c=0;s.setUint8(c,l?P.rpcComponentBinary:P.rpcBinary),c+=1,s.setUint32(c,i,!0),c+=4,s.setUint8(c,p),c+=1,s.setUint32(c,u.byteLength,!0),c+=4,D(r,c,u),c+=u.byteLength,l&&(s.setUint8(c,o.__netid),c+=1);for(const e of a)null!=e&&this.sendWithQueue(n,{connection:e,reliable:t,buffer:r});return}const f=this.serializer.encode(s),h=I.encode(f);if(h.byteLength>65535)return void console.warn("RPC arguments are too large to send with the JSON RPC format",r);let g=8+h.byteLength;l&&(g+=1);const w=new ArrayBuffer(g),m=new DataView(w);let v=0;m.setUint8(v,l?P.rpcComponent:P.rpc),v+=1,m.setUint32(v,i,!0),v+=4,m.setUint8(v,p),v+=1,m.setUint16(v,h.byteLength,!0),v+=2,D(w,v,h),v+=h.byteLength,l&&(m.setUint8(v,o.__netid),v+=1);for(const e of a)null!=e&&this.sendWithQueue(n,{connection:e,reliable:t,buffer:w})}sendWithQueue(e,t){if(this.shouldQueueMessageUntilActorReady(e,t.connection)){return void this.getPreSpawnMessageQueue(e,t.connection).push(t)}this.session.sendMessage(t.connection,t.reliable,t.buffer)}findQueuedActorsInData(e,t=[]){if("object"==typeof e){if(Array.isArray(e))for(const t of e)this.findQueuedActorsInData(t);if(e instanceof d){this.actorPreSpawnMessageBuffer.get(e)}}}handlePropertySet(e,t,n,r,s,o){if(this.mode==y.none)return;if(!this.isServer)return;if(!this.shouldReplicate(n))return;let i=this.replicatedProperties.get(n);null==i&&(i={},this.replicatedProperties.set(n,i));const c=this.serializer.encode(s),a=I.encode(c),l=a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength);i[this.getReplicatedPropertyKey(r,o)]={property:r,replOn:e,reliable:t,buffer:l,component:o},this.sendProperty(e,t,n,r,l,o)}sendProperty(e,t,n,r,s,o){if(!this.isServer)return;const i=[],c=this.resolveActorConnection(n);switch(e){case b.all:i.push(...this.session.clients);break;case b.owner:null!=c&&i.push(c);break;case b.notOwner:null==c?i.push(...this.session.clients):i.push(...this.session.clients.filter(e=>e.id!==c.id))}const a=null!=o&&null!=o.__netid;let l=6+r.length+2+s.byteLength;a&&(l+=1);const d=new ArrayBuffer(l),p=new DataView(d);let u=0;p.setUint8(u,a?P.propComponent:P.prop),u+=1,p.setUint32(u,n.__netid,!0),u+=4,p.setUint8(u,r.length),u+=1;for(let e=0;e<r.length;e++)p.setUint8(u++,r.charCodeAt(e));p.setUint16(u,s.byteLength,!0),u+=2,new Uint8Array(d,u,s.byteLength).set(new Uint8Array(s)),u+=s.byteLength,a&&(p.setUint8(u,o.__netid),u+=1);for(const e of i)null!=e&&this.isRelevant(n,e)&&this.sendWithQueue(n,{connection:e,reliable:t,buffer:d})}defineNetId(e){null==e.__netid&&(e.__netid=this.nextNetId++)}registerReplicatedProperty(e,t,n,r,s,o){if(null==n||null==r||null==s)return;let i=this.replicatedPropertyRegistry.get(n);null==i&&(i=[],this.replicatedPropertyRegistry.set(n,i));const c=o??(s instanceof u?s:void 0),a=i.find(e=>e.target===s&&e.property===r);if(null!=a)return a.replOn=e,a.reliable=t,void(a.component=c);i.push({property:r,replOn:e,reliable:t,target:s,component:c})}sendActorSpawn(e,t=this.session.clients){if(!this.isServer)return;const n=t.filter(t=>this.isRelevant(e,t));this.defineNetId(e);const r=e.__netid;let s=e.constructor.__actorId??e.constructor.name;const o=I.encode(s);let i;null!=e.__netSceneId&&(i=I.encode(e.__netSceneId),i.byteLength>65535&&(console.warn(`Scene actor id is too long to replicate as a startup actor: ${e.__netSceneId}`),i=void 0));const c=i?.byteLength??0,a=6+o.length+12+12+1+4+2+c,l=new ArrayBuffer(a),d=new DataView(l);let p=0;d.setUint8(p,P.spawn),p+=1,d.setUint32(p,r,!0),p+=4,d.setUint8(p,o.length),p+=1,new Uint8Array(l).set(o,p),p+=o.length,d.setFloat32(p,e.position.x,!0),p+=4,d.setFloat32(p,e.position.y,!0),p+=4,d.setFloat32(p,e.position.z,!0),p+=4,d.setFloat32(p,e.rotation.x,!0),p+=4,d.setFloat32(p,e.rotation.y,!0),p+=4,d.setFloat32(p,e.rotation.z,!0),p+=4;let u=p;p+=1,d.setUint32(p,e.owner?.__netid??0),p+=4,d.setUint16(p,c,!0),p+=2,null!=i&&(D(l,p,i),p+=i.byteLength);let f=this.replicatedActors.get(e);null==f&&(f={spawnedAt:Date.now(),connections:[]},this.replicatedActors.set(e,f));for(const t of n){const n=l.slice(0),r=new DataView(n),s=this.resolveActorConnection(e)?.id===t.id?w.autonomousProxy:w.simulatedProxy;r.setUint8(u,s),this.getPreSpawnMessageQueue(e,t),this.session.sendMessage(t,!0,n),f.connections.some(e=>e.id===t.id)||f.connections.push(t)}}sendActorRemove(e){if(!this.isServer)return;const t=new ArrayBuffer(5),n=new DataView(t);let r=0;n.setUint8(r,P.removeActor),r+=1,n.setUint32(r,e.__netid,!0);for(const e of this.session.clients)this.session.sendMessage(e,!0,t)}processRemoveActor(e,t){if(this.isServer||this.session.server?.id!==e.id)return;const n=new DataView(t).getUint32(1,!0),r=this.world.actors.find(e=>e.__netid===n);r&&(this.world.removeActor(r),this.replicatedActors?.delete?.(r),this.replicatedProperties?.delete?.(r))}setOwningConnection(e,t){this.actorConnection.set(e.id,t)}getOwningConnection(e){return this.actorConnection.get(e.id)}getActorsByOwningConnection(e){const t=[];return this.actorConnection.forEach((n,r)=>{if(n.id===e.id){const e=this.world.actors.find(e=>e.id===r);null!=e&&t.push(e)}}),t}resolveActorConnection(e){let t;for(;null==t&&null!=e;)t=this.actorConnection.get(e.id),null==t&&(e=e.owner);return t}isLocallyControlled(e){let t=e;for(;null!=t;){if(t.netRole===w.autonomousProxy)return!0;if(t instanceof U)return t.isLocallyControlled;t=e.owner}return!1}isLocalOwner(e){return this.isLocallyControlled(e)}sendServerTime(e){const t=new ArrayBuffer(9),n=new DataView(t);n.setUint8(0,P.serverTime),n.setBigUint64(1,BigInt(Date.now()),!0),this.session.sendMessage(e,!0,t)}parseServerTime(e){const t=new DataView(e).getBigUint64(1,!0);return Number(t)}getConnectionKey(e){return e.id.toString()}getPreSpawnMessageQueue(e,t){let n=this.actorPreSpawnMessageBuffer.get(e);null==n&&(n=new Map,this.actorPreSpawnMessageBuffer.set(e,n));const r=this.getConnectionKey(t);let s=n.get(r);return null==s&&(s=[],n.set(r,s)),s}shouldQueueMessageUntilActorReady(e,t){const n=this.actorPreSpawnMessageBuffer.get(e);return!!n?.has(this.getConnectionKey(t))||this.isServer&&!this.replicatedActors.has(e)&&this.shouldReplicate(e)}isPropertyMessage(e){const t=new DataView(e).getUint8(0);return t===P.prop||t===P.propComponent}getReplicatedPropertyKey(e,t){return null!=t?.__netid?`component:${t.__netid}:${e}`:`actor:${e}`}sendPropertySnapshot(e,t){const n=this.buildPropertySnapshotEntries(e,t);if(0===n.length)return;const r=this.createPropertySnapshotBuffer(e,n);this.session.sendMessage(t,!0,r)}buildPropertySnapshotEntries(e,t){if(!this.isRelevant(e,t))return[];const n=this.replicatedPropertyRegistry.get(e);if(null==n)return[];const r=[];for(const s of n){if(!this.shouldReplicatePropertyToConnection(e,s.replOn,t))continue;if(null!=s.component&&null==s.component.__netid)continue;const n=this.readReplicatedPropertyValue(s),o=this.serializer.encode(n),i=I.encode(o),c=i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength);r.push({property:s.property,component:s.component,buffer:c})}return r}shouldReplicatePropertyToConnection(e,t,n){const r=this.resolveActorConnection(e);switch(t){case b.all:return!0;case b.owner:return r?.id===n.id;case b.notOwner:return null==r||r.id!==n.id}}readReplicatedPropertyValue(e){const t=e.target[e.property];return A(t)?t.value:t}createPropertySnapshotBuffer(e,t){let n=7;const r=t.map(e=>I.encode(e.property));for(let e=0;e<t.length;e++){const s=t[e];n+=1,null!=s.component&&(n+=1),n+=1+r[e].byteLength+4+s.buffer.byteLength}const s=new ArrayBuffer(n),o=new DataView(s);let i=0;o.setUint8(i,P.propSnapshot),i+=1,o.setUint32(i,e.__netid,!0),i+=4,o.setUint16(i,t.length,!0),i+=2;for(let e=0;e<t.length;e++){const n=t[e],c=r[e],a=null!=n.component;o.setUint8(i,a?$.component:$.actor),i+=1,a&&(o.setUint8(i,n.component.__netid),i+=1),o.setUint8(i,c.byteLength),i+=1,new Uint8Array(s,i,c.byteLength).set(c),i+=c.byteLength,o.setUint32(i,n.buffer.byteLength,!0),i+=4,new Uint8Array(s,i,n.buffer.byteLength).set(new Uint8Array(n.buffer)),i+=n.buffer.byteLength}return s}decodeReplicatedValue(e){let t;if(null!=N)t=N.decode(e);else{t="";const n=new Uint8Array(e);for(let e=0;e<n.length;e++)t+=String.fromCharCode(n[e])}return this.serializer.decode(t,F)}applyReplicatedProperty(e,t,n){A(e[t])?e[t].value=n:e[t]=n}callRepNotify(e,t){const n=e[`onRep_${t}`];"function"==typeof n&&n.call(e)}};L=e([a()],L);export{L as NetService};const Q=new c,B=new i,I=new TextEncoder,N="undefined"!=typeof TextDecoder?new TextDecoder:void 0;function O(e,t,n){const r=new Uint8Array(e,t,n);if(null!=N)return N.decode(r);let s="";for(let e=0;e<r.length;e++)s+=String.fromCharCode(r[e]);return s}function D(e,t,n){new Uint8Array(e,t,n.byteLength).set(n)}const F=new m;/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type SignalDispose = () => void;
|
|
2
|
+
type SignalLike<T = unknown> = {
|
|
3
|
+
subscribe: (fn: (value: T) => void) => SignalDispose;
|
|
4
|
+
value: T;
|
|
5
|
+
};
|
|
6
|
+
export declare function isSignalLike<T = unknown>(value: unknown): value is SignalLike<T>;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=net-utils.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export declare enum ReplOn {
|
|
2
|
+
/**
|
|
3
|
+
* The property will be replicated on all connected clients.
|
|
4
|
+
* This is usually the default behavior.
|
|
5
|
+
*/
|
|
6
|
+
all = 0,
|
|
7
|
+
/**
|
|
8
|
+
* The property will be replicated on the owning client and server
|
|
9
|
+
*
|
|
10
|
+
* Example use case:
|
|
11
|
+
* - Information that should be hidden from other players such as
|
|
12
|
+
* remaining ammunition or active spell cooldown but needs to be
|
|
13
|
+
* known by the player and server.
|
|
14
|
+
*/
|
|
15
|
+
owner = 1,
|
|
16
|
+
/**
|
|
17
|
+
* The property will be replicated on all clients and server but
|
|
18
|
+
* not the owner.
|
|
19
|
+
*
|
|
20
|
+
* Example use case:
|
|
21
|
+
* - Certain state is already set on the owning client
|
|
22
|
+
* that could for example drive visual effects or sound.
|
|
23
|
+
* We exclude the owner to avoid unnecesary networking and
|
|
24
|
+
* triggering effective twice.
|
|
25
|
+
* - Movement state like isJumping used to control animation state
|
|
26
|
+
* machines, which is likely already set
|
|
27
|
+
* on the owning client for immediate feedback.
|
|
28
|
+
*/
|
|
29
|
+
notOwner = 2
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=replication.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decorator for marking a method as an RPC.
|
|
3
|
+
* @param reliable - If the call on remotes has to happen. Set to false for better performance is ok to lose some calls
|
|
4
|
+
*/
|
|
5
|
+
export declare function RunOnServer(reliable?: boolean): any;
|
|
6
|
+
/**
|
|
7
|
+
* Decorator for marking a method as an RPC.
|
|
8
|
+
* @param reliable - If the call on remotes has to happen. Set to false for better performance is ok to lose some calls
|
|
9
|
+
*/
|
|
10
|
+
export declare function RunOnClient(reliable?: boolean): any;
|
|
11
|
+
/**
|
|
12
|
+
* Decorator for marking a method as an RPC.
|
|
13
|
+
* @param reliable - If the call on remotes has to happen. Set to false for better performance is ok to lose some calls
|
|
14
|
+
*/
|
|
15
|
+
export declare function RunOnNotOwner(reliable?: boolean): any;
|
|
16
|
+
/**
|
|
17
|
+
* Decorator for marking a method as an RPC.
|
|
18
|
+
* @param reliable - If the call on remotes has to happen. Set to false for better performance is ok to lose some calls
|
|
19
|
+
*/
|
|
20
|
+
export declare function RunOnAll(reliable?: boolean): any;
|
|
21
|
+
//# sourceMappingURL=rpc-decorator.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{inject as n}from"../../inject.js";import{NetService as t}from"./net-service.js";import{registerRpcMethod as e,RunsOn as r}from"./rpc.js";import{BaseActor as o}from"../../actors/actor.js";import{NetMode as i}from"../net-session.js";import{ActorComponent as s}from"../../actors/component.js";export function RunOnServer(n=!0){return c(r.server,n)}export function RunOnClient(n=!0){return c(r.client,n)}export function RunOnNotOwner(n=!0){return c(r.notOwner,n)}export function RunOnAll(n=!0){return c(r.all,n)}function c(r,o=!0){return function(...i){if(i.length>=3){const[s,c,u]=i,a=u.value,f=c.toString();let p;return e(s,f),u.value=l(a,f,r,o,()=>(p??(p=n(t)),p)),u}const[s,c]=i,u=c.name.toString();let a;return c.addInitializer(function(){e(Object.getPrototypeOf(this),u),a=n(t)}),l(s,u,r,o,()=>(a??(a=n(t)),a))}}function l(n,t,e,c,l){return function(...u){const a=l();if(!(this instanceof o||this instanceof s))return void console.warn("RPC is defined on a non actor");let f,p;if(this instanceof o)f=this;else if(f=this.actor,p=this,null==f)return void console.warn("Can't call RPC on component before actor is set");let m,v=!1;return a.isServer&&(e===r.all||e===r.server||e===r.notOwner&&!a.isLocalOwner(f)&&a.mode===i.listenServer||e===r.client&&!a.isDedicatedServer&&a.isLocalOwner(f))?v=!0:a.isServer||e!==r.all&&e!==r.client&&e!==r.notOwner||(v=!0),v&&(m=n.apply(this,u)),a&&"function"==typeof a.sendRpc?a.sendRpc(e,c,f,t,u,p):console.warn("Net service is not set up",{netService:a}),m}}/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare enum RunsOn {
|
|
2
|
+
/**
|
|
3
|
+
* Runs on the owning client if sent from the server.
|
|
4
|
+
* Can be called on client as well and executes locally only.
|
|
5
|
+
*
|
|
6
|
+
* Example use case: correct player position
|
|
7
|
+
*/
|
|
8
|
+
client = 0,
|
|
9
|
+
/**
|
|
10
|
+
* Runs on clients (or listen server) if it is not the owner.
|
|
11
|
+
* Can only be called from the server.
|
|
12
|
+
* Does not run on dedicated server.
|
|
13
|
+
*
|
|
14
|
+
* Example use case: playing effects that already were played on the owning client
|
|
15
|
+
*/
|
|
16
|
+
notOwner = 1,
|
|
17
|
+
/**
|
|
18
|
+
* Runs on the server when sent from the client.
|
|
19
|
+
* Can be called on the server as well and executes locally only.
|
|
20
|
+
*
|
|
21
|
+
* Example use cases: process user input
|
|
22
|
+
*/
|
|
23
|
+
server = 2,
|
|
24
|
+
/**
|
|
25
|
+
* Runs on the server and all clients.
|
|
26
|
+
* If called on a client, it is only executed locally.
|
|
27
|
+
*
|
|
28
|
+
* May be used in combination with checking if not dedicated server
|
|
29
|
+
* to not perform unnecessary work that is purely visual.
|
|
30
|
+
*
|
|
31
|
+
* Example use cases: visual effects, playing sound, synchronize state
|
|
32
|
+
*/
|
|
33
|
+
all = 3
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=rpc.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export var RunsOn;!function(e){e[e.client=0]="client",e[e.notOwner=1]="notOwner",e[e.server=2]="server",e[e.all=3]="all"}(RunsOn||(RunsOn={}));const e=Symbol("rpc-method-registry");export function registerRpcMethod(n,o){const r=function(n){const o=Object.prototype.hasOwnProperty.call(n,e)?n[e]:void 0;if(null!=o)return o;const r=t(Object.getPrototypeOf(n)),s={methodNames:null!=r?[...r.methodNames]:[],methodIdsByName:null!=r?new Map(r.methodIdsByName):new Map};return Object.defineProperty(n,e,{value:s}),s}(n),s=r.methodIdsByName.get(o);if(null!=s)return s;if(r.methodNames.length>=256)return void console.warn(`Too many RPC methods registered on ${function(e){return e.constructor?.name??"target"}(n)}. A maximum of 256 methods can be encoded.`);const m=r.methodNames.length;return r.methodNames.push(o),r.methodIdsByName.set(o,m),m}export function getRpcMethodId(e,n){return t(e)?.methodIdsByName.get(n)}export function getRpcMethodName(e,n){return t(e)?.methodNames[n]}function t(t){let n=t;for(;null!=n;){const t=Object.prototype.hasOwnProperty.call(n,e)?n[e]:void 0;if(null!=t)return t;n=Object.getPrototypeOf(n)}}/*
|
|
2
|
+
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
|
+
* See the LICENSE.md file for details.
|
|
4
|
+
*/
|
|
@@ -9,6 +9,7 @@ import { ShaderImpl } from '../../shader/shader.js';
|
|
|
9
9
|
import type { ShaderGraphDocument } from '../../shader/graph/model.js';
|
|
10
10
|
import { Sequence } from '../../effects/sequence/sequence-data.js';
|
|
11
11
|
import { DataAssetRef } from '../../scene/objects/data-asset.js';
|
|
12
|
+
import { Type } from '../../utils/type.js';
|
|
12
13
|
export declare class AssetLoader {
|
|
13
14
|
protected assetResourceLoader: AssetResourceLoader;
|
|
14
15
|
protected assetService: AssetsProvider;
|
|
@@ -24,6 +25,7 @@ export declare class AssetLoader {
|
|
|
24
25
|
private ktx2Loader;
|
|
25
26
|
private textureLoader;
|
|
26
27
|
private audioLoader;
|
|
28
|
+
private animationVariantIds;
|
|
27
29
|
constructor(assetResourceLoader: AssetResourceLoader, assetService: AssetsProvider, shaders: ShaderImpl[]);
|
|
28
30
|
/**
|
|
29
31
|
* @param filePath
|
|
@@ -44,13 +46,19 @@ export declare class AssetLoader {
|
|
|
44
46
|
getModelByAssetName(name: string): Promise<LoadedMesh>;
|
|
45
47
|
getModelByAssetId(id: AssetId): Promise<LoadedMesh>;
|
|
46
48
|
getAnimationClipByAssetId(id: AssetId): Promise<THREE.AnimationClip | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Resolve an animation reference for a concrete target rig without running a
|
|
51
|
+
* retarget solver. A mismatched source clip must already have a generated
|
|
52
|
+
* output recorded by an Animation Retargeter asset.
|
|
53
|
+
*/
|
|
54
|
+
getAnimationClipForTargetByAssetId(id: AssetId, targetRigId?: AssetId): Promise<THREE.AnimationClip | null>;
|
|
47
55
|
getAnimationClipByAssetName(name: string): Promise<THREE.AnimationClip | null>;
|
|
48
56
|
getTextureByAssetName(name: string): Promise<THREE.Texture>;
|
|
49
57
|
getTextureByAssetId(id: AssetId): Promise<THREE.Texture>;
|
|
50
58
|
getSequenceById(id: AssetId): Promise<Sequence>;
|
|
51
59
|
getSequenceByName(name: string): Promise<Sequence>;
|
|
52
|
-
getDataAssetById<T = unknown>(id: AssetId): Promise<DataAssetRef<T> | null>;
|
|
53
|
-
getDataAssetByName<T = unknown>(name: string): Promise<DataAssetRef<T> | null>;
|
|
60
|
+
getDataAssetById<T = unknown>(id: AssetId, type?: Type<T>): Promise<DataAssetRef<T> | null>;
|
|
61
|
+
getDataAssetByName<T = unknown>(name: string, type?: Type<T>): Promise<DataAssetRef<T> | null>;
|
|
54
62
|
getShaderGraphByAssetId(id: AssetId): Promise<ShaderGraphDocument>;
|
|
55
63
|
prepareShaderGraphParameters(graph: ShaderGraphDocument, params?: Record<string, any>): Promise<Record<string, unknown>>;
|
|
56
64
|
getMaterialByAssetId(id: AssetId): Promise<Material>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate as e,__metadata as
|
|
1
|
+
import{__decorate as e,__metadata as t}from"tslib";import{AudioLoader as s,LoadingManager as a,TextureLoader as r}from"three";import{FBXLoader as i,GLTFLoader as n,MTLLoader as o,OBJLoader as h,TGALoader as d}from"three-stdlib";import{KTX2Loader as c}from"three/examples/jsm/Addons.js";import{Service as l}from"typedi";import{AssetResourceLoader as u}from"../../scene/asset-resource-loader.js";import{applyMaterial as w}from"../../scene/materializer";import{materialFromAsset as g,materializeDataAssetRef as f,prepareShaderGraphParameters as m}from"../../scene/materializer.js";import{Prefab as y}from"../../scene/objects/prefab.js";import{pathJoin as A}from"../../utils/files.js";import{Sequence as p}from"../../effects/sequence/sequence-data.js";import{resolveAnimationClipAssetForTarget as b}from"../animation/retarget.js";let v=class{constructor(e,t,l){this.assetResourceLoader=e,this.assetService=t,this.shaders=l,this.baseUrl="",this.urlSuffix="",this.loadingManager=new a,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new i(this.loadingManager),this.objLoader=new h(this.loadingManager),this.mtlLoader=new o(this.loadingManager),this.tgaLoader=new d(this.loadingManager),this.ktx2Loader=new c(this.loadingManager),this.textureLoader=new r(this.loadingManager),this.audioLoader=new s(this.loadingManager),this.animationVariantIds=new Map,this.assetResourceLoader.materialProvider=e=>this.getMaterialByAssetId(e),this.assetResourceLoader.animationRigProvider=async e=>(await this.assetService.getAsset(e))?.animationRig}resolvePath(e){return A(this.baseUrl,e)+this.urlSuffix}getAudioAtPath(e){const t=this.resolvePath(e);return this.audioLoader.loadAsync(t)}async getAudioByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No audio could be found with asset id ${e}`);return this.assetResourceLoader.getAudio(t)}async getAudioByAssetName(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No audio could be found with asset name ${e}`);return this.assetResourceLoader.getAudio(t)}async getModelAtPath(e){const t=this.resolvePath(e);switch(e.split(".").pop().toLowerCase()){case"glb":case"gltf":return(await this.glbLoader.loadAsync(t)).scene;case"fbx":return this.fbxLoader.loadAsync(t);case"obj":return this.objLoader.loadAsync(t);default:throw new Error(`File suffix is not supperted in file ${e}`)}}async getGltfAtPath(e){const t=this.resolvePath(e);return this.glbLoader.loadAsync(t)}async getModelByAssetName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No model could be found with asset name ${e}`);return this.assetResourceLoader.getMesh(t,{applyMaterials:!0,materialResolver:e=>this.getMaterialByAssetId(e)})}async getModelByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No model could be found with asset id ${e}`);return this.assetResourceLoader.getMesh(t,{applyMaterials:!0,materialResolver:e=>this.getMaterialByAssetId(e)})}async getAnimationClipByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No animation clip could be found with asset id ${e}`);return this.assetResourceLoader.getAnimationClip(t)}async getAnimationClipForTargetByAssetId(e,t){const s=await this.assetService.getAsset(e);if(null==s)throw new Error(`No animation clip could be found with asset id ${e}`);let a=s;if(null!=t&&s.anim?.rigId!==t){const r=`${e}|${t}`,i=this.animationVariantIds.get(r);null!=i?a=await this.assetService.getAsset(i):(a=b(s,await this.assetService.getAssets(),t),this.animationVariantIds.set(r,a.id))}return this.assetResourceLoader.getAnimationClip(a)}async getAnimationClipByAssetName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No animation clip could be found with asset name ${e}`);return this.assetResourceLoader.getAnimationClip(t)}async applyMaterials(e,t){for(const s of e.materialAssignments??[])await w(t,s,async e=>this.getMaterialByAssetId(e))}async getTextureByAssetName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No texture could be found with asset name ${e}`);return this.assetResourceLoader.getTexture(t)}async getTextureByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No texture could be found with asset id ${e}`);return this.assetResourceLoader.getTexture(t)}async getSequenceById(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No sequence could be found with asset id ${e}`);if(null==t.sequence)throw new Error(`Missing sequence data in asset ${e}`);return new p(t.sequence)}async getSequenceByName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==t)throw new Error(`No sequence could be found with asset name ${e}`);if(null==t.sequence)throw new Error(`Missing sequence data in asset ${e}`);return new p(t.sequence)}async getDataAssetById(e,t){const s=await f(e,this.assetService,this.assetResourceLoader,void 0,void 0,this.shaders);if(null!=t&&null!=s&&!(s.value instanceof t))throw new Error(`Invalid type. Expecting asset with id ${e} to be of type ${t.name} but got:`+s.value);return s}async getDataAssetByName(e,t){const s=(await this.assetService.getAssets()).find(t=>t.name===e);if(null==s)throw new Error(`No data asset could be found with name ${e}`);return this.getDataAssetById(s.id,t)}async getShaderGraphByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No shader graph could be found with asset id ${e}`);if("shaderGraph"!==t.type||null==t.shaderGraph)throw new Error(`Missing shader graph data in asset ${e}`);return t.shaderGraph}async prepareShaderGraphParameters(e,t={}){return m(t,e,this.assetService,this.assetResourceLoader,void 0,this.shaders)}async getMaterialByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No material could be found with asset id ${e}`);return g(t,null,this.assetService,this.assetResourceLoader,this.shaders,!1)}async getAsset(e){return this.assetService.getAsset(e)}async getPrefabByName(e){const t=(await this.assetService.getAssets()).find(t=>t.name===e);if("prefab"!==t.type)throw`Asset with name ${e} is not a prefab`;return new y(t)}async getPrefabById(e){const t=await this.getAsset(e);if("prefab"!==t.type)throw`Asset with name ${name} is not a prefab`;return new y(t)}clearCache(e){this.animationVariantIds.clear(),this.assetResourceLoader.clearCache(e)}clearCacheById(e){this.animationVariantIds.clear(),this.assetResourceLoader.clearCacheById(e)}};v=e([l(),t("design:paramtypes",[u,Function,Array])],v);export{v as AssetLoader};/*
|
|
2
2
|
* Copyright (©) 2026 Hology Interactive AB. All rights reserved.
|
|
3
3
|
* See the LICENSE.md file for details.
|
|
4
4
|
*/
|