@momo2555/koppeliajs 0.0.161 → 0.0.163
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/components/ResizableText.svelte +24 -6
- package/dist/scripts/console.d.ts +89 -32
- package/dist/scripts/console.js +174 -68
- package/dist/scripts/customCallback.d.ts +18 -0
- package/dist/scripts/customCallback.js +22 -4
- package/dist/scripts/device.d.ts +47 -12
- package/dist/scripts/device.js +49 -19
- package/dist/scripts/koppelia.d.ts +157 -37
- package/dist/scripts/koppelia.js +160 -49
- package/dist/scripts/koppeliaWebsocket.d.ts +33 -28
- package/dist/scripts/koppeliaWebsocket.js +37 -41
- package/dist/scripts/message.d.ts +46 -29
- package/dist/scripts/message.js +47 -31
- package/dist/scripts/option.d.ts +26 -11
- package/dist/scripts/option.js +26 -14
- package/dist/scripts/play.d.ts +46 -4
- package/dist/scripts/play.js +46 -4
- package/dist/scripts/resident.d.ts +19 -0
- package/dist/scripts/resident.js +21 -1
- package/dist/scripts/song.d.ts +36 -0
- package/dist/scripts/song.js +36 -0
- package/dist/scripts/stage.d.ts +29 -0
- package/dist/scripts/stage.js +29 -2
- package/dist/scripts/state.d.ts +26 -9
- package/dist/scripts/state.js +28 -14
- package/dist/stores/routeStore.d.ts +13 -0
- package/dist/stores/routeStore.js +23 -13
- package/package.json +1 -1
|
@@ -1,26 +1,44 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
2
|
+
import { routeType } from '../stores/routeStore.js';
|
|
3
3
|
import { Koppelia } from '../scripts/koppelia.js';
|
|
4
|
+
import { onDestroy } from 'svelte';
|
|
4
5
|
|
|
5
6
|
export let id: string = '';
|
|
6
|
-
|
|
7
|
+
export let defaultFontSize: number = 10;
|
|
7
8
|
|
|
8
9
|
$: fontSize = defaultFontSize;
|
|
10
|
+
$: callbackId = "";
|
|
9
11
|
|
|
10
12
|
let koppelia = Koppelia.instance;
|
|
11
|
-
|
|
13
|
+
|
|
12
14
|
koppelia.onReady(async () => {
|
|
13
|
-
await koppelia.
|
|
15
|
+
let resizableTexts = await koppelia.getResizableTexts();
|
|
16
|
+
let resizableExist = false;
|
|
17
|
+
for (let rt of resizableTexts) {
|
|
18
|
+
if (rt.id !== undefined && rt.id == id) {
|
|
19
|
+
if (rt.fontSize !== undefined) {
|
|
20
|
+
fontSize = rt.fontSize;
|
|
21
|
+
}
|
|
22
|
+
resizableExist = true;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (!resizableExist) {
|
|
27
|
+
await koppelia.registerNewResizableText(id, defaultFontSize);
|
|
28
|
+
}
|
|
29
|
+
callbackId = koppelia.onResizableTextChanged(id, (newFontSize: number) => {
|
|
14
30
|
fontSize = newFontSize;
|
|
15
31
|
});
|
|
16
32
|
});
|
|
17
33
|
|
|
34
|
+
onDestroy(() => {
|
|
35
|
+
koppelia.unsubResizableText(callbackId);
|
|
36
|
+
});
|
|
18
37
|
</script>
|
|
19
38
|
|
|
20
39
|
<div class="resizable-text" id="resizable-text-{id}" style="font-size: {fontSize}px;">
|
|
21
|
-
|
|
40
|
+
<slot />
|
|
22
41
|
</div>
|
|
23
42
|
|
|
24
43
|
<style>
|
|
25
|
-
|
|
26
44
|
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Message, type MessageData, PeerType } from
|
|
3
|
-
import type { AnyState } from
|
|
1
|
+
import { type Callback, KoppeliaWebsocket } from "./koppeliaWebsocket.js";
|
|
2
|
+
import { Message, type MessageData, PeerType } from "./message.js";
|
|
3
|
+
import type { AnyState } from "./state.js";
|
|
4
4
|
export type ChangeStateCallback = (from: string, state: AnyState, update: boolean) => void;
|
|
5
5
|
export type ChangeStageCallback = (from: string, stage: string) => void;
|
|
6
6
|
export type DataExchangeCallback = (from: string, data: any) => void;
|
|
@@ -11,7 +11,8 @@ export type AnyRequestCallback = (request: string, params: {
|
|
|
11
11
|
}, from: string, address: string) => void;
|
|
12
12
|
export type MediaResponseData = string | Blob | ArrayBuffer | any;
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Handles the Koppelia console connection, facilitating the sending and receiving of requests
|
|
15
|
+
* and managing event subscriptions for state changes, device data, and custom logic.
|
|
15
16
|
*/
|
|
16
17
|
export declare class Console {
|
|
17
18
|
consoleHostname: string;
|
|
@@ -22,62 +23,115 @@ export declare class Console {
|
|
|
22
23
|
private _deviceDataHandlers;
|
|
23
24
|
private _dataExchangeHandlers;
|
|
24
25
|
private _anyRequestHandlers;
|
|
25
|
-
private _ready;
|
|
26
26
|
private _onReadyCallback;
|
|
27
|
+
private _ready;
|
|
27
28
|
private _mediaApiUrl;
|
|
28
29
|
constructor();
|
|
29
30
|
/**
|
|
30
|
-
*
|
|
31
|
-
* @
|
|
32
|
-
|
|
31
|
+
* Generates a unique random ID used for registering and tracking callbacks.
|
|
32
|
+
* @returns A randomly generated string ID.
|
|
33
|
+
*/
|
|
34
|
+
private _generateId;
|
|
35
|
+
/**
|
|
36
|
+
* Unsubscribes a previously registered callback using its unique ID.
|
|
37
|
+
* @param id The subscription identifier returned by any "on..." listener function.
|
|
38
|
+
* @returns True if the ID was found and successfully removed, false otherwise.
|
|
39
|
+
*/
|
|
40
|
+
unsubscribeCallback(id: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Dispatches a message through the console socket.
|
|
43
|
+
* The routing source is automatically appended based on the current application state.
|
|
44
|
+
* @param message The message payload to send.
|
|
45
|
+
* @param callback Optional callback triggered when the WebSocket receives a specific response.
|
|
33
46
|
*/
|
|
34
47
|
sendMessage(message: Message, callback?: Callback): void;
|
|
35
48
|
/**
|
|
36
|
-
*
|
|
37
|
-
* @param peer
|
|
49
|
+
* Identifies the current client application (controller or monitor) to the console.
|
|
50
|
+
* @param peer The peer type to identify as.
|
|
38
51
|
*/
|
|
39
52
|
identify(peer: PeerType): void;
|
|
53
|
+
/**
|
|
54
|
+
* Retrieves the list of connected devices.
|
|
55
|
+
* @todo Implementation pending.
|
|
56
|
+
*/
|
|
40
57
|
getConnectedDevices(): void;
|
|
41
58
|
/**
|
|
42
|
-
*
|
|
43
|
-
* @param receiver
|
|
44
|
-
* @param data
|
|
59
|
+
* Transmits data payload directly to a specific peer type.
|
|
60
|
+
* @param receiver The target peer intended to receive the data.
|
|
61
|
+
* @param data The data payload to transmit.
|
|
45
62
|
*/
|
|
46
63
|
sendDataTo(receiver: PeerType, data: MessageData): void;
|
|
47
64
|
/**
|
|
48
|
-
*
|
|
49
|
-
* @param callback
|
|
65
|
+
* Registers a callback to execute whenever a new state is received from the console.
|
|
66
|
+
* @param callback The function to execute on state change.
|
|
67
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
68
|
+
*/
|
|
69
|
+
onStateChange(callback: ChangeStateCallback): string;
|
|
70
|
+
/**
|
|
71
|
+
* Registers a callback to execute whenever the current application stage changes.
|
|
72
|
+
* @param callback The function to execute on stage change.
|
|
73
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
74
|
+
*/
|
|
75
|
+
onStageChange(callback: ChangeStageCallback): string;
|
|
76
|
+
/**
|
|
77
|
+
* Registers a callback to execute when the console connection is fully established and ready.
|
|
78
|
+
* If the console is already ready at the time of calling, the callback is executed immediately.
|
|
79
|
+
* @param callback The function to execute upon readiness.
|
|
80
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
50
81
|
*/
|
|
51
|
-
|
|
82
|
+
onReady(callback: () => void): string;
|
|
52
83
|
/**
|
|
53
|
-
*
|
|
54
|
-
* @param callback
|
|
84
|
+
* Registers a callback to listen for specific device events.
|
|
85
|
+
* @param callback The function to execute when a device event occurs.
|
|
86
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
55
87
|
*/
|
|
56
|
-
|
|
88
|
+
onDeviceEvent(callback: DeviceEventCallback): string;
|
|
57
89
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* @
|
|
90
|
+
* Registers a callback to listen for raw data exchanges between peers.
|
|
91
|
+
* @param callback The function to execute upon receiving exchanged data.
|
|
92
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
61
93
|
*/
|
|
62
|
-
|
|
63
|
-
onDeviceEvent(callback: DeviceEventCallback): void;
|
|
64
|
-
onDataExchange(callback: DataExchangeCallback): void;
|
|
65
|
-
onRequest(callback: AnyRequestCallback): void;
|
|
94
|
+
onDataExchange(callback: DataExchangeCallback): string;
|
|
66
95
|
/**
|
|
67
|
-
*
|
|
96
|
+
* Registers a generic callback to intercept and handle custom or unrecognized requests.
|
|
97
|
+
* @param callback The function to execute for generic requests.
|
|
98
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
99
|
+
*/
|
|
100
|
+
onRequest(callback: AnyRequestCallback): string;
|
|
101
|
+
/**
|
|
102
|
+
* Gets the current readiness state of the console WebSocket connection.
|
|
68
103
|
*/
|
|
69
104
|
get ready(): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Constructs the full URL for a media asset based on the API port and hostname.
|
|
107
|
+
* @param path The relative path to the media asset.
|
|
108
|
+
* @returns The fully qualified URL string.
|
|
109
|
+
*/
|
|
70
110
|
getMediaUrl(path: string): string;
|
|
71
111
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* @
|
|
112
|
+
* Normalizes a media URL to ensure cross-client compatibility.
|
|
113
|
+
* Corrects edge cases where media links cached in game states by one client (e.g., controller)
|
|
114
|
+
* fail when accessed by another (e.g., monitor).
|
|
115
|
+
* @param mediaUrl The raw URL string to fix.
|
|
116
|
+
* @returns The corrected and standardized URL string.
|
|
77
117
|
*/
|
|
78
118
|
fixMediaUrl(mediaUrl: string): string;
|
|
119
|
+
/**
|
|
120
|
+
* Fetches a media asset from the API and automatically parses it based on its Content-Type.
|
|
121
|
+
* @param path The relative path to the media asset.
|
|
122
|
+
* @returns A promise resolving to the parsed data (JSON, Text, Blob, or ArrayBuffer).
|
|
123
|
+
* @throws Will throw an error if the HTTP request fails.
|
|
124
|
+
*/
|
|
79
125
|
getMedia(path: string): Promise<MediaResponseData>;
|
|
126
|
+
/**
|
|
127
|
+
* Initializes core WebSocket event listeners and maps them to the internal handlers.
|
|
128
|
+
*/
|
|
80
129
|
private _initEvents;
|
|
130
|
+
/**
|
|
131
|
+
* Core router for incoming WebSocket data. Decodes the message type and
|
|
132
|
+
* dispatches it to the corresponding internal execution loops.
|
|
133
|
+
* @param request The parsed Message object received from the socket.
|
|
134
|
+
*/
|
|
81
135
|
private _processReceivedData;
|
|
82
136
|
private _execDeviceDataHandlers;
|
|
83
137
|
private _execDeviceEventHandlers;
|
|
@@ -85,5 +139,8 @@ export declare class Console {
|
|
|
85
139
|
private _execChangeStageHandlers;
|
|
86
140
|
private _execDataExchangeHandlers;
|
|
87
141
|
private _execAnyRequestHandlers;
|
|
142
|
+
/**
|
|
143
|
+
* Hard-resets the application by clearing all registered event handlers.
|
|
144
|
+
*/
|
|
88
145
|
destroyEvents(): void;
|
|
89
146
|
}
|
package/dist/scripts/console.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { KoppeliaWebsocket } from
|
|
2
|
-
import { Message,
|
|
3
|
-
import { page } from
|
|
4
|
-
import { get } from
|
|
5
|
-
import { routeType } from
|
|
6
|
-
import { logger } from
|
|
1
|
+
import { KoppeliaWebsocket } from "./koppeliaWebsocket.js";
|
|
2
|
+
import { Message, MessageType, PeerType } from "./message.js";
|
|
3
|
+
import { page } from "$app/stores";
|
|
4
|
+
import { get } from "svelte/store";
|
|
5
|
+
import { routeType } from "../stores/routeStore.js";
|
|
6
|
+
import { logger } from "./logger.js";
|
|
7
7
|
const PORT = 2225;
|
|
8
8
|
const API_PORT = 8000;
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Handles the Koppelia console connection, facilitating the sending and receiving of requests
|
|
11
|
+
* and managing event subscriptions for state changes, device data, and custom logic.
|
|
11
12
|
*/
|
|
12
13
|
export class Console {
|
|
13
14
|
consoleHostname = "";
|
|
@@ -18,8 +19,8 @@ export class Console {
|
|
|
18
19
|
_deviceDataHandlers;
|
|
19
20
|
_dataExchangeHandlers;
|
|
20
21
|
_anyRequestHandlers;
|
|
21
|
-
_ready = false;
|
|
22
22
|
_onReadyCallback;
|
|
23
|
+
_ready = false;
|
|
23
24
|
_mediaApiUrl;
|
|
24
25
|
constructor() {
|
|
25
26
|
this.consoleHostname = "";
|
|
@@ -30,44 +31,96 @@ export class Console {
|
|
|
30
31
|
this.consoleSocket = new KoppeliaWebsocket(consoleUrl);
|
|
31
32
|
this._mediaApiUrl = "http://" + this.consoleHostname + ":" + API_PORT;
|
|
32
33
|
this._ready = false;
|
|
33
|
-
this._changeStateHandlers =
|
|
34
|
-
this._changeStageHandlers =
|
|
35
|
-
this._deviceEventHandlers =
|
|
36
|
-
this._deviceDataHandlers =
|
|
37
|
-
this._dataExchangeHandlers =
|
|
38
|
-
this._onReadyCallback =
|
|
39
|
-
this._anyRequestHandlers =
|
|
34
|
+
this._changeStateHandlers = {};
|
|
35
|
+
this._changeStageHandlers = {};
|
|
36
|
+
this._deviceEventHandlers = {};
|
|
37
|
+
this._deviceDataHandlers = {};
|
|
38
|
+
this._dataExchangeHandlers = {};
|
|
39
|
+
this._onReadyCallback = {};
|
|
40
|
+
this._anyRequestHandlers = {};
|
|
40
41
|
this._initEvents();
|
|
41
42
|
}
|
|
42
43
|
/**
|
|
43
|
-
*
|
|
44
|
-
* @
|
|
45
|
-
|
|
44
|
+
* Generates a unique random ID used for registering and tracking callbacks.
|
|
45
|
+
* @returns A randomly generated string ID.
|
|
46
|
+
*/
|
|
47
|
+
_generateId() {
|
|
48
|
+
return Math.random().toString(36).substring(2, 15) +
|
|
49
|
+
Math.random().toString(36).substring(2, 15);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Unsubscribes a previously registered callback using its unique ID.
|
|
53
|
+
* @param id The subscription identifier returned by any "on..." listener function.
|
|
54
|
+
* @returns True if the ID was found and successfully removed, false otherwise.
|
|
55
|
+
*/
|
|
56
|
+
unsubscribeCallback(id) {
|
|
57
|
+
let deleted = false;
|
|
58
|
+
if (id in this._changeStateHandlers) {
|
|
59
|
+
delete this._changeStateHandlers[id];
|
|
60
|
+
deleted = true;
|
|
61
|
+
}
|
|
62
|
+
if (id in this._changeStageHandlers) {
|
|
63
|
+
delete this._changeStageHandlers[id];
|
|
64
|
+
deleted = true;
|
|
65
|
+
}
|
|
66
|
+
if (id in this._deviceEventHandlers) {
|
|
67
|
+
delete this._deviceEventHandlers[id];
|
|
68
|
+
deleted = true;
|
|
69
|
+
}
|
|
70
|
+
if (id in this._deviceDataHandlers) {
|
|
71
|
+
delete this._deviceDataHandlers[id];
|
|
72
|
+
deleted = true;
|
|
73
|
+
}
|
|
74
|
+
if (id in this._dataExchangeHandlers) {
|
|
75
|
+
delete this._dataExchangeHandlers[id];
|
|
76
|
+
deleted = true;
|
|
77
|
+
}
|
|
78
|
+
if (id in this._anyRequestHandlers) {
|
|
79
|
+
delete this._anyRequestHandlers[id];
|
|
80
|
+
deleted = true;
|
|
81
|
+
}
|
|
82
|
+
if (id in this._onReadyCallback) {
|
|
83
|
+
delete this._onReadyCallback[id];
|
|
84
|
+
deleted = true;
|
|
85
|
+
}
|
|
86
|
+
return deleted;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Dispatches a message through the console socket.
|
|
90
|
+
* The routing source is automatically appended based on the current application state.
|
|
91
|
+
* @param message The message payload to send.
|
|
92
|
+
* @param callback Optional callback triggered when the WebSocket receives a specific response.
|
|
46
93
|
*/
|
|
47
94
|
sendMessage(message, callback) {
|
|
48
95
|
let route = PeerType.NONE;
|
|
49
|
-
if (get(routeType) == "monitor")
|
|
96
|
+
if (get(routeType) == "monitor") {
|
|
50
97
|
route = PeerType.MONITOR;
|
|
51
|
-
|
|
98
|
+
}
|
|
99
|
+
else if (get(routeType) == "controller") {
|
|
52
100
|
route = PeerType.CONTROLLER;
|
|
101
|
+
}
|
|
53
102
|
message.setSource(route, "");
|
|
54
103
|
this.consoleSocket.send(message, callback);
|
|
55
104
|
}
|
|
56
105
|
/**
|
|
57
|
-
*
|
|
58
|
-
* @param peer
|
|
106
|
+
* Identifies the current client application (controller or monitor) to the console.
|
|
107
|
+
* @param peer The peer type to identify as.
|
|
59
108
|
*/
|
|
60
109
|
identify(peer) {
|
|
61
110
|
let req = new Message();
|
|
62
111
|
req.setIdentification(peer);
|
|
63
112
|
this.consoleSocket.send(req);
|
|
64
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Retrieves the list of connected devices.
|
|
116
|
+
* @todo Implementation pending.
|
|
117
|
+
*/
|
|
65
118
|
getConnectedDevices() {
|
|
66
119
|
}
|
|
67
120
|
/**
|
|
68
|
-
*
|
|
69
|
-
* @param receiver
|
|
70
|
-
* @param data
|
|
121
|
+
* Transmits data payload directly to a specific peer type.
|
|
122
|
+
* @param receiver The target peer intended to receive the data.
|
|
123
|
+
* @param data The data payload to transmit.
|
|
71
124
|
*/
|
|
72
125
|
sendDataTo(receiver, data) {
|
|
73
126
|
let req = new Message();
|
|
@@ -75,56 +128,93 @@ export class Console {
|
|
|
75
128
|
req.setDestination(receiver);
|
|
76
129
|
}
|
|
77
130
|
/**
|
|
78
|
-
*
|
|
79
|
-
* @param callback
|
|
131
|
+
* Registers a callback to execute whenever a new state is received from the console.
|
|
132
|
+
* @param callback The function to execute on state change.
|
|
133
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
80
134
|
*/
|
|
81
135
|
onStateChange(callback) {
|
|
82
|
-
this.
|
|
136
|
+
const id = this._generateId();
|
|
137
|
+
this._changeStateHandlers[id] = callback;
|
|
138
|
+
return id;
|
|
83
139
|
}
|
|
84
140
|
/**
|
|
85
|
-
*
|
|
86
|
-
* @param callback
|
|
141
|
+
* Registers a callback to execute whenever the current application stage changes.
|
|
142
|
+
* @param callback The function to execute on stage change.
|
|
143
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
87
144
|
*/
|
|
88
145
|
onStageChange(callback) {
|
|
89
|
-
this.
|
|
146
|
+
const id = this._generateId();
|
|
147
|
+
this._changeStageHandlers[id] = callback;
|
|
148
|
+
return id;
|
|
90
149
|
}
|
|
91
150
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* @param callback
|
|
151
|
+
* Registers a callback to execute when the console connection is fully established and ready.
|
|
152
|
+
* If the console is already ready at the time of calling, the callback is executed immediately.
|
|
153
|
+
* @param callback The function to execute upon readiness.
|
|
154
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
95
155
|
*/
|
|
96
156
|
onReady(callback) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
157
|
+
const id = this._generateId();
|
|
158
|
+
if (!this._ready) {
|
|
159
|
+
this._onReadyCallback[id] = callback;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
100
162
|
callback();
|
|
163
|
+
}
|
|
164
|
+
return id;
|
|
101
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Registers a callback to listen for specific device events.
|
|
168
|
+
* @param callback The function to execute when a device event occurs.
|
|
169
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
170
|
+
*/
|
|
102
171
|
onDeviceEvent(callback) {
|
|
103
|
-
this.
|
|
172
|
+
const id = this._generateId();
|
|
173
|
+
this._deviceEventHandlers[id] = callback;
|
|
174
|
+
return id;
|
|
104
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Registers a callback to listen for raw data exchanges between peers.
|
|
178
|
+
* @param callback The function to execute upon receiving exchanged data.
|
|
179
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
180
|
+
*/
|
|
105
181
|
onDataExchange(callback) {
|
|
106
|
-
this.
|
|
182
|
+
const id = this._generateId();
|
|
183
|
+
this._dataExchangeHandlers[id] = callback;
|
|
184
|
+
return id;
|
|
107
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Registers a generic callback to intercept and handle custom or unrecognized requests.
|
|
188
|
+
* @param callback The function to execute for generic requests.
|
|
189
|
+
* @returns The unique subscription ID used for unsubscribing.
|
|
190
|
+
*/
|
|
108
191
|
onRequest(callback) {
|
|
109
|
-
this.
|
|
192
|
+
const id = this._generateId();
|
|
193
|
+
this._anyRequestHandlers[id] = callback;
|
|
194
|
+
return id;
|
|
110
195
|
}
|
|
111
196
|
/**
|
|
112
|
-
*
|
|
197
|
+
* Gets the current readiness state of the console WebSocket connection.
|
|
113
198
|
*/
|
|
114
199
|
get ready() {
|
|
115
200
|
return this._ready;
|
|
116
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Constructs the full URL for a media asset based on the API port and hostname.
|
|
204
|
+
* @param path The relative path to the media asset.
|
|
205
|
+
* @returns The fully qualified URL string.
|
|
206
|
+
*/
|
|
117
207
|
getMediaUrl(path) {
|
|
118
208
|
if (!path.startsWith("/"))
|
|
119
209
|
path = "/" + path;
|
|
120
210
|
return this._mediaApiUrl + path;
|
|
121
211
|
}
|
|
122
212
|
/**
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* @
|
|
213
|
+
* Normalizes a media URL to ensure cross-client compatibility.
|
|
214
|
+
* Corrects edge cases where media links cached in game states by one client (e.g., controller)
|
|
215
|
+
* fail when accessed by another (e.g., monitor).
|
|
216
|
+
* @param mediaUrl The raw URL string to fix.
|
|
217
|
+
* @returns The corrected and standardized URL string.
|
|
128
218
|
*/
|
|
129
219
|
fixMediaUrl(mediaUrl) {
|
|
130
220
|
let url = new URL(mediaUrl);
|
|
@@ -133,6 +223,12 @@ export class Console {
|
|
|
133
223
|
fixedurl.search = url.search;
|
|
134
224
|
return fixedurl.toString();
|
|
135
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Fetches a media asset from the API and automatically parses it based on its Content-Type.
|
|
228
|
+
* @param path The relative path to the media asset.
|
|
229
|
+
* @returns A promise resolving to the parsed data (JSON, Text, Blob, or ArrayBuffer).
|
|
230
|
+
* @throws Will throw an error if the HTTP request fails.
|
|
231
|
+
*/
|
|
136
232
|
async getMedia(path) {
|
|
137
233
|
const response = await fetch(this.getMediaUrl(path));
|
|
138
234
|
if (!response.ok) {
|
|
@@ -140,22 +236,26 @@ export class Console {
|
|
|
140
236
|
}
|
|
141
237
|
const contentType = response.headers.get("Content-Type") || "";
|
|
142
238
|
if (contentType.includes("application/json")) {
|
|
143
|
-
return await response.json();
|
|
239
|
+
return await response.json();
|
|
144
240
|
}
|
|
145
241
|
else if (contentType.startsWith("text/")) {
|
|
146
|
-
return await response.text();
|
|
242
|
+
return await response.text();
|
|
147
243
|
}
|
|
148
|
-
else if (contentType.startsWith("image/") ||
|
|
149
|
-
|
|
244
|
+
else if (contentType.startsWith("image/") ||
|
|
245
|
+
contentType.includes("application/octet-stream")) {
|
|
246
|
+
return await response.blob();
|
|
150
247
|
}
|
|
151
248
|
else {
|
|
152
|
-
return await response.arrayBuffer();
|
|
249
|
+
return await response.arrayBuffer();
|
|
153
250
|
}
|
|
154
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Initializes core WebSocket event listeners and maps them to the internal handlers.
|
|
254
|
+
*/
|
|
155
255
|
_initEvents() {
|
|
156
256
|
this.consoleSocket.onOpen(() => {
|
|
157
257
|
this._ready = true;
|
|
158
|
-
for (let callback of this._onReadyCallback) {
|
|
258
|
+
for (let callback of Object.values(this._onReadyCallback)) {
|
|
159
259
|
callback();
|
|
160
260
|
}
|
|
161
261
|
});
|
|
@@ -163,12 +263,17 @@ export class Console {
|
|
|
163
263
|
this._processReceivedData(request);
|
|
164
264
|
});
|
|
165
265
|
}
|
|
266
|
+
/**
|
|
267
|
+
* Core router for incoming WebSocket data. Decodes the message type and
|
|
268
|
+
* dispatches it to the corresponding internal execution loops.
|
|
269
|
+
* @param request The parsed Message object received from the socket.
|
|
270
|
+
*/
|
|
166
271
|
_processReceivedData(request) {
|
|
167
|
-
logger.log("
|
|
168
|
-
if (request.header.type === undefined)
|
|
272
|
+
logger.log("Received new data from console", request);
|
|
273
|
+
if (request.header.type === undefined) {
|
|
169
274
|
return;
|
|
275
|
+
}
|
|
170
276
|
let type = request.header.type;
|
|
171
|
-
/* Handle specific requests */
|
|
172
277
|
if (type == MessageType.REQUEST) {
|
|
173
278
|
switch (request.request.exec) {
|
|
174
279
|
case "changeState":
|
|
@@ -183,53 +288,54 @@ export class Console {
|
|
|
183
288
|
break;
|
|
184
289
|
}
|
|
185
290
|
}
|
|
186
|
-
/* Handle data exchange */
|
|
187
291
|
else if (type == MessageType.DATA_EXCHANGE) {
|
|
188
292
|
this._execDataExchangeHandlers(request.header.from, request.data);
|
|
189
293
|
}
|
|
190
|
-
/* Handle device event */
|
|
191
294
|
else if (type == MessageType.DEVICE_EVENT) {
|
|
192
295
|
this._execDeviceEventHandlers(request.header.device, request.header.from_addr, request.event);
|
|
193
296
|
}
|
|
194
|
-
/* Handle device data */
|
|
195
297
|
else if (type == MessageType.DEVICE_DATA) {
|
|
196
298
|
this._execDeviceDataHandlers(request.header.from_addr, request.data);
|
|
197
299
|
}
|
|
198
300
|
}
|
|
301
|
+
// --- Dictionary execution methods below ---
|
|
199
302
|
_execDeviceDataHandlers(from_addr, data) {
|
|
200
|
-
for (let handler of this._deviceDataHandlers) {
|
|
303
|
+
for (let handler of Object.values(this._deviceDataHandlers)) {
|
|
201
304
|
handler(from_addr, data);
|
|
202
305
|
}
|
|
203
306
|
}
|
|
204
307
|
_execDeviceEventHandlers(device, from_addr, event) {
|
|
205
|
-
for (let handler of this._deviceEventHandlers) {
|
|
308
|
+
for (let handler of Object.values(this._deviceEventHandlers)) {
|
|
206
309
|
handler(device, from_addr, event);
|
|
207
310
|
}
|
|
208
311
|
}
|
|
209
312
|
_execChangeStateHandlers(from, state, update) {
|
|
210
|
-
for (let handler of this._changeStateHandlers) {
|
|
313
|
+
for (let handler of Object.values(this._changeStateHandlers)) {
|
|
211
314
|
handler(from, state, update);
|
|
212
315
|
}
|
|
213
316
|
}
|
|
214
317
|
_execChangeStageHandlers(from, stage) {
|
|
215
|
-
for (let handler of this._changeStageHandlers) {
|
|
318
|
+
for (let handler of Object.values(this._changeStageHandlers)) {
|
|
216
319
|
handler(from, stage);
|
|
217
320
|
}
|
|
218
321
|
}
|
|
219
322
|
_execDataExchangeHandlers(from, data) {
|
|
220
|
-
for (let handler of this._dataExchangeHandlers) {
|
|
323
|
+
for (let handler of Object.values(this._dataExchangeHandlers)) {
|
|
221
324
|
handler(from, data);
|
|
222
325
|
}
|
|
223
326
|
}
|
|
224
327
|
_execAnyRequestHandlers(request, params, from, address) {
|
|
225
|
-
for (let handler of this._anyRequestHandlers) {
|
|
328
|
+
for (let handler of Object.values(this._anyRequestHandlers)) {
|
|
226
329
|
handler(request, params, from, address);
|
|
227
330
|
}
|
|
228
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* Hard-resets the application by clearing all registered event handlers.
|
|
334
|
+
*/
|
|
229
335
|
destroyEvents() {
|
|
230
|
-
this._deviceEventHandlers =
|
|
231
|
-
this._deviceDataHandlers =
|
|
232
|
-
this._anyRequestHandlers =
|
|
233
|
-
logger.log("
|
|
336
|
+
this._deviceEventHandlers = {};
|
|
337
|
+
this._deviceDataHandlers = {};
|
|
338
|
+
this._anyRequestHandlers = {};
|
|
339
|
+
logger.log("Destroyed event handlers");
|
|
234
340
|
}
|
|
235
341
|
}
|
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import type { Console } from "./console.js";
|
|
2
|
+
/**
|
|
3
|
+
* Manages the registration and network-wide execution of custom callbacks.
|
|
4
|
+
* Allows different nodes in the system to broadcast and react to custom function calls.
|
|
5
|
+
*/
|
|
2
6
|
export declare class CustomCallbacks {
|
|
3
7
|
private _console;
|
|
4
8
|
private _customCallbacks;
|
|
5
9
|
constructor(console: Console);
|
|
10
|
+
/**
|
|
11
|
+
* Broadcasts a request across the network to execute a registered custom callback.
|
|
12
|
+
* @param name The registered name of the custom callback to trigger.
|
|
13
|
+
* @param args A dictionary of arguments to pass to the callback function.
|
|
14
|
+
*/
|
|
6
15
|
runCustomCallback(name: string, args: {
|
|
7
16
|
[key: string]: any;
|
|
8
17
|
}): void;
|
|
18
|
+
/**
|
|
19
|
+
* Registers a local function to be executed when a specific custom callback request is received.
|
|
20
|
+
* @param name The identifier name for this callback.
|
|
21
|
+
* @param callback The function to execute when triggered by the network.
|
|
22
|
+
*/
|
|
9
23
|
registerCustomCallback(name: string, callback: (args: {
|
|
10
24
|
[key: string]: any;
|
|
11
25
|
}) => void): void;
|
|
26
|
+
/**
|
|
27
|
+
* Removes a previously registered custom callback from the local listener registry.
|
|
28
|
+
* @param name The identifier name of the callback to remove.
|
|
29
|
+
*/
|
|
12
30
|
unregisterCustomCallback(name: string): void;
|
|
13
31
|
}
|