Observer embryo, Maestro done
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
|
||||
export class ArenaAgentLoader {
|
||||
|
||||
constructor(arenaCnx, storage, debug = false) {
|
||||
this.cnx = arenaCnx
|
||||
this.storage = storage
|
||||
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.storage.agentsIndexKey))
|
||||
}
|
||||
|
||||
async #loadAgentFromHash(agentId) {
|
||||
const key = this.storage.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,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user