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, }, }) } }