@dcl/sdk 7.29.1-36863326504.commit-aa54c50 → 7.30.1-37783952461.commit-52fa56c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/explorer-ui/index.d.ts +118 -0
  2. package/explorer-ui/index.js +235 -0
  3. package/internal/transports/rendererTransport.js +2 -5
  4. package/network/binary-message-bus.d.ts +3 -6
  5. package/network/binary-message-bus.js +5 -9
  6. package/network/index.d.ts +2 -8
  7. package/network/index.js +3 -16
  8. package/network/message-bus-sync.d.ts +3 -16
  9. package/network/message-bus-sync.js +103 -164
  10. package/network/state.js +5 -3
  11. package/package.json +6 -6
  12. package/src/explorer-ui/index.ts +398 -0
  13. package/src/internal/transports/rendererTransport.ts +1 -4
  14. package/src/network/binary-message-bus.ts +4 -9
  15. package/src/network/index.ts +3 -40
  16. package/src/network/message-bus-sync.ts +112 -180
  17. package/src/network/state.ts +4 -3
  18. package/atom.d.ts +0 -19
  19. package/atom.js +0 -83
  20. package/future.d.ts +0 -8
  21. package/future.js +0 -26
  22. package/network/chunking.d.ts +0 -5
  23. package/network/chunking.js +0 -38
  24. package/network/events/implementation.d.ts +0 -93
  25. package/network/events/implementation.js +0 -221
  26. package/network/events/index.d.ts +0 -42
  27. package/network/events/index.js +0 -43
  28. package/network/events/protocol.d.ts +0 -27
  29. package/network/events/protocol.js +0 -66
  30. package/network/events/registry.d.ts +0 -8
  31. package/network/events/registry.js +0 -3
  32. package/network/server/index.d.ts +0 -14
  33. package/network/server/index.js +0 -256
  34. package/network/server/utils.d.ts +0 -18
  35. package/network/server/utils.js +0 -135
  36. package/server/env-var.d.ts +0 -15
  37. package/server/env-var.js +0 -31
  38. package/server/index.d.ts +0 -2
  39. package/server/index.js +0 -3
  40. package/server/storage/constants.d.ts +0 -80
  41. package/server/storage/constants.js +0 -19
  42. package/server/storage/error-message.d.ts +0 -1
  43. package/server/storage/error-message.js +0 -9
  44. package/server/storage/index.d.ts +0 -54
  45. package/server/storage/index.js +0 -60
  46. package/server/storage/player.d.ts +0 -60
  47. package/server/storage/player.js +0 -244
  48. package/server/storage/scene.d.ts +0 -55
  49. package/server/storage/scene.js +0 -232
  50. package/server/storage/serialize.d.ts +0 -1
  51. package/server/storage/serialize.js +0 -135
  52. package/server/storage/value-cache.d.ts +0 -1
  53. package/server/storage/value-cache.js +0 -67
  54. package/server/storage/write-queue.d.ts +0 -1
  55. package/server/storage/write-queue.js +0 -113
  56. package/server/storage-url.d.ts +0 -13
  57. package/server/storage-url.js +0 -42
  58. package/server/utils.d.ts +0 -35
  59. package/server/utils.js +0 -69
  60. package/src/atom.ts +0 -98
  61. package/src/future.ts +0 -38
  62. package/src/network/chunking.ts +0 -45
  63. package/src/network/events/implementation.ts +0 -271
  64. package/src/network/events/index.ts +0 -48
  65. package/src/network/events/protocol.ts +0 -94
  66. package/src/network/events/registry.ts +0 -18
  67. package/src/network/server/index.ts +0 -341
  68. package/src/network/server/utils.ts +0 -189
  69. package/src/server/env-var.ts +0 -36
  70. package/src/server/index.ts +0 -12
  71. package/src/server/storage/constants.ts +0 -112
  72. package/src/server/storage/error-message.ts +0 -8
  73. package/src/server/storage/index.ts +0 -83
  74. package/src/server/storage/player.ts +0 -345
  75. package/src/server/storage/scene.ts +0 -324
  76. package/src/server/storage/serialize.ts +0 -132
  77. package/src/server/storage/value-cache.ts +0 -119
  78. package/src/server/storage/write-queue.ts +0 -174
  79. package/src/server/storage-url.ts +0 -49
  80. package/src/server/utils.ts +0 -83
@@ -0,0 +1,398 @@
1
+ import {
2
+ engine,
3
+ ExplorerItemPurchaseResult,
4
+ ExplorerUi,
5
+ ExplorerUiEventsResult,
6
+ GrowOnlyValueSetComponentDefinition,
7
+ IEngine,
8
+ PBExplorerItemPurchaseResult,
9
+ PBExplorerUiEventsResult
10
+ } from '@dcl/ecs'
11
+ import { openExplorerUi, OpenExplorerUiResult } from '~system/RestrictedActions'
12
+
13
+ export { ExplorerUi, OpenExplorerUiResult }
14
+
15
+ // What an explorer that does not echo request_id, or a user-initiated action, leaves on the wire.
16
+ const UNCORRELATED = 0
17
+
18
+ // Panels that can be on screen next to another panel. The `ui` field alone cannot attribute
19
+ // their events, so an event on one of these panels must carry a request_id.
20
+ const CONCURRENT_PANELS: readonly ExplorerUi[] = [ExplorerUi.EU_ITEM_PURCHASE]
21
+
22
+ /** @public */
23
+ export type CorrelatedEvent = {
24
+ timestamp: number
25
+ requestId: number
26
+ }
27
+
28
+ /**
29
+ * A named stream of events that this helper can collect and stop on.
30
+ * @public
31
+ */
32
+ export type Channel<N extends string = string, T extends CorrelatedEvent = CorrelatedEvent> = {
33
+ readonly name: N
34
+ readonly component: GrowOnlyValueSetComponentDefinition<T>
35
+ }
36
+
37
+ /** @public */
38
+ export type AnyChannel = Channel<string, any>
39
+
40
+ /**
41
+ * Wraps a grow-only result component as a {@link Channel}. The name must be unique within a scene.
42
+ * @public
43
+ */
44
+ export function channel<N extends string, T extends CorrelatedEvent>(
45
+ name: N,
46
+ component: GrowOnlyValueSetComponentDefinition<T>
47
+ ): Channel<N, T> {
48
+ return { name, component }
49
+ }
50
+
51
+ /** Panel lifecycle events: opened and closed. @public */
52
+ export const ExplorerUiEvents: Channel<'explorerUi', PBExplorerUiEventsResult> = /* @__PURE__ */ channel(
53
+ 'explorerUi',
54
+ ExplorerUiEventsResult
55
+ )
56
+
57
+ /** Outcome of an `EU_ITEM_PURCHASE` flow: purchased, dismissed or failed. @public */
58
+ export const ItemPurchase: Channel<'itemPurchase', PBExplorerItemPurchaseResult> = /* @__PURE__ */ channel(
59
+ 'itemPurchase',
60
+ ExplorerItemPurchaseResult
61
+ )
62
+
63
+ /**
64
+ * The `$case` names of a channel's event union.
65
+ * @public
66
+ */
67
+ export type CaseOf<C extends AnyChannel> =
68
+ C extends Channel<any, infer T> ? Extract<T[keyof T], { $case: string }>['$case'] : never
69
+
70
+ /** @public */
71
+ export type Variant<C extends AnyChannel = AnyChannel, K extends string = string> = {
72
+ readonly channel: C
73
+ readonly $case: K
74
+ }
75
+
76
+ /** @public */
77
+ export function variant<C extends AnyChannel, K extends CaseOf<C>>(ch: C, $case: K): Variant<C, K> {
78
+ return { channel: ch, $case }
79
+ }
80
+
81
+ /**
82
+ * What ends the wait before the panel closes: any event on a channel, or one `$case` of it.
83
+ * @public
84
+ */
85
+ export type StopCondition = AnyChannel | Variant
86
+
87
+ /** @public */
88
+ export type Collected<C> = C extends Channel<infer N, infer T> ? { channel: N; event: T } : never
89
+
90
+ /**
91
+ * How the wait ended.
92
+ * - `closed`: the panel this call opened was closed.
93
+ * - `matched`: `until` fired first, so the panel may still be on screen.
94
+ * - `notOpened`: this call did not open anything. `openResult` says why.
95
+ * - `timedOut`: `timeoutMs` elapsed first.
96
+ *
97
+ * `events` always holds everything collected, the event that stopped the wait included.
98
+ * @public
99
+ */
100
+ export type WaitOutcome<C extends readonly AnyChannel[]> =
101
+ | { $case: 'closed'; events: readonly Collected<C[number]>[] }
102
+ | { $case: 'matched'; events: readonly Collected<C[number]>[] }
103
+ | { $case: 'notOpened'; openResult: OpenExplorerUiResult }
104
+ | { $case: 'timedOut'; events: readonly Collected<C[number]>[] }
105
+
106
+ /** @public */
107
+ export type WaitOptions<C extends readonly AnyChannel[]> = {
108
+ /** Channels whose events land in `events`. Defaults to none. */
109
+ collect?: C
110
+ /** Stops the wait early. The panel closing always stops it regardless. */
111
+ until?: StopCondition
112
+ /**
113
+ * Bounds the wait, in milliseconds. On expiry the promise resolves with `$case: 'timedOut'`.
114
+ * No default, because a panel can stay open for minutes. Without it, an explorer that opens
115
+ * a panel and then emits no `closed` leaves the promise pending for the scene's whole life.
116
+ */
117
+ timeoutMs?: number
118
+ }
119
+
120
+ /** @public */
121
+ export type OpenExplorerUiRequest =
122
+ | { ui: Exclude<ExplorerUi, ExplorerUi.EU_ITEM_PURCHASE>; itemPurchase?: undefined }
123
+ | { ui: ExplorerUi.EU_ITEM_PURCHASE; itemPurchase: { urn: string } }
124
+
125
+ /**
126
+ * Signature of {@link openExplorerUiAndWait}. The second overload takes a bare `ui`, so a
127
+ * computed panel value needs no narrowing.
128
+ * @public
129
+ */
130
+ export interface OpenExplorerUiAndWait {
131
+ <const C extends readonly AnyChannel[] = []>(
132
+ request: OpenExplorerUiRequest,
133
+ options?: WaitOptions<C>
134
+ ): Promise<WaitOutcome<C>>
135
+ (ui: Exclude<ExplorerUi, ExplorerUi.EU_ITEM_PURCHASE>): Promise<WaitOutcome<[]>>
136
+ }
137
+
138
+ /** @internal exposed for tests */
139
+ export const EXPLORER_UI_WAIT_TIMEOUT_SYSTEM = 'explorer-ui-wait-timeout'
140
+
141
+ // Lowest priority sorts this system last, so when it removes itself mid-tick it splices the
142
+ // last element of the array the engine is iterating and skips no other system.
143
+ const TIMEOUT_SYSTEM_PRIORITY = Number.MIN_SAFE_INTEGER
144
+
145
+ type OpenExplorerUiFn = (body: {
146
+ ui: ExplorerUi
147
+ requestId?: number
148
+ itemPurchase?: { urn: string }
149
+ }) => Promise<{ openResult: OpenExplorerUiResult }>
150
+
151
+ type CollectedEvent = { channel: string; event: CorrelatedEvent }
152
+
153
+ type Session = {
154
+ requestId: number
155
+ ui: ExplorerUi
156
+ correlationRequired: boolean
157
+ collect: ReadonlySet<string>
158
+ watched: ReadonlySet<string>
159
+ until: { channel: string; $case: string | undefined } | undefined
160
+ events: CollectedEvent[]
161
+ timeoutMs: number | undefined
162
+ elapsedMs: number
163
+ settled: boolean
164
+ settle: (outcome: WaitOutcome<never[]>) => void
165
+ fail: (error: Error) => void
166
+ }
167
+
168
+ type Attribution = 'yes' | 'no' | 'ambiguous'
169
+
170
+ // ts-proto renders a `oneof` as one wrapper property `{ $case, [$case]: value }`. Finding that
171
+ // property by shape keeps the helper independent of the name each message gave it: `event` on
172
+ // one message, `status` on another.
173
+ function caseOf(event: CorrelatedEvent): string | undefined {
174
+ for (const key of Object.keys(event)) {
175
+ const value = (event as unknown as Record<string, unknown>)[key]
176
+ if (value && typeof value === 'object' && typeof (value as { $case?: unknown }).$case === 'string') {
177
+ return (value as { $case: string }).$case
178
+ }
179
+ }
180
+ return undefined
181
+ }
182
+
183
+ function normalizeStop(stop: StopCondition): { channel: AnyChannel; $case: string | undefined } {
184
+ return '$case' in stop ? { channel: stop.channel, $case: stop.$case } : { channel: stop, $case: undefined }
185
+ }
186
+
187
+ /** @internal test seam. The production instance is {@link openExplorerUiAndWait}. */
188
+ export function create(deps: {
189
+ engine: IEngine
190
+ openExplorerUi: OpenExplorerUiFn
191
+ explorerUiEvents: Channel<'explorerUi', PBExplorerUiEventsResult>
192
+ }) {
193
+ const { engine: engineInstance, openExplorerUi: openExplorerUiFn, explorerUiEvents } = deps
194
+ const root = engineInstance.RootEntity
195
+
196
+ const sessions = new Map<number, Session>()
197
+ // Keyed by name, so two wrappers around the same component arm one listener, not two.
198
+ const armed = new Map<string, GrowOnlyValueSetComponentDefinition<any>>()
199
+ // Starts at 1 so a minted id never collides with UNCORRELATED.
200
+ let nextRequestId = 1
201
+ let timeoutSystemAdded = false
202
+
203
+ function arm(ch: AnyChannel) {
204
+ const bound = armed.get(ch.name)
205
+ if (bound) {
206
+ if (bound !== ch.component) {
207
+ throw new Error(
208
+ `openExplorerUiAndWait: channel name '${ch.name}' is already bound to a different component. ` +
209
+ `Channel names identify a stream, so they have to be unique within a scene.`
210
+ )
211
+ }
212
+ return
213
+ }
214
+ armed.set(ch.name, ch.component)
215
+ const name = ch.name
216
+ // onChange has no unsubscribe, so one listener per channel lives for the engine's lifetime.
217
+ ch.component.onChange(root, (value: CorrelatedEvent | undefined) => {
218
+ // `undefined` arrives on DELETE_ENTITY. Otherwise `value` is one appended element,
219
+ // not the whole set.
220
+ if (value) deliver(name, value)
221
+ })
222
+ }
223
+
224
+ function attribute(session: Session, name: string, event: CorrelatedEvent): Attribution {
225
+ if (event.requestId === session.requestId) return 'yes'
226
+ if (event.requestId !== UNCORRELATED) return 'no'
227
+ // Only the lifecycle channel carries a second discriminator, `ui`, and it identifies a
228
+ // session only while panels cannot coexist. A second call for the same panel is answered
229
+ // WAS_ALREADY_OPEN, so at most one session per non-concurrent panel is ever live.
230
+ if (session.correlationRequired || name !== explorerUiEvents.name) return 'ambiguous'
231
+ return (event as PBExplorerUiEventsResult).ui === session.ui ? 'yes' : 'no'
232
+ }
233
+
234
+ function deliver(name: string, event: CorrelatedEvent) {
235
+ // Settling deletes from `sessions` mid-iteration, which a Map tolerates. Nothing adds.
236
+ for (const session of sessions.values()) {
237
+ if (!session.watched.has(name)) continue
238
+ const attribution = attribute(session, name, event)
239
+ if (attribution === 'no') continue
240
+ if (attribution === 'ambiguous') {
241
+ failSession(
242
+ session,
243
+ new Error(
244
+ `openExplorerUiAndWait: got a '${name}' event with no request_id, and nothing else identifies ` +
245
+ `the call it belongs to. This explorer does not echo OpenExplorerUiRequest.request_id.`
246
+ )
247
+ )
248
+ continue
249
+ }
250
+ accept(session, name, event)
251
+ }
252
+ }
253
+
254
+ function accept(session: Session, name: string, event: CorrelatedEvent) {
255
+ if (session.collect.has(name)) session.events.push({ channel: name, event })
256
+
257
+ // The close is terminal and wins over `until`, because `matched` would tell the caller
258
+ // that the panel is still on screen.
259
+ if (name === explorerUiEvents.name && caseOf(event) === 'closed') {
260
+ settleSession(session, { $case: 'closed', events: session.events as never[] })
261
+ return
262
+ }
263
+
264
+ const until = session.until
265
+ if (!until || until.channel !== name) return
266
+ if (until.$case === undefined || until.$case === caseOf(event)) {
267
+ settleSession(session, { $case: 'matched', events: session.events as never[] })
268
+ }
269
+ }
270
+
271
+ function settleSession(session: Session, outcome: WaitOutcome<never[]>) {
272
+ if (session.settled) return
273
+ session.settled = true
274
+ sessions.delete(session.requestId)
275
+ session.settle(outcome)
276
+ maybeRemoveTimeoutSystem()
277
+ }
278
+
279
+ function failSession(session: Session, error: Error) {
280
+ if (session.settled) return
281
+ session.settled = true
282
+ sessions.delete(session.requestId)
283
+ session.fail(error)
284
+ maybeRemoveTimeoutSystem()
285
+ }
286
+
287
+ function hasTimedSession(): boolean {
288
+ for (const session of sessions.values()) {
289
+ if (session.timeoutMs !== undefined) return true
290
+ }
291
+ return false
292
+ }
293
+
294
+ function maybeRemoveTimeoutSystem() {
295
+ if (!timeoutSystemAdded || hasTimedSession()) return
296
+ timeoutSystemAdded = false
297
+ engineInstance.removeSystem(EXPLORER_UI_WAIT_TIMEOUT_SYSTEM)
298
+ }
299
+
300
+ function ensureTimeoutSystem() {
301
+ if (timeoutSystemAdded) return
302
+ timeoutSystemAdded = true
303
+ // The scene runtime has no timers, so elapsed time is accumulated from the engine's dt.
304
+ engineInstance.addSystem(
305
+ (dt: number) => {
306
+ for (const session of sessions.values()) {
307
+ if (session.timeoutMs === undefined) continue
308
+ session.elapsedMs += dt * 1000
309
+ if (session.elapsedMs >= session.timeoutMs) {
310
+ settleSession(session, { $case: 'timedOut', events: session.events as never[] })
311
+ }
312
+ }
313
+ maybeRemoveTimeoutSystem()
314
+ },
315
+ TIMEOUT_SYSTEM_PRIORITY,
316
+ EXPLORER_UI_WAIT_TIMEOUT_SYSTEM
317
+ )
318
+ }
319
+
320
+ async function openExplorerUiAndWait(
321
+ request: OpenExplorerUiRequest | Exclude<ExplorerUi, ExplorerUi.EU_ITEM_PURCHASE>,
322
+ options?: WaitOptions<readonly AnyChannel[]>
323
+ ): Promise<WaitOutcome<never[]>> {
324
+ const { ui, itemPurchase } = typeof request === 'number' ? { ui: request, itemPurchase: undefined } : request
325
+ const requestId = nextRequestId++
326
+
327
+ const collect = options?.collect ?? []
328
+ const collectNames = new Set<string>()
329
+ for (const ch of collect) collectNames.add(ch.name)
330
+
331
+ const stop = options?.until ? normalizeStop(options.until) : undefined
332
+ const watched = new Set<string>(collectNames)
333
+ watched.add(explorerUiEvents.name)
334
+ if (stop) watched.add(stop.channel.name)
335
+
336
+ // Armed before the RPC, because events can land while the RPC is in flight. A listener
337
+ // that is already up is what makes replaying the accumulated set unnecessary.
338
+ arm(explorerUiEvents)
339
+ for (const ch of collect) arm(ch)
340
+ if (stop) arm(stop.channel)
341
+
342
+ let settle!: (outcome: WaitOutcome<never[]>) => void
343
+ let fail!: (error: Error) => void
344
+ const outcome = new Promise<WaitOutcome<never[]>>((resolve, reject) => {
345
+ settle = resolve
346
+ fail = reject
347
+ })
348
+
349
+ const session: Session = {
350
+ requestId,
351
+ ui,
352
+ correlationRequired: CONCURRENT_PANELS.includes(ui),
353
+ collect: collectNames,
354
+ watched,
355
+ until: stop ? { channel: stop.channel.name, $case: stop.$case } : undefined,
356
+ events: [],
357
+ timeoutMs: options?.timeoutMs,
358
+ elapsedMs: 0,
359
+ settled: false,
360
+ settle,
361
+ fail
362
+ }
363
+ sessions.set(requestId, session)
364
+ if (session.timeoutMs !== undefined) ensureTimeoutSystem()
365
+
366
+ try {
367
+ const { openResult } = await openExplorerUiFn({ ui, requestId, itemPurchase })
368
+ // This call opened nothing, so no event carrying this request id is coming.
369
+ if (openResult !== OpenExplorerUiResult.OPENED) {
370
+ settleSession(session, { $case: 'notOpened', openResult })
371
+ }
372
+ } catch (error) {
373
+ // Routed through the session rather than rethrown, so that `outcome` is never left
374
+ // pending and unobserved.
375
+ failSession(session, error as Error)
376
+ }
377
+
378
+ return outcome
379
+ }
380
+
381
+ // The implementation takes both argument forms and is blind to `collect`. The cast is what
382
+ // gives callers the two overloads that relate them.
383
+ return { openExplorerUiAndWait: openExplorerUiAndWait as OpenExplorerUiAndWait }
384
+ }
385
+
386
+ const helper = /* @__PURE__ */ create({ engine, openExplorerUi, explorerUiEvents: ExplorerUiEvents })
387
+
388
+ /**
389
+ * Opens an explorer panel and waits for the session it started. The wait ends when the panel
390
+ * closes. See {@link WaitOptions} to collect events, to stop earlier or to bound the wait.
391
+ *
392
+ * Every lifecycle outcome resolves, see {@link WaitOutcome}. The promise rejects only when an
393
+ * event cannot be attributed to a call at all: an explorer too old to echo `request_id`
394
+ * paired with a panel that can coexist with another one.
395
+ *
396
+ * @public
397
+ */
398
+ export const openExplorerUiAndWait: OpenExplorerUiAndWait = helper.openExplorerUiAndWait
@@ -41,10 +41,7 @@ export function createRendererTransport(engineApi: EngineApiForTransport): Trans
41
41
  }
42
42
  return !!message
43
43
  },
44
- type: 'renderer',
45
- // The renderer/host is the authority for reserved-range entities (avatars,
46
- // root/player/camera): it is the only transport allowed to mutate or delete them.
47
- allowReservedEntities: true
44
+ type: 'renderer'
48
45
  }
49
46
 
50
47
  return rendererTransport
@@ -1,12 +1,9 @@
1
1
  import { ReadWriteByteBuffer } from '@dcl/ecs/dist/serialization/ByteBuffer'
2
2
 
3
3
  export enum CommsMessage {
4
- CRDT = 7,
5
- REQ_CRDT_STATE = 8,
6
- RES_CRDT_STATE = 9,
7
- CRDT_SERVER = 4,
8
- CRDT_AUTHORITATIVE = 5,
9
- CUSTOM_EVENT = 6
4
+ CRDT = 1,
5
+ REQ_CRDT_STATE = 2,
6
+ RES_CRDT_STATE = 3
10
7
  }
11
8
 
12
9
  export function BinaryMessageBus<T extends CommsMessage>(
@@ -23,9 +20,7 @@ export function BinaryMessageBus<T extends CommsMessage>(
23
20
  __processMessages: (messages: Uint8Array[]) => {
24
21
  for (const message of messages) {
25
22
  const commsMsg = decodeCommsMessage<T>(message)
26
- if (!commsMsg) {
27
- continue
28
- }
23
+ if (!commsMsg) continue
29
24
  const { sender, messageType, data } = commsMsg
30
25
  const fn = mapping.get(messageType)
31
26
  if (fn) fn(data, sender)
@@ -2,46 +2,9 @@ import { sendBinary } from '~system/CommunicationsController'
2
2
  import { engine } from '@dcl/ecs'
3
3
  import { addSyncTransport } from './message-bus-sync'
4
4
  import { getUserData } from '~system/UserIdentity'
5
- import { isServer as isServerApi } from '~system/EngineApi'
6
- import { Atom } from '../atom'
7
-
8
- // Create isServer atom for consistent state
9
- const isServerAtom = Atom<boolean>(false)
10
- void isServerApi({}).then((response) => {
11
- isServerAtom.swap(!!response.isServer)
12
- })
13
-
14
- // Helper function to check if running on server
15
- export function isServer(): boolean {
16
- return isServerAtom.getOrNull() ?? false
17
- }
18
5
 
19
6
  // initialize sync transport for sdk engine
20
- const {
21
- getChildren,
22
- syncEntity,
23
- parentEntity,
24
- getParent,
25
- myProfile,
26
- removeParent,
27
- getFirstChild,
28
- isStateSyncronized,
29
- binaryMessageBus,
30
- eventBus
31
- } = addSyncTransport(engine, sendBinary, getUserData, isServerApi, 'network')
32
-
33
- // Re-export the room messaging system
34
- export { registerMessages, getRoom } from './events'
7
+ const { getChildren, syncEntity, parentEntity, getParent, myProfile, removeParent, getFirstChild, isStateSyncronized } =
8
+ addSyncTransport(engine, sendBinary, getUserData)
35
9
 
36
- export {
37
- getFirstChild,
38
- getChildren,
39
- syncEntity,
40
- parentEntity,
41
- getParent,
42
- myProfile,
43
- removeParent,
44
- isStateSyncronized,
45
- binaryMessageBus,
46
- eventBus
47
- }
10
+ export { getFirstChild, getChildren, syncEntity, parentEntity, getParent, myProfile, removeParent, isStateSyncronized }