@needle-tools/engine 2.30.0-pre → 2.31.0-pre

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 (34) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/needle-engine.d.ts +807 -753
  3. package/dist/needle-engine.js +336 -336
  4. package/dist/needle-engine.js.map +4 -4
  5. package/dist/needle-engine.min.js +16 -16
  6. package/dist/needle-engine.min.js.map +4 -4
  7. package/lib/engine/engine_physics.d.ts +19 -8
  8. package/lib/engine/engine_physics.js +57 -48
  9. package/lib/engine/engine_physics.js.map +1 -1
  10. package/lib/engine-components/Camera.js +0 -1
  11. package/lib/engine-components/Camera.js.map +1 -1
  12. package/lib/engine-components/Component.d.ts +10 -0
  13. package/lib/engine-components/Component.js +53 -0
  14. package/lib/engine-components/Component.js.map +1 -1
  15. package/lib/engine-components/Rigidbody.d.ts +1 -1
  16. package/lib/engine-components/Rigidbody.js +3 -3
  17. package/lib/engine-components/Rigidbody.js.map +1 -1
  18. package/lib/engine-components/ScreenCapture.d.ts +35 -6
  19. package/lib/engine-components/ScreenCapture.js +356 -103
  20. package/lib/engine-components/ScreenCapture.js.map +1 -1
  21. package/lib/engine-components/VideoPlayer.d.ts +4 -0
  22. package/lib/engine-components/VideoPlayer.js +22 -1
  23. package/lib/engine-components/VideoPlayer.js.map +1 -1
  24. package/lib/needle-engine.d.ts +1 -0
  25. package/lib/needle-engine.js +1 -0
  26. package/lib/needle-engine.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/engine/engine_physics.ts +74 -57
  29. package/src/engine-components/Camera.ts +0 -1
  30. package/src/engine-components/Component.ts +58 -0
  31. package/src/engine-components/RigidBody.ts +2 -2
  32. package/src/engine-components/ScreenCapture.ts +386 -114
  33. package/src/engine-components/VideoPlayer.ts +26 -2
  34. package/src/needle-engine.ts +1 -0
@@ -6,75 +6,269 @@ import { RoomEvents } from "../engine/engine_networking";
6
6
  import { UserJoinedOrLeftRoomModel } from "../engine/engine_networking";
7
7
  import { serializeable } from "../engine/engine_serialization";
8
8
  import { IModel } from "../engine/engine_networking";
9
+ import { IPointerClickHandler } from "./ui/PointerEvents";
10
+ import { EventDispatcher } from "three";
11
+ import { AudioSource } from "./AudioSource";
12
+ import { getWorldScale, setWorldScale } from "../engine/engine_three_utils";
13
+
14
+
15
+ export enum ScreenCaptureDevice {
16
+ Screen = 0,
17
+ Camera = 1
18
+ }
19
+
20
+ export enum ScreenCaptureMode {
21
+ Idle = 0,
22
+ Sending = 1,
23
+ Receiving = 2
24
+ }
25
+
26
+ export enum AspectMode {
27
+ None = 0,
28
+ AdjustHeight = 1,
29
+ AdjustWidth = 2,
30
+ }
31
+
32
+ function disposeStream(str: MediaStream | null | undefined) {
33
+ if (!str) return;
34
+ for (const cap of str.getTracks())
35
+ cap.stop();
36
+ }
37
+
38
+ export class ScreenCapture extends Behaviour implements IPointerClickHandler {
39
+
40
+ onPointerClick() {
41
+ if (this.isSending) {
42
+ this.close();
43
+ return;
44
+ }
45
+ this.share();
46
+ }
47
+
48
+
9
49
 
10
- export class ScreenCapture extends Behaviour {
11
50
 
12
51
  @serializeable()
13
- streamOnAwake: boolean = true;
52
+ device: ScreenCaptureDevice = ScreenCaptureDevice.Screen;
14
53
 
15
- start() {
16
- console.warn("EXPERIMENTAL screen capture", this);
17
- if (this.streamOnAwake)
18
- this.open();
54
+ @serializeable()
55
+ aspectMode: AspectMode = AspectMode.AdjustHeight;
56
+
57
+
58
+ get isSending() {
59
+ return this._currentStream && this._currentMode === ScreenCaptureMode.Sending;
60
+ }
61
+ get isReceiving() {
62
+ return this._currentStream && this._currentMode === ScreenCaptureMode.Receiving;
19
63
  }
20
64
 
21
- private requestOpen: boolean = false;
22
- private captureStream: MediaStream | null = null;
65
+ private _net?: NetworkedVideo;
66
+ private _video?: VideoPlayer;
67
+ private _requestOpen: boolean = false;
68
+ private _currentStream: MediaStream | null = null;
69
+ private _currentMode: ScreenCaptureMode = ScreenCaptureMode.Idle;
23
70
 
24
- async open(force: boolean = false) {
25
- if (this.captureStream && !force) return;
26
- this.close();
27
- this.requestOpen = true;
71
+ awake() {
72
+ AudioSource.registerWaitForAllowAudio(() => {
73
+ if (this._video && this._currentStream && this._currentMode === ScreenCaptureMode.Receiving) {
74
+ this._video.setVideo(this._currentStream);
75
+ }
76
+ });
77
+ }
78
+
79
+ start() {
80
+ this._video = GameObject.getComponentInChildren(this.gameObject, VideoPlayer) ?? undefined;
81
+ if (!this._video) {
82
+ console.error("Missing VideoPlayer component");
83
+ return;
84
+ }
85
+ const handle = PeerHandle.getOrCreate(this.context, this.guid);
86
+ this._net = new NetworkedVideo(this.context, handle);
87
+ this._net.enable();
88
+ //@ts-ignore
89
+ this._net.addEventListener(PeerEvent.ReceiveVideo, this.onReceiveVideo.bind(this));
90
+ }
91
+
92
+ async share() {
93
+ this._requestOpen = true;
28
94
  try {
29
- const player = GameObject.getComponentInChildren(this.gameObject, VideoPlayer);
30
- if (player) {
95
+ if (this._video) {
96
+
97
+ const settings: MediaTrackConstraints = {
98
+ echoCancellation: true,
99
+ autoGainControl: false,
100
+ };
31
101
  const displayMediaOptions: DisplayMediaStreamConstraints = {
32
- video: true,
33
- audio: true
102
+ video: settings,
103
+ audio: settings,
34
104
  };
35
- this.captureStream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
36
- if (this.captureStream && this.requestOpen) {
37
- //@ts-ignore
38
- player.clip = this.captureStream;
39
- player.create(true);
105
+
106
+ switch (this.device) {
107
+ case ScreenCaptureDevice.Camera:
108
+ this.tryShareUserCamera(displayMediaOptions);
109
+ break;
110
+
111
+ case ScreenCaptureDevice.Screen:
112
+ if (!navigator.mediaDevices.getDisplayMedia) {
113
+ console.error("No getDisplayMedia support");
114
+ return;
115
+ }
116
+ const myVideo = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
117
+ if (this._requestOpen) {
118
+ this.setVideo(myVideo, ScreenCaptureMode.Sending);
119
+ }
120
+ else disposeStream(myVideo);
121
+ break;
40
122
  }
41
- this.handleNetworkedVideo();
42
123
  }
43
- } catch (err) {
44
- console.error("Error: " + err);
124
+ } catch (err: any) {
125
+ if (err.name === "NotAllowedError") {
126
+ // user cancelled stream selection
127
+ console.log("Selection cancelled");
128
+ this._requestOpen = false;
129
+ return;
130
+ }
131
+ console.error("Error opening video", err);
45
132
  }
46
133
  }
47
134
 
48
135
  close() {
49
- this.requestOpen = false;
50
- if (this.captureStream) {
51
- for (const cap of this.captureStream.getTracks())
52
- cap.stop();
53
- this.captureStream = null;
136
+ this._requestOpen = false;
137
+ if (this._currentStream) {
138
+ console.warn("Close current stream / disposing resources");
139
+ disposeStream(this._currentStream);
140
+ this._net?.stopSendingVideo(this._currentStream);
141
+ this._currentMode = ScreenCaptureMode.Idle;
142
+ this._currentStream = null;
54
143
  }
55
144
  }
56
145
 
57
- private handleNetworkedVideo() {
58
- if (!this.context.connection.isConnected) {
59
- console.warn("Will not stream video - not connected to room");
60
- return;
61
- }
62
- if (this.captureStream) {
63
- const handle = PeerHandle.getOrCreate(this.context, this.guid);
64
- handle.enable();
65
- // if (!this.peer)
66
- // this.peer = new Peer();
67
- const net = new NetworkedVideo(this.context, handle);
68
- net.enable();
69
- net.startSendingVideo(this.captureStream);
146
+ private setVideo(stream: MediaStream, mode: ScreenCaptureMode) {
147
+ if (stream === this._currentStream) return;
148
+ this.close();
149
+ if (!stream || !this._video) return;
150
+ this._currentStream = stream;
151
+ this._requestOpen = true;
152
+ this._currentMode = mode;
153
+ this._video.setVideo(stream);
154
+ if (mode === ScreenCaptureMode.Sending)
155
+ this._net?.startSendingVideo(stream);
156
+
157
+ this._targetObjects = undefined;
158
+ this.updateAspect();
159
+ }
160
+
161
+ private onReceiveVideo(evt: ReceiveVideoEvent) {
162
+ this.setVideo(evt.stream, ScreenCaptureMode.Receiving);
163
+ }
164
+
165
+
166
+
167
+
168
+ private async tryShareUserCamera(opts: DisplayMediaStreamConstraints) {
169
+
170
+ // let newWindow = open('', 'example', 'width=300,height=300');
171
+ // if (window) {
172
+ // newWindow!.document.body.innerHTML = "Please allow access to your camera and microphone";
173
+ // }
174
+
175
+ // TODO: allow user to select device
176
+ const devices = (await navigator.mediaDevices.enumerateDevices()).filter(d => d.kind === "videoinput");
177
+ console.log("Request camera", devices);
178
+ for (const dev of devices) {
179
+ try {
180
+ if (!this._requestOpen) break;
181
+ if (dev.kind !== "videoinput") continue;
182
+ const id = dev.deviceId;
183
+ if (opts.video !== false) {
184
+ if (typeof opts.video === "undefined" || typeof opts.video === "boolean") {
185
+ opts.video = {};
186
+ }
187
+ opts.video.deviceId = id;
188
+ }
189
+ const userMedia = await navigator.mediaDevices.getUserMedia(opts);
190
+ if (this._requestOpen) {
191
+ this.setVideo(userMedia, ScreenCaptureMode.Sending);
192
+ }
193
+ else disposeStream(userMedia);
194
+ console.log("Selected camera", dev);
195
+ break;
196
+ }
197
+ catch (err) {
198
+ console.warn(err);
199
+ }
70
200
  }
71
201
  }
202
+ // private _cameraSelectionWindow : Window | null = null;
203
+ // private openWindowToSelectCamera(){
204
+
205
+ // }
206
+
207
+
208
+
209
+
210
+ private _targetObjects?: Array<THREE.Object3D>;
211
+
212
+ private updateAspect() {
213
+ this.startCoroutine(this.updateAspectImpl());
214
+ }
72
215
 
216
+ private _updateAspectRoutineId: number = -1;
217
+ private *updateAspectImpl() {
218
+ const id = ++this._updateAspectRoutineId;
219
+ while (this.aspectMode !== AspectMode.None && this._currentStream && id === this._updateAspectRoutineId) {
220
+ const video = this._video;
221
+ const stream = this._currentStream;
222
+ if (!video) return;
223
+ if (!stream) return;
224
+ let aspect: number | undefined = undefined;
225
+ for (const track of stream.getVideoTracks()) {
226
+ const settings = track.getSettings();
227
+ if (settings.width && settings.height) {
228
+ aspect = settings.width / settings.height;
229
+ break;
230
+ }
231
+ }
232
+ if (aspect === undefined) return;
233
+ if (!this._targetObjects)
234
+ this._targetObjects = video.getTargetObjects();
235
+ for (const obj of this._targetObjects) {
236
+ let worldAspect = 1;
237
+ if (obj.parent) {
238
+ const parentScale = getWorldScale(obj.parent);
239
+ worldAspect = parentScale.x / parentScale.y;
240
+ }
241
+ switch (this.aspectMode) {
242
+ case AspectMode.AdjustHeight:
243
+ obj.scale.y = 1 / aspect * obj.scale.x * worldAspect;
244
+ break;
245
+ case AspectMode.AdjustWidth:
246
+ obj.scale.x = aspect * obj.scale.y * worldAspect;
247
+ break;
248
+ }
249
+ }
250
+ yield;
251
+ }
252
+ }
73
253
  }
74
254
 
75
255
 
76
- enum PeerHandleEvent {
256
+ /////// PEER
257
+
258
+ enum PeerEvent {
77
259
  Connected = "peer-user-connected",
260
+ ReceiveVideo = "receive-video",
261
+ Disconnected = "peer-user-disconnected",
262
+ }
263
+
264
+ class ReceiveVideoEvent {
265
+ readonly type = PeerEvent.ReceiveVideo;
266
+ readonly stream: MediaStream;
267
+ readonly target: CallHandle;
268
+ constructor(stream: MediaStream, target: CallHandle) {
269
+ this.stream = stream
270
+ this.target = target;
271
+ }
78
272
  }
79
273
 
80
274
  class PeerUserConnectedModel implements IModel {
@@ -94,22 +288,48 @@ enum CallDirection {
94
288
  Outgoing = "outgoing",
95
289
  }
96
290
 
97
- class CallHandle {
291
+ class CallHandle extends EventDispatcher {
292
+ readonly userId: string;
98
293
  readonly direction: CallDirection;
99
294
  readonly call: Peer.MediaConnection;
100
- stream: MediaStream | null;
295
+ get stream() { return this._stream; };
296
+
297
+ private _stream: MediaStream | null = null;
298
+ private _isDisposed: boolean = false;
299
+
300
+ close() {
301
+ if (this._isDisposed) return;
302
+ this._isDisposed = true;
303
+ this.call.close();
304
+ disposeStream(this._stream);
305
+ }
306
+
307
+ get isOpen() {
308
+ return this.call.peerConnection?.connectionState === "connected";// && this._stream?.active;
309
+ }
101
310
 
102
- constructor(call: Peer.MediaConnection, direction: CallDirection) {
311
+ get isClosed() {
312
+ return !this.isOpen;
313
+ }
314
+
315
+ constructor(userId: string, call: Peer.MediaConnection, direction: CallDirection) {
316
+ super();
317
+ this.userId = userId;
103
318
  this.call = call;
104
319
  this.direction = direction;
105
- this.stream = null;
320
+ this._stream = null;
106
321
  call.on("stream", stream => {
107
- this.stream = stream;
322
+ console.log("Receive video", stream.getAudioTracks(), stream.getVideoTracks());
323
+ this._stream = stream;
324
+ if (direction === CallDirection.Incoming) {
325
+ const args: ReceiveVideoEvent = new ReceiveVideoEvent(stream, this);
326
+ this.dispatchEvent(args);
327
+ }
108
328
  });
109
329
  }
110
330
  }
111
331
 
112
- class PeerHandle {
332
+ class PeerHandle extends EventDispatcher {
113
333
 
114
334
  private static readonly instances: Map<string, PeerHandle> = new Map();
115
335
 
@@ -125,6 +345,12 @@ class PeerHandle {
125
345
  return peer;
126
346
  }
127
347
 
348
+ getMyPeerId(): string | undefined {
349
+ if (this.context.connection.connectionId)
350
+ return this.getPeerIdFromUserId(this.context.connection.connectionId);
351
+ return undefined;
352
+ }
353
+
128
354
  getPeerIdFromUserId(userConnectionId: string): string {
129
355
  // we build the peer id ourselves so we dont need to wait for peer to report it
130
356
  return this.id + "-" + userConnectionId;
@@ -135,13 +361,8 @@ class PeerHandle {
135
361
  }
136
362
 
137
363
  makeCall(peerId: string, stream: MediaStream): CallHandle | undefined {
138
- // if (userId === this.context.connection.connectionId) {
139
- // console.warn("Can not call self");
140
- // return;
141
- // }
142
- // const peerId = this.getUserPeerId(userId);
143
- console.log("CALL", peerId);
144
- const call = this._peer?.call(peerId, stream);
364
+ const opts = { metadata: { userId: this.context.connection.connectionId } };
365
+ const call = this._peer?.call(peerId, stream, opts);
145
366
  if (call)
146
367
  return this.registerCall(call, CallDirection.Outgoing);
147
368
  return undefined;
@@ -156,6 +377,7 @@ class PeerHandle {
156
377
  private _outgoingCalls: CallHandle[] = [];
157
378
 
158
379
  private constructor(context: Context, id: string) {
380
+ super();
159
381
  this.context = context;
160
382
  this.id = id;
161
383
  this.setupPeer();
@@ -203,7 +425,7 @@ class PeerHandle {
203
425
  if (this._enabledPeer) return;
204
426
  this._enabledPeer = true;
205
427
  if (!this._peer) {
206
- const peerId = this.getPeerIdFromUserId(this.context.connection.connectionId);
428
+ const peerId = this.getMyPeerId();
207
429
  this._peer = new Peer(peerId);
208
430
  }
209
431
  if (this._enabled)
@@ -218,31 +440,60 @@ class PeerHandle {
218
440
  }
219
441
 
220
442
  private unsubscribePeerEvents() {
443
+ // TODO: unsubscribe
221
444
  }
222
445
 
223
446
  private onPeerConnect(id): void {
224
- console.log("connect", id);
225
- this.context.connection.send(PeerHandleEvent.Connected, new PeerUserConnectedModel(this, id));
447
+ console.log("Peer connected as", id);
448
+ this.context.connection.send(PeerEvent.Connected, new PeerUserConnectedModel(this, id));
226
449
  }
227
450
 
228
451
  private onPeerReceivingCall(call: Peer.MediaConnection): void {
229
- console.log("RECEIVE CALL");
230
452
  call.answer();
231
453
  this.registerCall(call, CallDirection.Incoming);
232
454
  }
233
455
 
234
456
  private registerCall(call: Peer.MediaConnection, direction: CallDirection): CallHandle {
457
+
458
+ const meta = call.metadata;
459
+ if (!meta || !meta.userId) {
460
+ console.error("Missing call metadata", call);
461
+ }
462
+ const userId = meta.userId;
463
+
464
+ if (direction === CallDirection.Incoming) console.log("Receive call from", call.metadata);
465
+ else console.log("Make call to", call.metadata);
466
+
235
467
  const arr = direction === CallDirection.Incoming ? this._incomingCalls : this._outgoingCalls;
236
- const handle = new CallHandle(call, direction);
468
+ const handle = new CallHandle(userId, call, direction);
237
469
  arr.push(handle);
238
470
  call.on("error", err => {
239
- console.error(err);
471
+ console.error("Call error", err);
240
472
  });
241
473
  call.on("close", () => {
474
+ console.log("Call ended", call.metadata);
475
+ call.close();
242
476
  const index = arr.indexOf(handle);
243
477
  if (index !== -1)
244
478
  arr.splice(index, 1);
245
479
  });
480
+
481
+ if (direction === CallDirection.Incoming) {
482
+
483
+ handle.addEventListener(PeerEvent.ReceiveVideo, e => {
484
+ this.dispatchEvent(e);
485
+ });
486
+
487
+ call.on("stream", () => {
488
+ // workaround for https://github.com/peers/peerjs/issues/636
489
+ let closeInterval = setInterval(() => {
490
+ if (!handle.isOpen) {
491
+ clearInterval(closeInterval);
492
+ handle.close();
493
+ }
494
+ }, 2000);
495
+ });
496
+ }
246
497
  return handle;
247
498
  }
248
499
 
@@ -252,36 +503,29 @@ class PeerHandle {
252
503
  }
253
504
 
254
505
 
255
- type UserVideoCall = {
256
- call: Peer.MediaConnection;
257
- stream: MediaStream;
258
- userId: string;
259
- }
506
+ // type UserVideoCall = {
507
+ // call: Peer.MediaConnection;
508
+ // stream: MediaStream;
509
+ // userId: string;
510
+ // }
260
511
 
261
- class NetworkedVideo {
512
+ // type IncomingStreamArgs = {
513
+ // stream: MediaStream;
514
+ // userId: string;
515
+ // }
516
+
517
+ class NetworkedVideo extends EventDispatcher {
262
518
 
263
519
  private readonly context: Context;
264
520
  private readonly peer: PeerHandle;
265
521
 
266
- private _sendingVideoStreams: Map<MediaStream, UserVideoCall[]> = new Map();
522
+ // private _receiveVideoStreamListeners: Array<(info: IncomingStreamArgs) => void> = [];
523
+ private _sendingVideoStreams: Map<MediaStream, CallHandle[]> = new Map();
267
524
 
268
525
  constructor(context: Context, peer: PeerHandle) {
526
+ super();
269
527
  this.context = context;
270
528
  this.peer = peer;
271
-
272
- // this.peer.on("open", (id) => {
273
- // console.log("PEERID", id);
274
- // });
275
- // // this.peer.on("call", (call) => {
276
- // // });
277
- // // this.peer.on("connection", (conn) => {
278
- // // });
279
- // // this.peer.on("error", (err) => {
280
- // // });
281
- // // this.peer.on("disconnected", () => {
282
- // // });
283
- // // this.peer.on("close", () => {
284
- // // });
285
529
  }
286
530
 
287
531
  startSendingVideo(stream: MediaStream) {
@@ -291,8 +535,18 @@ class NetworkedVideo {
291
535
  };
292
536
  }
293
537
 
294
- stopSendingVideo(_steam: MediaStream) {
295
-
538
+ stopSendingVideo(_steam: MediaStream | undefined | null) {
539
+ if (_steam) {
540
+ const calls = this._sendingVideoStreams.get(_steam);
541
+ if (calls) {
542
+ for (const call of calls) {
543
+ call.close();
544
+ }
545
+ }
546
+ this._sendingVideoStreams.delete(_steam);
547
+ if (calls)
548
+ console.log("Currently sending", this._sendingVideoStreams);
549
+ }
296
550
  }
297
551
 
298
552
  private onConnectRoomFn: Function = this.onConnectRoom.bind(this);
@@ -300,14 +554,22 @@ class NetworkedVideo {
300
554
  private onUserLeftFn: Function = this.onUserLeft.bind(this);
301
555
 
302
556
  enable() {
303
- this.context.connection.beginListen(PeerHandleEvent.Connected, this.onUserConnectedFn);
557
+ this.peer.enable();
558
+ this.context.connection.beginListen(PeerEvent.Connected, this.onUserConnectedFn);
559
+ this.peer.addEventListener("receive-video", this.onReceiveVideo.bind(this));
304
560
  }
305
561
 
306
562
  disable() {
563
+ this.peer.disable();
307
564
  // this.context.connection.stopListening(RoomEvents.UserJoinedRoom, this.onUserConnectedFn);
308
565
  // this.context.connection.stopListening(RoomEvents.UserLeftRoom, this.onUserLeftFn);
309
566
  }
310
567
 
568
+ private onReceiveVideo(evt) {
569
+ console.log("RECEIVE VIDEO", evt);
570
+ this.dispatchEvent({ type: "receive-video", target: this, stream: evt.stream, userId: evt.userId });
571
+ }
572
+
311
573
  private onConnectRoom() {
312
574
 
313
575
  }
@@ -316,41 +578,51 @@ class NetworkedVideo {
316
578
  // console.log(this.peer.id, user.guid)
317
579
  if (this.peer.id === user.guid) {
318
580
  console.log("USER CONNECTED", user);
319
- const userId = this.peer.getUserIdFromPeerId(user.peerId);
320
- console.log(userId);
321
- // this.updateSendingCalls();
322
- const call = this.peer.makeCall(user.peerId, this._sendingVideoStreams.keys().next().value);
323
-
324
- // for (const userId of this.context.connection.usersInRoom()) {
325
- // const id = this.peer.getPeerIdFromUserId(userId);
326
- // if(id === user.peerId) console.log(userId);
327
- // }
581
+ const stream = this._sendingVideoStreams.keys().next().value;
582
+ this.peer.makeCall(user.peerId, stream);
328
583
  }
329
584
  }
330
585
 
331
586
  private onUserLeft(_: UserJoinedOrLeftRoomModel) {
332
-
587
+ this.stopCallsToUsersThatAreNotInTheRoomAnymore();
333
588
  }
334
589
 
335
590
  private updateSendingCalls() {
336
- // for (const str of this._sendingVideoStreams.keys()) {
337
- // const calls = this._sendingVideoStreams.get(str) || [];
338
- // for (const userId of this.context.connection.usersInRoom()) {
339
- // const existing = calls.find(c => c.userId === userId);
340
- // if (!existing) {
341
- // const call = this.peer.makeCall(userId, str);
342
- // console.log(call);
343
- // if (call) {
344
- // calls.push({
345
- // call: call,
346
- // stream: str,
347
- // userId: userId
348
- // });
349
- // }
350
- // }
351
- // }
352
- // this._sendingVideoStreams.set(str, calls);
353
- // }
591
+ let startedNewCall = false;
592
+ for (const stream of this._sendingVideoStreams.keys()) {
593
+ const calls = this._sendingVideoStreams.get(stream) || [];
594
+ for (const userId of this.context.connection.usersInRoom()) {
595
+ if (userId === this.context.connection.connectionId) continue;
596
+ const existing = calls.find(c => c.userId === userId);
597
+ if (!existing) {
598
+ const handle = this.peer.makeCall(this.peer.getPeerIdFromUserId(userId), stream);
599
+ if (handle) {
600
+ startedNewCall = true;
601
+ calls.push(handle);
602
+ }
603
+ }
604
+ }
605
+
606
+ this._sendingVideoStreams.set(stream, calls);
607
+ }
608
+ this.stopCallsToUsersThatAreNotInTheRoomAnymore();
609
+ if (startedNewCall) {
610
+ console.log("Currently sending", this._sendingVideoStreams);
611
+ }
612
+ }
613
+
614
+ private stopCallsToUsersThatAreNotInTheRoomAnymore() {
615
+ for (const stream of this._sendingVideoStreams.keys()) {
616
+ const calls = this._sendingVideoStreams.get(stream);
617
+ if (!calls) continue;
618
+ for (let i = calls.length - 1; i >= 0; i--) {
619
+ const call = calls[i];
620
+ if (!this.context.connection.userIsInRoom(call.userId)) {
621
+ call.close();
622
+ calls.splice(i, 1);
623
+ }
624
+ }
625
+ }
354
626
  }
355
627
 
356
628
  // const call = peer.call(peerId, stream);