@dcl/sdk 7.0.0-3548419522.commit-ddcf4b7 → 7.0.0

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 (75) hide show
  1. package/ecs.d.ts +1 -0
  2. package/ecs.js +2 -0
  3. package/index.d.ts +1 -0
  4. package/index.js +11 -0
  5. package/internal/Observable.d.ts +36 -0
  6. package/internal/Observable.js +190 -0
  7. package/internal/transports/networkTransport.d.ts +2 -0
  8. package/internal/transports/networkTransport.js +16 -0
  9. package/internal/transports/rendererTransport.d.ts +7 -0
  10. package/internal/transports/rendererTransport.js +39 -0
  11. package/math.d.ts +3 -0
  12. package/math.js +4 -0
  13. package/messageBus.d.ts +10 -0
  14. package/messageBus.js +43 -0
  15. package/observables.d.ts +225 -0
  16. package/observables.js +75 -0
  17. package/package.json +12 -18
  18. package/react-ecs.d.ts +3 -0
  19. package/react-ecs.js +4 -0
  20. package/src/ecs.ts +1 -0
  21. package/src/index.ts +18 -0
  22. package/src/internal/Observable.ts +425 -0
  23. package/src/internal/transports/networkTransport.ts +24 -0
  24. package/src/internal/transports/rendererTransport.ts +60 -0
  25. package/src/math.ts +3 -0
  26. package/src/messageBus.ts +62 -0
  27. package/src/observables.ts +579 -0
  28. package/src/react-ecs.ts +3 -0
  29. package/tsconfig.json +11 -0
  30. package/types/tsconfig.ecs7.json +3 -8
  31. package/dist/ecs7/index.d.ts +0 -4679
  32. package/dist/ecs7/index.js +0 -15202
  33. package/dist/ecs7/index.min.js +0 -1
  34. package/dist/ecs7/index.min.js.map +0 -1
  35. package/dist/ecs7/proto-definitions/README.md +0 -32
  36. package/dist/ecs7/proto-definitions/Transform.md +0 -25
  37. package/dist/ecs7/proto-definitions/animator.proto +0 -19
  38. package/dist/ecs7/proto-definitions/audio_source.proto +0 -13
  39. package/dist/ecs7/proto-definitions/audio_stream.proto +0 -11
  40. package/dist/ecs7/proto-definitions/avatar_attach.proto +0 -19
  41. package/dist/ecs7/proto-definitions/avatar_modifier_area.proto +0 -19
  42. package/dist/ecs7/proto-definitions/avatar_shape.proto +0 -32
  43. package/dist/ecs7/proto-definitions/billboard.proto +0 -17
  44. package/dist/ecs7/proto-definitions/camera_mode.proto +0 -10
  45. package/dist/ecs7/proto-definitions/camera_mode_area.proto +0 -14
  46. package/dist/ecs7/proto-definitions/common/camera_type.proto +0 -8
  47. package/dist/ecs7/proto-definitions/common/id.md +0 -2
  48. package/dist/ecs7/proto-definitions/common/id.proto +0 -8
  49. package/dist/ecs7/proto-definitions/common/input_action.proto +0 -20
  50. package/dist/ecs7/proto-definitions/common/texts.proto +0 -20
  51. package/dist/ecs7/proto-definitions/gltf_container.proto +0 -13
  52. package/dist/ecs7/proto-definitions/material.proto +0 -56
  53. package/dist/ecs7/proto-definitions/mesh_collider.proto +0 -35
  54. package/dist/ecs7/proto-definitions/mesh_renderer.proto +0 -30
  55. package/dist/ecs7/proto-definitions/nft_shape.proto +0 -40
  56. package/dist/ecs7/proto-definitions/pointer_events_result.proto +0 -25
  57. package/dist/ecs7/proto-definitions/pointer_hover_feedback.proto +0 -31
  58. package/dist/ecs7/proto-definitions/pointer_lock.proto +0 -9
  59. package/dist/ecs7/proto-definitions/raycast.proto +0 -20
  60. package/dist/ecs7/proto-definitions/raycast_result.proto +0 -25
  61. package/dist/ecs7/proto-definitions/text_shape.proto +0 -33
  62. package/dist/ecs7/proto-definitions/ui_background.proto +0 -11
  63. package/dist/ecs7/proto-definitions/ui_text.proto +0 -17
  64. package/dist/ecs7/proto-definitions/ui_transform.proto +0 -141
  65. package/dist/ecs7/proto-definitions/visibility_component.proto +0 -9
  66. package/dist/playground/snippets/billboard.ts +0 -108
  67. package/dist/playground/snippets/cube-spawner.ts +0 -39
  68. package/dist/playground/snippets/info.json +0 -1
  69. package/dist/playground/snippets/material.ts +0 -48
  70. package/dist/playground/snippets/mesh.ts +0 -68
  71. package/dist/playground/snippets/pointer-events.ts +0 -50
  72. package/dist/playground/snippets/raycast-hit-many.ts +0 -63
  73. package/dist/playground/snippets/raycast-hit.ts +0 -62
  74. package/dist/playground/snippets/ui.tsx +0 -134
  75. package/types/ecs7/index.d.ts +0 -4679
@@ -0,0 +1,425 @@
1
+ /**
2
+ * A class serves as a medium between the observable and its observers
3
+ * @deprecated This function is an inheritance of ECS6, it's here temporary for the feature parity, please read the news and docs to know how handle when it's removed
4
+ */
5
+ export class ObserverEventState {
6
+ /**
7
+ * An Observer can set this property to true to prevent subsequent observers of being notified
8
+ */
9
+ public skipNextObservers!: boolean
10
+
11
+ /**
12
+ * Get the mask value that were used to trigger the event corresponding to this EventState object
13
+ */
14
+ public mask!: number
15
+
16
+ /**
17
+ * The object that originally notified the event
18
+ */
19
+ public target?: any
20
+
21
+ /**
22
+ * The current object in the bubbling phase
23
+ */
24
+ public currentTarget?: any
25
+
26
+ /**
27
+ * This will be populated with the return value of the last function that was executed.
28
+ * If it is the first function in the callback chain it will be the event data.
29
+ */
30
+ public lastReturnValue?: any
31
+
32
+ /**
33
+ * Create a new EventState
34
+ * @param mask - defines the mask associated with this state
35
+ * @param skipNextObservers - defines a flag which will instruct the observable to skip following observers when set to true
36
+ * @param target - defines the original target of the state
37
+ * @param currentTarget - defines the current target of the state
38
+ */
39
+ constructor(
40
+ mask: number,
41
+ skipNextObservers = false,
42
+ target?: any,
43
+ currentTarget?: any
44
+ ) {
45
+ this.initalize(mask, skipNextObservers, target, currentTarget)
46
+ }
47
+
48
+ /**
49
+ * Initialize the current event state
50
+ * @param mask - defines the mask associated with this state
51
+ * @param skipNextObservers - defines a flag which will instruct the observable to skip following observers when set to true
52
+ * @param target - defines the original target of the state
53
+ * @param currentTarget - defines the current target of the state
54
+ * @returns the current event state
55
+ */
56
+ public initalize(
57
+ mask: number,
58
+ skipNextObservers = false,
59
+ target?: any,
60
+ currentTarget?: any
61
+ ): ObserverEventState {
62
+ this.mask = mask
63
+ this.skipNextObservers = skipNextObservers
64
+ this.target = target
65
+ this.currentTarget = currentTarget
66
+ return this
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Represent an Observer registered to a given Observable object.
72
+ * @deprecated This function is an inheritance of ECS6, it's here temporary for the feature parity, please read the news and docs to know how handle when it's removed
73
+ */
74
+ export class Observer<T> {
75
+ /**
76
+ * Gets or sets a property defining that the observer as to be unregistered after the next notification
77
+ */
78
+ public unregisterOnNextCall = false
79
+
80
+ /** For internal usage */
81
+ public _willBeUnregistered = false
82
+
83
+ /**
84
+ * Creates a new observer
85
+ * @param callback - defines the callback to call when the observer is notified
86
+ * @param mask - defines the mask of the observer (used to filter notifications)
87
+ * @param scope - defines the current scope used to restore the JS context
88
+ */
89
+ constructor(
90
+ /**
91
+ * Defines the callback to call when the observer is notified
92
+ */
93
+ public callback: (eventData: T, eventState: ObserverEventState) => void,
94
+ /**
95
+ * Defines the mask of the observer (used to filter notifications)
96
+ */
97
+ public mask: number,
98
+ /**
99
+ * Defines the current scope used to restore the JS context
100
+ */
101
+ public scope: any = null
102
+ ) {}
103
+ }
104
+
105
+ /**
106
+ * The Observable class is a simple implementation of the Observable pattern.
107
+ *
108
+ * There's one slight particularity though: a given Observable can notify its observer using a particular mask value, only the Observers registered with this mask value will be notified.
109
+ * This enable a more fine grained execution without having to rely on multiple different Observable objects.
110
+ * For instance you may have a given Observable that have four different types of notifications: Move (mask = 0x01), Stop (mask = 0x02), Turn Right (mask = 0X04), Turn Left (mask = 0X08).
111
+ * A given observer can register itself with only Move and Stop (mask = 0x03), then it will only be notified when one of these two occurs and will never be for Turn Left/Right.
112
+ *
113
+ * @deprecated This function is an inheritance of ECS6, it's here temporary for the feature parity, please read the news and docs to know how handle when it's removed
114
+ */
115
+ export class Observable<T> {
116
+ private _observers = new Array<Observer<T>>()
117
+
118
+ private _eventState: ObserverEventState
119
+
120
+ private _onObserverAdded: null | ((observer: Observer<T>) => void) = null
121
+
122
+ /**
123
+ * Creates a new observable
124
+ * @param onObserverAdded - defines a callback to call when a new observer is added
125
+ */
126
+ constructor(onObserverAdded?: (observer: Observer<T>) => void) {
127
+ this._eventState = new ObserverEventState(0)
128
+
129
+ if (onObserverAdded) {
130
+ this._onObserverAdded = onObserverAdded
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Create a new Observer with the specified callback
136
+ * @param callback - the callback that will be executed for that Observer
137
+ * @param mask - the mask used to filter observers
138
+ * @param insertFirst - if true the callback will be inserted at the first position, hence executed before the others ones. If false (default behavior) the callback will be inserted at the last position, executed after all the others already present.
139
+ * @param scope - optional scope for the callback to be called from
140
+ * @param unregisterOnFirstCall - defines if the observer as to be unregistered after the next notification
141
+ * @returns the new observer created for the callback
142
+ */
143
+ public add(
144
+ callback: (eventData: T, eventState: ObserverEventState) => void,
145
+ mask: number = -1,
146
+ insertFirst = false,
147
+ scope: any = null,
148
+ unregisterOnFirstCall = false
149
+ ): null | Observer<T> {
150
+ if (!callback) {
151
+ return null
152
+ }
153
+
154
+ const observer = new Observer(callback, mask, scope)
155
+ observer.unregisterOnNextCall = unregisterOnFirstCall
156
+
157
+ if (insertFirst) {
158
+ this._observers.unshift(observer)
159
+ } else {
160
+ this._observers.push(observer)
161
+ }
162
+
163
+ if (this._onObserverAdded) {
164
+ this._onObserverAdded(observer)
165
+ }
166
+
167
+ return observer
168
+ }
169
+
170
+ /**
171
+ * Create a new Observer with the specified callback and unregisters after the next notification
172
+ * @param callback - the callback that will be executed for that Observer
173
+ * @returns the new observer created for the callback
174
+ */
175
+ public addOnce(
176
+ callback: (eventData: T, eventState: ObserverEventState) => void
177
+ ): null | Observer<T> {
178
+ return this.add(callback, undefined, undefined, undefined, true)
179
+ }
180
+
181
+ /**
182
+ * Remove an Observer from the Observable object
183
+ * @param observer - the instance of the Observer to remove
184
+ * @returns false if it doesn't belong to this Observable
185
+ */
186
+ public remove(observer: null | Observer<T>): boolean {
187
+ if (!observer) {
188
+ return false
189
+ }
190
+
191
+ const index = this._observers.indexOf(observer)
192
+
193
+ if (index !== -1) {
194
+ this._deferUnregister(observer)
195
+ return true
196
+ }
197
+
198
+ return false
199
+ }
200
+
201
+ /**
202
+ * Remove a callback from the Observable object
203
+ * @param callback - the callback to remove
204
+ * @param scope - optional scope. If used only the callbacks with this scope will be removed
205
+ * @returns false if it doesn't belong to this Observable
206
+ */
207
+ public removeCallback(
208
+ callback: (eventData: T, eventState: ObserverEventState) => void,
209
+ scope?: any
210
+ ): boolean {
211
+ for (let index = 0; index < this._observers.length; index++) {
212
+ if (
213
+ this._observers[index].callback === callback &&
214
+ (!scope || scope === this._observers[index].scope)
215
+ ) {
216
+ this._deferUnregister(this._observers[index])
217
+ return true
218
+ }
219
+ }
220
+
221
+ return false
222
+ }
223
+
224
+ /**
225
+ * Notify all Observers by calling their respective callback with the given data
226
+ * Will return true if all observers were executed, false if an observer set skipNextObservers to true, then prevent the subsequent ones to execute
227
+ * @param eventData - defines the data to send to all observers
228
+ * @param mask - defines the mask of the current notification (observers with incompatible mask (ie mask & observer.mask === 0) will not be notified)
229
+ * @param target - defines the original target of the state
230
+ * @param currentTarget - defines the current target of the state
231
+ * @returns false if the complete observer chain was not processed (because one observer set the skipNextObservers to true)
232
+ */
233
+ public notifyObservers(
234
+ eventData: T,
235
+ mask: number = -1,
236
+ target?: any,
237
+ currentTarget?: any
238
+ ): boolean {
239
+ if (!this._observers.length) {
240
+ return true
241
+ }
242
+
243
+ const state = this._eventState
244
+ state.mask = mask
245
+ state.target = target
246
+ state.currentTarget = currentTarget
247
+ state.skipNextObservers = false
248
+ state.lastReturnValue = eventData
249
+
250
+ for (const obs of this._observers) {
251
+ if (obs._willBeUnregistered) {
252
+ continue
253
+ }
254
+
255
+ if (obs.mask & mask) {
256
+ if (obs.scope) {
257
+ state.lastReturnValue = obs.callback.apply(obs.scope, [
258
+ eventData,
259
+ state
260
+ ])
261
+ } else {
262
+ state.lastReturnValue = obs.callback(eventData, state)
263
+ }
264
+
265
+ if (obs.unregisterOnNextCall) {
266
+ this._deferUnregister(obs)
267
+ }
268
+ }
269
+ if (state.skipNextObservers) {
270
+ return false
271
+ }
272
+ }
273
+ return true
274
+ }
275
+
276
+ /**
277
+ * Calling this will execute each callback, expecting it to be a promise or return a value.
278
+ * If at any point in the chain one function fails, the promise will fail and the execution will not continue.
279
+ * This is useful when a chain of events (sometimes async events) is needed to initialize a certain object
280
+ * and it is crucial that all callbacks will be executed.
281
+ * The order of the callbacks is kept, callbacks are not executed parallel.
282
+ *
283
+ * @param eventData - The data to be sent to each callback
284
+ * @param mask - is used to filter observers defaults to -1
285
+ * @param target - defines the callback target (see EventState)
286
+ * @param currentTarget - defines he current object in the bubbling phase
287
+ * @returns will return a Promise than resolves when all callbacks executed successfully.
288
+ */
289
+ public notifyObserversWithPromise(
290
+ eventData: T,
291
+ mask: number = -1,
292
+ target?: any,
293
+ currentTarget?: any
294
+ ): Promise<T> {
295
+ // create an empty promise
296
+ let p: Promise<any> = Promise.resolve(eventData)
297
+
298
+ // no observers? return this promise.
299
+ if (!this._observers.length) {
300
+ return p
301
+ }
302
+
303
+ const state = this._eventState
304
+ state.mask = mask
305
+ state.target = target
306
+ state.currentTarget = currentTarget
307
+ state.skipNextObservers = false
308
+
309
+ // execute one callback after another (not using Promise.all, the order is important)
310
+ this._observers.forEach((obs) => {
311
+ if (state.skipNextObservers) {
312
+ return
313
+ }
314
+ if (obs._willBeUnregistered) {
315
+ return
316
+ }
317
+ if (obs.mask & mask) {
318
+ if (obs.scope) {
319
+ p = p.then((lastReturnedValue) => {
320
+ state.lastReturnValue = lastReturnedValue
321
+ return obs.callback.apply(obs.scope, [eventData, state])
322
+ })
323
+ } else {
324
+ p = p.then((lastReturnedValue) => {
325
+ state.lastReturnValue = lastReturnedValue
326
+ return obs.callback(eventData, state)
327
+ })
328
+ }
329
+ if (obs.unregisterOnNextCall) {
330
+ this._deferUnregister(obs)
331
+ }
332
+ }
333
+ })
334
+
335
+ // return the eventData
336
+ return p.then(() => {
337
+ return eventData
338
+ })
339
+ }
340
+
341
+ /**
342
+ * Notify a specific observer
343
+ * @param observer - defines the observer to notify
344
+ * @param eventData - defines the data to be sent to each callback
345
+ * @param mask - is used to filter observers defaults to -1
346
+ */
347
+ public notifyObserver(
348
+ observer: Observer<T>,
349
+ eventData: T,
350
+ mask: number = -1
351
+ ): void {
352
+ const state = this._eventState
353
+ state.mask = mask
354
+ state.skipNextObservers = false
355
+
356
+ observer.callback(eventData, state)
357
+ }
358
+
359
+ /**
360
+ * Gets a boolean indicating if the observable has at least one observer
361
+ * @returns true is the Observable has at least one Observer registered
362
+ */
363
+ public hasObservers(): boolean {
364
+ return this._observers.length > 0
365
+ }
366
+
367
+ /**
368
+ * Clear the list of observers
369
+ */
370
+ public clear(): void {
371
+ this._observers = new Array<Observer<T>>()
372
+ this._onObserverAdded = null
373
+ }
374
+
375
+ /**
376
+ * Clone the current observable
377
+ * @returns a new observable
378
+ */
379
+ public clone(): Observable<T> {
380
+ const result = new Observable<T>()
381
+
382
+ result._observers = this._observers.slice(0)
383
+
384
+ return result
385
+ }
386
+
387
+ /**
388
+ * Does this observable handles observer registered with a given mask
389
+ * @param mask - defines the mask to be tested
390
+ * @returns whether or not one observer registered with the given mask is handeled
391
+ */
392
+ public hasSpecificMask(mask: number = -1): boolean {
393
+ for (const obs of this._observers) {
394
+ if (obs.mask & mask || obs.mask === mask) {
395
+ return true
396
+ }
397
+ }
398
+ return false
399
+ }
400
+
401
+ private _deferUnregister(observer: Observer<T>): void {
402
+ observer.unregisterOnNextCall = false
403
+ observer._willBeUnregistered = true
404
+ Promise.resolve()
405
+ .then.bind(Promise.resolve())(async () => this._remove(observer))
406
+ .catch(console.error)
407
+ }
408
+
409
+ // This should only be called when not iterating over _observers to avoid callback skipping.
410
+ // Removes an observer from the _observer Array.
411
+ private _remove(observer: null | Observer<T>): boolean {
412
+ if (!observer) {
413
+ return false
414
+ }
415
+
416
+ const index = this._observers.indexOf(observer)
417
+
418
+ if (index !== -1) {
419
+ this._observers.splice(index, 1)
420
+ return true
421
+ }
422
+
423
+ return false
424
+ }
425
+ }
@@ -0,0 +1,24 @@
1
+ import { TransportMessage, Transport } from '@dcl/ecs'
2
+
3
+ export function createNetworkTransport(): Transport {
4
+ // const rpc = new RpcTransport()
5
+ function send(..._args: any[]) {
6
+ // console.log('NetworkMessage Sent: ', ...args)
7
+ }
8
+
9
+ const type = 'network-transport'
10
+ return {
11
+ send,
12
+ type,
13
+ filter(message: TransportMessage): boolean {
14
+ // Echo message, ignore them
15
+ if (message.transportType === type) {
16
+ return false
17
+ }
18
+
19
+ // TODO: Static entities & Network components
20
+
21
+ return !!message // validComponents.includes(componentId)
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,60 @@
1
+ import { Transport, TransportMessage } from '@dcl/ecs'
2
+ import { ECSComponentIDs } from '@dcl/ecs/dist/components/generated/ids.gen'
3
+ import type {
4
+ CrdtSendToRendererRequest,
5
+ CrdtSendToResponse
6
+ } from '~system/EngineApi'
7
+
8
+ const componentIds = Object.values(ECSComponentIDs)
9
+ .filter((a) => typeof a === 'number')
10
+ .map(Number)
11
+
12
+ export type EngineApiForTransport = {
13
+ crdtSendToRenderer(
14
+ body: CrdtSendToRendererRequest
15
+ ): Promise<CrdtSendToResponse>
16
+ }
17
+
18
+ export function createRendererTransport(
19
+ engineApi: EngineApiForTransport
20
+ ): Transport {
21
+ async function sendToRenderer(message: Uint8Array) {
22
+ const response = await engineApi.crdtSendToRenderer({
23
+ data: new Uint8Array(message)
24
+ })
25
+
26
+ if (response && response.data && response.data.length) {
27
+ if (rendererTransport.onmessage) {
28
+ for (const byteArray of response.data) {
29
+ rendererTransport.onmessage(byteArray)
30
+ }
31
+ }
32
+ }
33
+ }
34
+
35
+ const type = 'renderer'
36
+ const rendererTransport: Transport = {
37
+ type,
38
+ send(message: Uint8Array): void {
39
+ sendToRenderer(message).catch((error) => {
40
+ console.error(error)
41
+ debugger
42
+ })
43
+ },
44
+ filter(message: TransportMessage): boolean {
45
+ // Echo message, ignore them
46
+ if (message.transportType === type) {
47
+ return false
48
+ }
49
+
50
+ // Only send renderer components (Proto Generated)
51
+ if (!componentIds.includes(message.componentId)) {
52
+ return false
53
+ }
54
+
55
+ return !!message
56
+ }
57
+ }
58
+
59
+ return rendererTransport
60
+ }
package/src/math.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from '@dcl/ecs-math'
2
+ export * from '@dcl/ecs-math/dist/Matrix'
3
+ export * from '@dcl/ecs-math/dist/Plane'
@@ -0,0 +1,62 @@
1
+ import { Observer } from './internal/Observable'
2
+ import { IEvents, onCommsMessage } from './observables'
3
+ import * as communicationsController from '~system/CommunicationsController'
4
+
5
+ /**
6
+ * @alpha
7
+ * @deprecated this will only exist for a few releases in ECS7
8
+ */
9
+ export class MessageBus {
10
+ private messageQueue: string[] = []
11
+ private flushing = false
12
+
13
+ constructor() {}
14
+
15
+ on(
16
+ message: string,
17
+ callback: (value: any, sender: string) => void
18
+ ): Observer<IEvents['comms']> {
19
+ return onCommsMessage.add((e) => {
20
+ const m = JSON.parse(e.message)
21
+
22
+ if (m.message === message) {
23
+ callback(m.payload, e.sender)
24
+ }
25
+ })!
26
+ }
27
+
28
+ // @internal
29
+ sendRaw(message: string) {
30
+ this.messageQueue.push(message)
31
+
32
+ this.flush()
33
+ }
34
+
35
+ emit(message: string, payload: Record<any, any>) {
36
+ const messageToSend = JSON.stringify({ message, payload })
37
+ this.sendRaw(messageToSend)
38
+ onCommsMessage.notifyObservers({
39
+ message: messageToSend,
40
+ sender: 'self'
41
+ })
42
+ }
43
+
44
+ private flush() {
45
+ if (this.messageQueue.length === 0) return
46
+ if (this.flushing) return
47
+
48
+ const message = this.messageQueue.shift()!
49
+
50
+ this.flushing = true
51
+
52
+ communicationsController.send({ message }).then(
53
+ (_) => {
54
+ this.flushing = false
55
+ this.flush()
56
+ },
57
+ (_) => {
58
+ this.flushing = false
59
+ }
60
+ )
61
+ }
62
+ }