159 lines
4.9 KiB
JavaScript
159 lines
4.9 KiB
JavaScript
import { AccesRights } from '../accesRights.js'
|
|
import { GpsStorageReader } from './gpsStorageReader.js'
|
|
import { RequestorRegistry } from './requestorRegistry.js'
|
|
import { SimState } from '../GPS/simulationState.js'
|
|
|
|
export class observerServer {
|
|
|
|
constructor(configHelper, allRediscnx, debug) {
|
|
this.configHelper = configHelper
|
|
this.observerConfig = configHelper.config
|
|
this.allRediscnx = allRediscnx
|
|
this.debug = debug
|
|
this.accessRights = new AccesRights(this.observerConfig, debug)
|
|
this.arenaCnx = null
|
|
this.arenaCnxs = []
|
|
this.systemCnx = null
|
|
this.gpsStorageReader = null
|
|
this.requestorRegistry = null
|
|
this.state = SimState.IDLE
|
|
this.bigBangEpoch = null
|
|
}
|
|
|
|
getObserverSettings() {
|
|
const observer = this.observerConfig.observer ?? {}
|
|
return({
|
|
senderId: observer.senderId ?? 'observer',
|
|
scanIntervalMs: observer.scanIntervalMs ?? 300,
|
|
frustumEventsChannel: observer.observerFrustumEventsChannel
|
|
?? 'system:observer:subscribed[UID]:agents',
|
|
lifecycle: {
|
|
arenaChannel: observer.lifecycle?.arenaChannel ?? 'arena:lifecycle',
|
|
godsReadyChannel: observer.lifecycle?.godsReadyChannel ?? 'arena:gods:ready',
|
|
},
|
|
})
|
|
}
|
|
|
|
getGpsStorageSettings() {
|
|
const gps = this.observerConfig.gps ?? {}
|
|
return(gps.GPSstorage ?? null)
|
|
}
|
|
|
|
initGpsStorageReader() {
|
|
const gpsStorage = this.getGpsStorageSettings()
|
|
if(gpsStorage && this.systemCnx) {
|
|
this.gpsStorageReader = new GpsStorageReader(this.systemCnx, gpsStorage, this.debug)
|
|
this.initRequestorRegistry()
|
|
}
|
|
}
|
|
|
|
initRequestorRegistry() {
|
|
if(!this.gpsStorageReader || this.requestorRegistry) return
|
|
const { scanIntervalMs } = this.getObserverSettings()
|
|
this.requestorRegistry = new RequestorRegistry(
|
|
this.gpsStorageReader,
|
|
() => this.now(),
|
|
scanIntervalMs,
|
|
(subscriberId, payload) => this.publishFrustumAgentEvents(
|
|
subscriberId,
|
|
payload.agents,
|
|
payload.t
|
|
),
|
|
this.debug
|
|
)
|
|
}
|
|
|
|
async publishFrustumAgentEvents(subscriberId, agents, t) {
|
|
if(!this.systemCnx || !subscriberId) return
|
|
if(!Array.isArray(agents) || !agents.length) return
|
|
|
|
const { frustumEventsChannel } = this.getObserverSettings()
|
|
const chan = frustumEventsChannel.replace(/\[UID\]/g, subscriberId)
|
|
const senderId = this.getObserverSettings().senderId
|
|
|
|
for(const agent of agents) {
|
|
if(!agent?.id || !agent?.position) continue
|
|
|
|
await this.systemCnx.redisPublish(chan, {
|
|
eventType: 'move',
|
|
sender: senderId,
|
|
payload: {
|
|
aid: agent.id,
|
|
coords: {
|
|
x: agent.position.x,
|
|
y: agent.position.y,
|
|
z: agent.position.z,
|
|
},
|
|
t,
|
|
},
|
|
})
|
|
}
|
|
|
|
if(this.debug) {
|
|
console.log(`[Observer] Frustum events: ${agents.length} agent(s) on ${chan} at t=${t}`)
|
|
}
|
|
}
|
|
|
|
isLive() {
|
|
return(this.state === SimState.LIVE)
|
|
}
|
|
|
|
simNow() {
|
|
if(this.bigBangEpoch === null) return(null)
|
|
return((performance.now() - this.bigBangEpoch) / 1000)
|
|
}
|
|
|
|
now() {
|
|
if(this.isLive()) return(this.simNow())
|
|
return(null)
|
|
}
|
|
|
|
onYourMarks() {
|
|
this.state = SimState.PREPARE
|
|
this.bigBangEpoch = null
|
|
this.requestorRegistry?.clear()
|
|
}
|
|
|
|
onBigBang() {
|
|
this.bigBangEpoch = performance.now()
|
|
this.state = SimState.LIVE
|
|
}
|
|
|
|
onSimulationStopped(payload = {}) {
|
|
this.requestorRegistry?.clear()
|
|
this.state = SimState.IDLE
|
|
this.bigBangEpoch = null
|
|
if(this.debug) console.log(`[Observer] simulationStopped at t=${payload.t}`)
|
|
}
|
|
|
|
wireSystemConnexion(cnx) {
|
|
cnx.observerSrv = this
|
|
cnx.accessRights = this.accessRights
|
|
cnx.reloadAccessRights = () => this.reloadAccessRights()
|
|
cnx.getAccessRights = () => this.getAccessRights()
|
|
if(!this.systemCnx || cnx.redisConfig.role === 'primary') {
|
|
this.systemCnx = cnx
|
|
this.initGpsStorageReader()
|
|
}
|
|
}
|
|
|
|
wireArenaConnexion(cnx) {
|
|
cnx.observerSrv = this
|
|
this.arenaCnxs.push(cnx)
|
|
if(!this.arenaCnx || cnx.redisConfig.role === 'primary') {
|
|
this.arenaCnx = cnx
|
|
}
|
|
}
|
|
|
|
async reloadAccessRights() {
|
|
await this.configHelper.refreshAccessRights()
|
|
this.observerConfig.accessRights = this.configHelper.config.accessRights
|
|
this.accessRights.refreshAccessRights(this.observerConfig)
|
|
}
|
|
|
|
getAccessRights() {
|
|
return(this.observerConfig.accessRights)
|
|
}
|
|
|
|
}
|