diff --git a/src/server/dev.ts b/src/server/dev.ts index 6e078422..9cb63415 100644 --- a/src/server/dev.ts +++ b/src/server/dev.ts @@ -3,6 +3,8 @@ import * as history from 'connect-history-api-fallback' import * as express from 'express' import * as http from 'http' import * as minimist from 'minimist' +import { reaction } from 'mobx' +import { IObservableValue } from 'mobx' import * as favicon from 'serve-favicon' import * as sio from 'socket.io' import * as webpack from 'webpack' @@ -34,9 +36,10 @@ const server = http.createServer(app) const sioNetwork = sio(server, { parser: NUClearNetProxyParser } as any) // Initialize socket.io namespace immediately to catch reconnections. -WebSocketProxyNUClearNetServer.of(WebSocketServer.of(sioNetwork.of('/nuclearnet')), { - fakeNetworking: withVirtualRobots, -}) +const webSocketProxyNUClearNetServer = WebSocketProxyNUClearNetServer.of( + WebSocketServer.of(sioNetwork.of('/nuclearnet')), + { fakeNetworking: withVirtualRobots }, +) const devMiddleware = webpackDevMiddleware(compiler, { publicPath: '/', @@ -73,7 +76,21 @@ function init() { { frequency: 60, simulator: ChartSimulator.of() }, ], }) - virtualRobots.startSimulators() + let stopSimulators: () => void | undefined + reaction( + () => webSocketProxyNUClearNetServer.numConnections > 0, + enable => { + if (enable) { + // tslint:disable-next-line no-console + console.log('Client connected, starting simulator') + stopSimulators = virtualRobots.startSimulators() + } else if (stopSimulators) { + // tslint:disable-next-line no-console + console.log('No clients remain connected, stopping simulator') + } + }, + { fireImmediately: true }, + ) } if (nbsFile) { diff --git a/src/server/nuclearnet/web_socket_proxy_nuclearnet_server.ts b/src/server/nuclearnet/web_socket_proxy_nuclearnet_server.ts index e164651d..a260e896 100644 --- a/src/server/nuclearnet/web_socket_proxy_nuclearnet_server.ts +++ b/src/server/nuclearnet/web_socket_proxy_nuclearnet_server.ts @@ -1,3 +1,5 @@ +import { action } from 'mobx' +import { observable } from 'mobx' import { NUClearNetOptions } from 'nuclearnet.js' import { NUClearNetPeer } from 'nuclearnet.js' import { NUClearNetPacket } from 'nuclearnet.js' @@ -21,6 +23,8 @@ type Opts = { * improved to have more intelligent multiplexing. */ export class WebSocketProxyNUClearNetServer { + @observable numConnections: number = 0 + constructor(private server: WebSocketServer, private nuclearnetClient: NUClearNetClient) { server.onConnection(this.onClientConnection) } @@ -30,8 +34,11 @@ export class WebSocketProxyNUClearNetServer { return new WebSocketProxyNUClearNetServer(server, nuclearnetClient) } - private onClientConnection = (socket: WebSocket) => { + @action.bound + private onClientConnection(socket: WebSocket) { + this.numConnections++ WebSocketServerClient.of(this.nuclearnetClient, socket) + socket.onDisconnect(action(() => this.numConnections--)) } } @@ -149,9 +156,9 @@ class PacketProcessor { this.sendReliablePacket(event, packet) } else if (this.isEventBelowLimit(event)) { this.sendUnreliablePacket(event, packet) - }/* else { - // This event is unreliable and already at the limit, simply drop the packet. - }*/ + } else { + return // The event is unreliable and already at the limit, simply drop the packet. + } } private isEventBelowLimit(event: string) { diff --git a/src/server/nuclearnet/web_socket_server.ts b/src/server/nuclearnet/web_socket_server.ts index b4b9c1e8..1638bfcc 100644 --- a/src/server/nuclearnet/web_socket_server.ts +++ b/src/server/nuclearnet/web_socket_server.ts @@ -34,6 +34,10 @@ export class WebSocket { this.sioSocket.on(event, cb) } + onDisconnect(cb: () => void) { + this.on('disconnect', cb) + } + send(event: string, ...args: any[]) { this.sioSocket.emit(event, ...args) } diff --git a/src/server/prod.ts b/src/server/prod.ts index f33dc00c..797cc65d 100644 --- a/src/server/prod.ts +++ b/src/server/prod.ts @@ -3,6 +3,7 @@ import * as history from 'connect-history-api-fallback' import * as express from 'express' import * as http from 'http' import * as minimist from 'minimist' +import { reaction } from 'mobx' import * as favicon from 'serve-favicon' import * as sio from 'socket.io' @@ -34,6 +35,11 @@ server.listen(port, () => { console.log(`NUsight server started at http://localhost:${port}`) }) +const webSocketProxyNUClearNetServer = WebSocketProxyNUClearNetServer.of( + WebSocketServer.of(sioNetwork.of('/nuclearnet')), + { fakeNetworking: withVirtualRobots }, +) + if (withVirtualRobots) { const virtualRobots = VirtualRobots.of({ fakeNetworking: true, @@ -44,9 +50,19 @@ if (withVirtualRobots) { { frequency: 10, simulator: ChartSimulator.of() }, ], }) - virtualRobots.startSimulators() + let stopSimulators: () => void | undefined + reaction( + () => webSocketProxyNUClearNetServer.numConnections > 0, + enable => { + if (enable) { + // tslint:disable-next-line no-console + console.log('Client connected, starting simulator') + stopSimulators = virtualRobots.startSimulators() + } else if (stopSimulators) { + // tslint:disable-next-line no-console + console.log('No clients remain connected, stopping simulator') + } + }, + { fireImmediately: true }, + ) } - -WebSocketProxyNUClearNetServer.of(WebSocketServer.of(sioNetwork.of('/nuclearnet')), { - fakeNetworking: withVirtualRobots, -})