83 lines
2.7 KiB
JavaScript
83 lines
2.7 KiB
JavaScript
|
|
export class ArenaAgentLoader {
|
|
|
|
constructor(arenaCnx, arenaStorage, debug = false) {
|
|
this.cnx = arenaCnx
|
|
this.arenaStorage = arenaStorage
|
|
this.debug = debug
|
|
}
|
|
|
|
async loadAgents(expectedIds = null) {
|
|
// TODO: when arena mesh is sharded, iterate all arena Redis connections and merge agent ids
|
|
const agentIds = await this.#listAgentIds(expectedIds)
|
|
const agents = []
|
|
const errors = []
|
|
|
|
for(const agentId of agentIds) {
|
|
const result = await this.#loadAgentFromHash(agentId)
|
|
if(!result.ok) {
|
|
errors.push(result.err)
|
|
continue
|
|
}
|
|
agents.push(result.agent)
|
|
}
|
|
|
|
if(errors.length) return({ ok: false, err: errors.join('; '), agents: [] })
|
|
return({ ok: true, agents })
|
|
}
|
|
|
|
#parseHashField(raw) {
|
|
if(raw == null) return(null)
|
|
if(typeof(raw) === 'object') return(raw)
|
|
try { return(JSON.parse(raw)) }
|
|
catch { return(null) }
|
|
}
|
|
|
|
#isVector(v) {
|
|
return(
|
|
v &&
|
|
typeof(v) === 'object' &&
|
|
typeof(v.x) === 'number' &&
|
|
typeof(v.y) === 'number' &&
|
|
typeof(v.z) === 'number'
|
|
)
|
|
}
|
|
|
|
async #listAgentIds(expectedIds = null) {
|
|
if(Array.isArray(expectedIds) && expectedIds.length) return([...expectedIds])
|
|
return(await this.cnx.redisSmembers(this.arenaStorage.agentsIndexKey))
|
|
}
|
|
|
|
async #loadAgentFromHash(agentId) {
|
|
const key = this.arenaStorage.agentHashKey.replace(/\[UID\]/g, agentId)
|
|
const positionRaw = await this.cnx.redisHget(key, 'position')
|
|
const vectorRaw = await this.cnx.redisHget(key, 'vector')
|
|
let position = this.#parseHashField(positionRaw)
|
|
let vector = this.#parseHashField(vectorRaw)
|
|
|
|
if(!this.#isVector(vector)) {
|
|
const segmentRaw = await this.cnx.redisHget(key, 'segment')
|
|
const segment = this.#parseHashField(segmentRaw)
|
|
if(segment) {
|
|
if(!this.#isVector(vector) && this.#isVector(segment.vector)) vector = segment.vector
|
|
if(!this.#isVector(position) && this.#isVector(segment.position)) position = segment.position
|
|
}
|
|
}
|
|
|
|
if(!this.#isVector(vector)) return({ ok: false, err: `Invalid or missing vector for ${agentId}` })
|
|
if(!this.#isVector(position)) position = { x: 0, y: 0, z: 0 }
|
|
|
|
return({
|
|
ok: true,
|
|
agent: {
|
|
id: agentId,
|
|
position: { ...position },
|
|
vector: { ...vector },
|
|
since: 0,
|
|
generation: 1,
|
|
},
|
|
})
|
|
}
|
|
|
|
}
|