Core tests / core (push) Successful in 9m57s
Full verification / application (push) Failing after 5m16s
Full verification / local-brain (push) Failing after 6m15s
Realm simulation / simulated-live-world (push) Failing after 5m32s
WoW integration lab / real-worldserver (push) Canceled after 17m23s
Source branch: feature/ai-brain-router Source commit: c2a09e0460465201a58aaab56c71424e9a96405e
81 lines
3.1 KiB
TypeScript
81 lines
3.1 KiB
TypeScript
import { env } from 'cloudflare:workers';
|
|
import { seed } from './seed';
|
|
import type { State,StateStore,Bot,Recipe,Home } from './types';
|
|
|
|
function migrate(raw:any):State{
|
|
const defaults=seed();
|
|
const recipes:Recipe[]=(raw.recipes??defaults.recipes).map((r:Recipe)=>r);
|
|
for(const recipe of defaults.recipes){
|
|
if(!recipes.some(r=>r.id===recipe.id))recipes.push(structuredClone(recipe));
|
|
}
|
|
|
|
const homes:Home[]=(raw.homes??defaults.homes).map((h:Home)=>h);
|
|
for(const home of defaults.homes){
|
|
if(!homes.some(h=>h.id===home.id))homes.push(structuredClone(home));
|
|
}
|
|
|
|
const bots:Bot[]=(raw.bots??[]).map((b:any)=>{
|
|
const seeded=defaults.bots.find(x=>x.id===b.id);
|
|
const home=homes.find(h=>h.residentIds.includes(b.id));
|
|
return {
|
|
...b,
|
|
tier:b.tier??seeded?.tier??'resident',
|
|
mortal:b.mortal??true,
|
|
plotArmorHpFloor:b.plotArmorHpFloor??seeded?.plotArmorHpFloor??0,
|
|
simulationBand:b.simulationBand??seeded?.simulationBand??(b.status==='online'?'background':'dormant'),
|
|
homeId:b.homeId??seeded?.homeId??home?.id,
|
|
routine:b.routine??seeded?.routine??{wakeHour:7,sleepHour:23,preferredZones:[b.zone].filter(Boolean)},
|
|
autonomy:{managed:b.autonomy?.managed??false,...(b.autonomy??{})}
|
|
};
|
|
});
|
|
for(const hero of defaults.bots.filter(b=>b.tier==='hero')){
|
|
if(!bots.some(b=>b.id===hero.id||b.name.toLowerCase()===hero.name.toLowerCase()))bots.push(structuredClone(hero));
|
|
}
|
|
|
|
for(const home of homes){
|
|
home.residentIds=home.residentIds.filter(id=>bots.some(b=>b.id===id));
|
|
}
|
|
for(const bot of bots){
|
|
if(bot.homeId){
|
|
const home=homes.find(h=>h.id===bot.homeId);
|
|
if(home&&!home.residentIds.includes(bot.id)&&home.residentIds.length<home.capacity)home.residentIds.push(bot.id);
|
|
}
|
|
}
|
|
|
|
return {
|
|
...defaults,
|
|
...raw,
|
|
bots,
|
|
homes,
|
|
recipes,
|
|
events:raw.events??defaults.events,
|
|
sequence:raw.sequence??defaults.sequence,
|
|
settings:{
|
|
...defaults.settings,
|
|
...(raw.settings??{}),
|
|
hardcore:{...defaults.settings.hardcore,...(raw.settings?.hardcore??{})},
|
|
population:{...defaults.settings.population,...(raw.settings?.population??{})},
|
|
brains:{...defaults.settings.brains,...(raw.settings?.brains??{})}
|
|
},
|
|
director:{...defaults.director,...(raw.director??{})},
|
|
population:{...defaults.population,...(raw.population??{})},
|
|
operations:raw.operations??{}
|
|
};
|
|
}
|
|
|
|
export class D1Store implements StateStore {
|
|
async load():Promise<State>{
|
|
if(!env.DB) throw new Error('Realm database unavailable');
|
|
const initial=seed();
|
|
await env.DB.prepare('INSERT OR IGNORE INTO realm_state (id,revision,payload) VALUES (?,?,?)').bind('realm',0,JSON.stringify(initial)).run();
|
|
const row=await env.DB.prepare('SELECT payload FROM realm_state WHERE id=?').bind('realm').first<{payload:string}>();
|
|
if(!row)throw new Error('Realm state unavailable');
|
|
return migrate(JSON.parse(row.payload));
|
|
}
|
|
async save(s:State,expected:number){
|
|
s.revision=expected+1;
|
|
const result=await env.DB!.prepare('UPDATE realm_state SET revision=?,payload=? WHERE id=? AND revision=?').bind(s.revision,JSON.stringify(s),'realm',expected).run();
|
|
if(result.meta.changes!==1)throw new Error('State changed in another request. Refresh and try again.');
|
|
}
|
|
}
|