roooooms 2

This commit is contained in:
2025-09-06 22:22:36 -04:00
parent 03b751dda6
commit 2aa5352350
15 changed files with 473 additions and 1004 deletions

View File

@@ -1,6 +1,7 @@
import Logging from "@proxnet/undead-logging";
import type KV from "../../persistence/kv.ts";
import { type ServerBase } from "../../server.ts";
import { DatabaseSubroom, FactoryMode, RoomDataTypes, RoomSave, WriteMode } from "./RoomDataTypes.ts";
import { DatabaseSubroom, FactoryMode, RoomDataTypes, RoomSave, RoomSaveMap, WriteMode } from "./RoomDataTypes.ts";
export interface SubroomFactoryOptions {
mode: FactoryMode,
@@ -8,6 +9,8 @@ export interface SubroomFactoryOptions {
id: number
}
const log = new Logging("SubroomFactoryBase");
export class SubroomFactory {
#server: ServerBase;
@@ -19,7 +22,7 @@ export class SubroomFactory {
writeMode: WriteMode = WriteMode.WriteIfFree;
#obj: DatabaseSubroom | null = null;
#saves: RoomSave[] | null = null;
#saves: RoomSaveMap | null = null;
#cannotAccessBeforeInitError = new Error("Cannot access properties before initialization");
#cannotWriteBeforeInitError = new Error("Cannot write before initialization");
@@ -32,13 +35,22 @@ export class SubroomFactory {
}
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;
if (options.mode == FactoryMode.Fetch && data == null) throw new Error("No such subroom");
const saves = await this.#kv.getKv().get<RoomSaveMap>([options.id, 'saves']);
this.#saves = saves.value ?? new Map<number, RoomSave>();
this.#obj = options.mode == FactoryMode.Fetch ? data.value : {
RoomId: 0,
RoomSceneLocationId: "",
Name: "Subroom data init failed, contact an admin!",
IsSandbox: false,
MaxPlayers: 8,
CanMatchmakeInto: true,
LatestSaveId: null
}; // use template object when writing
this.#subroomId = options.id;
return this;
@@ -66,7 +78,7 @@ export class SubroomFactory {
IsSandbox: this.IsSandbox,
MaxPlayers: this.MaxPlayers,
CanMatchmakeInto: this.CanMatchmakeInto,
DataModifiedAt: save.SavedAt,
DataModifiedAt: save.SavedAt.toISOString(),
DataBlobName: save.DataBlobName
}
}
@@ -98,24 +110,41 @@ export class SubroomFactory {
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();
while (this.#saves.has(newId)) newId = this.#getAvailableSaveId();
return newId;
}
addSave(dataBlobName: string) {
/**
* Add a save (history) to the scene. Automatically resets the LatestSaveId.
*
* Use empty string for no datablob
*
* @param dataBlobName Filename of datablob on CDN
*/
addSave(dataBlobName?: string) {
if (!this.#saves) throw this.#cannotAccessBeforeInitError;
this.#saves.push({
SaveId: this.#getAvailableSaveId(),
DataBlobName: dataBlobName,
SavedAt: new Date().toISOString()
const newId = this.#getAvailableSaveId();
this.#saves.set(newId, {
DataBlobName: dataBlobName ?? "",
SavedAt: new Date()
});
this.LatestSaveId = newId;
}
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);
if (!this.#saves || !this.#obj) throw this.#cannotAccessBeforeInitError;
else if (!this.#obj.LatestSaveId) throw new Error(`No save is marked as the latest save`);
else {
if (this.#saves.size === 0) {
log.w(`No save could be found when fetching the latest save for subroomid ${this.#subroomId}!`);
return null;
} else if (this.#saves.size === 1) return this.#saves.values().toArray()[0];
else return this.#saves.get(this.#obj.LatestSaveId);
}
}
}