Files
factorio-expcluster/exp_scenario/messages.ts
T
bbassieandClaude Fable 5.1 2959d7476b Send every value, register protected entities, fix the pattern offset
- The instance sends every value of a feature, defaults included, so
  update_config is one loop which sets each field and compares. The
  stored table is the last set of values, and _apply is gone.
- values_equal compares table sizes before the contents.
- Protected entities are registered with register_on_object_destroyed
  and forgotten in on_object_destroyed, which covers every way an
  entity can go. The four removal handlers and the validity checks are
  gone. Entities destroyed while the feature is disabled are swept when
  it is enabled again. Saves from before the registrations table get it
  through the Storage on_init callback.
- Spawn area applied the water offset twice and the pattern offset
  never. The pattern tiles now move with the entities above them.
- pruneFeatureValues reads a validation result instead of catching an
  error, and FeaturesPage hands its pending state and unsaved bar to
  helpers.
- Shorter comments throughout.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 12:55:08 +00:00

129 lines
3.5 KiB
TypeScript

import * as lib from "@clusterio/lib";
import { Type, Static } from "@sinclair/typebox";
import type { FeatureValue } from "./features.js";
/** Create the roles and permission groups the scenario shipped with, see seed.ts. */
export class SeedRequest {
declare ["constructor"]: typeof SeedRequest;
static plugin = "exp_scenario" as const;
static type = "request" as const;
static src = "control" as const;
static dst = "controller" as const;
static permission = "exp_scenario.seed" as const;
constructor() {}
}
const FeatureValueSchema = Type.Union([Type.Boolean(), Type.Number(), Type.String(), Type.Array(Type.String()), Type.Null()]);
/** The config of one feature, see features.ts. Only values which differ from the default are stored. */
export class FeatureRecord {
constructor(
/** Name of the feature in features.ts */
public id: string,
public enabled: boolean,
public values: Record<string, FeatureValue> = {},
public updatedAtMs: number = 0,
public isDeleted: boolean = false,
) {}
static jsonSchema = Type.Object({
id: Type.String(),
enabled: Type.Boolean(),
values: Type.Record(Type.String(), FeatureValueSchema),
updated_at_ms: Type.Optional(Type.Number()),
is_deleted: Type.Optional(Type.Boolean()),
});
toJSON() {
const json: Static<typeof FeatureRecord.jsonSchema> = {
id: this.id,
enabled: this.enabled,
values: this.values,
};
if (this.updatedAtMs) {
json.updated_at_ms = this.updatedAtMs;
}
if (this.isDeleted) {
json.is_deleted = true;
}
return json;
}
static fromJSON(json: Static<typeof this.jsonSchema>) {
return new this(
json.id,
json.enabled,
json.values,
json.updated_at_ms ?? 0,
json.is_deleted ?? false,
);
}
}
export class FeatureUpdatedEvent {
declare ["constructor"]: typeof FeatureUpdatedEvent;
static plugin = "exp_scenario" as const;
static type = "event" as const;
static src = "controller" as const;
static dst = ["control", "instance"] as const;
static permission = "exp_scenario.config.view" as const;
constructor(
public updates: FeatureRecord[],
) {}
static jsonSchema = Type.Object({
updates: Type.Array(FeatureRecord.jsonSchema),
});
toJSON() {
return { updates: this.updates.map(feature => feature.toJSON()) };
}
static fromJSON(json: Static<typeof this.jsonSchema>) {
return new this(json.updates.map(feature => FeatureRecord.fromJSON(feature)));
}
}
/** List the config of every feature. */
export class FeatureListRequest {
declare ["constructor"]: typeof FeatureListRequest;
static plugin = "exp_scenario" as const;
static type = "request" as const;
static src = ["control", "instance"] as const;
static dst = "controller" as const;
static permission = "exp_scenario.config.view" as const;
static Response = lib.jsonArray(FeatureRecord);
}
/** Replace the config of a feature, values left out go back to their default. */
export class FeatureUpdateRequest {
declare ["constructor"]: typeof FeatureUpdateRequest;
static plugin = "exp_scenario" as const;
static type = "request" as const;
static src = "control" as const;
static dst = "controller" as const;
static permission = "exp_scenario.config.edit" as const;
static Response = FeatureRecord;
constructor(
public id: string,
public enabled: boolean,
public values: Record<string, FeatureValue>,
) {}
static jsonSchema = Type.Object({
id: Type.String(),
enabled: Type.Boolean(),
values: Type.Record(Type.String(), FeatureValueSchema),
});
static fromJSON(json: Static<typeof this.jsonSchema>) {
return new this(json.id, json.enabled, json.values);
}
}