diff --git a/packages/controller/src/HostConnection.ts b/packages/controller/src/HostConnection.ts index 72185d37..164f3e82 100644 --- a/packages/controller/src/HostConnection.ts +++ b/packages/controller/src/HostConnection.ts @@ -269,12 +269,14 @@ export default class HostConnection extends BaseConnection { } async handleInstanceSaveDetailsUpdatesEvent(event: lib.InstanceSaveDetailsUpdatesEvent) { + const now = Date.now(); const updates: lib.SaveDetails[] = []; for (const save of event.updates) { const existingSave = this._controller.saves.get(save.id); if (existingSave && save.equals(existingSave)) { continue; } + save.updatedAt = now; this._controller.saves.set(save.id, save); updates.push(save); } @@ -283,6 +285,7 @@ export default class HostConnection extends BaseConnection { for (const [id, save] of this._controller.saves) { if (save.instanceId === event.instanceId && !updatedSaves.has(id)) { save.isDeleted = true; + save.updatedAt = now; updates.push(save); this._controller.saves.delete(id); } diff --git a/packages/host/src/Instance.ts b/packages/host/src/Instance.ts index c49b3035..22c43cf7 100644 --- a/packages/host/src/Instance.ts +++ b/packages/host/src/Instance.ts @@ -402,6 +402,7 @@ rcon.print(game.table_to_json(players))`.replace(/\r?\n/g, " "); stat.mtimeMs, name === loadedSave, name === defaultSave, + 0, // Set by controller false, )); } diff --git a/packages/lib/src/data/messages_instance.ts b/packages/lib/src/data/messages_instance.ts index 17a27adf..dbc32be1 100644 --- a/packages/lib/src/data/messages_instance.ts +++ b/packages/lib/src/data/messages_instance.ts @@ -290,6 +290,8 @@ export class SaveDetails { public mtimeMs: number, public loaded: boolean, public loadByDefault: boolean, + /** Millisecond Unix timestamp this entry was last updated at */ + public updatedAt: number, public isDeleted: boolean, ) { } @@ -301,6 +303,7 @@ export class SaveDetails { "mtimeMs": Type.Number(), "loaded": Type.Boolean(), "loadByDefault": Type.Boolean(), + "updatedAt": Type.Number(), "isDeleted": Type.Boolean(), }); @@ -313,6 +316,7 @@ export class SaveDetails { json.mtimeMs, json.loaded, json.loadByDefault, + json.updatedAt, json.isDeleted, ); } @@ -322,16 +326,16 @@ export class SaveDetails { return `${this.instanceId}/${this.name}`; } - get updatedAt() { - return this.mtimeMs; - } - /** * Compare this save with another save. * @param other - save to compare with. * @returns true if this save is identical to the provided save */ equals(other: SaveDetails) { + // Note that updatedAt is not included in the equality check because + // instances send the whole list of saves with updatedAt set to zero + // to the controller whenever any save changes and this equals check + // is used to filter whether a save was updated. return ( this.instanceId === other.instanceId && this.type === other.type