This commit is contained in:
2025-09-03 14:32:02 -04:00
parent c6e2b6e4d3
commit 03b751dda6
22 changed files with 1429 additions and 150 deletions

View File

@@ -0,0 +1,121 @@
import type KV from "../../persistence/kv.ts";
import { type ServerBase } from "../../server.ts";
import { DatabaseSubroom, FactoryMode, RoomDataTypes, RoomSave, WriteMode } from "./RoomDataTypes.ts";
export interface SubroomFactoryOptions {
mode: FactoryMode,
writeMode: WriteMode
id: number
}
export class SubroomFactory {
#server: ServerBase;
#kv: KV;
#subroomId: number | null = null;
factoryMode: FactoryMode = FactoryMode.Fetch;
writeMode: WriteMode = WriteMode.WriteIfFree;
#obj: DatabaseSubroom | null = null;
#saves: RoomSave[] | null = null;
#cannotAccessBeforeInitError = new Error("Cannot access properties before initialization");
#cannotWriteBeforeInitError = new Error("Cannot write before initialization");
constructor(server: ServerBase, kv: KV) {
this.#server = server;
this.#kv = kv;
}
async init(options: SubroomFactoryOptions) {
const data = await this.#kv.getKv().get<DatabaseSubroom>([options.id, 'meta']);
if (data == null && this.factoryMode == FactoryMode.Fetch) throw new Error("No such subroom");
const saves = await this.#kv.getKv().get<RoomSave[]>([options.id, 'saves']);
this.#saves = saves.value;
this.#obj = data.value;
this.#subroomId = options.id;
return this;
}
async write() {
if (!this.#obj) throw this.#cannotWriteBeforeInitError;
if (!this.#subroomId) throw new Error("No RoomSceneId set");
await this.#kv.getKv().set([this.#subroomId, 'meta'], this.#obj);
await this.#kv.getKv().set([this.#subroomId, 'saves'], this.#saves);
this.#server.emit('room.subroom.updated', { subroom: this });
}
export(): RoomDataTypes.RoomScene {
if (!this.#subroomId) throw this.#cannotAccessBeforeInitError;
const save = this.getLatestSave();
if (!save) throw new Error("No save to export");
return {
RoomId: this.RoomId,
RoomSceneId: this.#subroomId,
RoomSceneLocationId: this.RoomSceneLocationId,
Name: this.Name,
IsSandbox: this.IsSandbox,
MaxPlayers: this.MaxPlayers,
CanMatchmakeInto: this.CanMatchmakeInto,
DataModifiedAt: save.SavedAt,
DataBlobName: save.DataBlobName
}
}
get RoomId() { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else return this.#obj.RoomId; }
set RoomId(data) { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else this.#obj.RoomId = data }
get RoomSceneId() { if (!this.#subroomId) throw this.#cannotAccessBeforeInitError; else return this.#subroomId; }
get RoomSceneLocationId() { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else return this.#obj.RoomSceneLocationId; }
set RoomSceneLocationId(data) { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else this.#obj.RoomSceneLocationId = data }
get Name() { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else return this.#obj.Name; }
set Name(data) { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else this.#obj.Name = data }
get IsSandbox() { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else return this.#obj.IsSandbox; }
set IsSandbox(data) { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else this.#obj.IsSandbox = data }
get MaxPlayers() { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else return this.#obj.MaxPlayers; }
set MaxPlayers(data) { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else this.#obj.MaxPlayers = data }
get CanMatchmakeInto() { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else return this.#obj.CanMatchmakeInto; }
set CanMatchmakeInto(data) { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else this.#obj.CanMatchmakeInto = data }
get LatestSaveId() { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else return this.#obj.LatestSaveId; }
set LatestSaveId(data) { if (!this.#obj) throw this.#cannotAccessBeforeInitError; else this.#obj.LatestSaveId = data }
#getAvailableSaveId() {
if (!this.#saves) throw this.#cannotAccessBeforeInitError;
let newId = Math.round(Math.random() * Math.pow(2, 31));
while (this.#saves.some(save => save.SaveId == newId)) newId = this.#getAvailableSaveId();
return newId;
}
addSave(dataBlobName: string) {
if (!this.#saves) throw this.#cannotAccessBeforeInitError;
this.#saves.push({
SaveId: this.#getAvailableSaveId(),
DataBlobName: dataBlobName,
SavedAt: new Date().toISOString()
});
}
getSaves() {
if (!this.#saves) throw this.#cannotAccessBeforeInitError;
return this.#saves;
}
getLatestSave() {
if (!this.#saves) throw this.#cannotAccessBeforeInitError;
return this.#saves.find(save => save.SaveId == this.LatestSaveId);
}
}