import { Piece } from "./piece.ts";
import { Registry } from "./registry.ts";
/**
* Abstract base class for piece serializers.
*
* For each piece type there is a serializer that can convert the piece back and
* forth to a key, and that also provides metadata about the type for the map
* editor. Mirrors the Java Serializer<T> interface exactly.
*
* create() and tag() are implemented by every registered serializer with no
* exceptions, so they're enforced at compile time. store()/example()/template()
* default to throwing since not every serializer needs to implement all three
* directly (see TypeOnlySerializer).
*/
export abstract class Serializer {
/**
* Reconstruct a piece from its resolved args array.
* String args are plain values; Piece args are already-resolved nested
* registry lookups (the Registry resolves "^"-escaped sub-keys before
* calling create, exactly as it does today).
*/
abstract create(args: Array<string | Piece>): Piece;
/**
* Return the canonical serialized key for this piece, e.g. "Door|Blue|off".
* The key must be parseable back via create().
*/
store(piece: Piece): string {
throw new Error("Serializer.store() not implemented");
}
/**
* Return a representative instance of this type for display in the map editor.
*/
example(): Piece {
throw new Error("Serializer.example() not implemented");
}
/**
* Given the typeId, return a human-readable template showing the key format,
* e.g. "Door|{color}|{state}". Used by the editor to guide authoring.
*/
template(typeId: string): string {
throw new Error("Serializer.template() not implemented");
}
/**
* Return the editor category for this type, e.g. "Terrain", "Room Features".
*/
abstract tag(): string;
}
/**
* A serializer base that works for any piece defined only by its type.
* The key is just the typeId with no arguments (e.g. "Floor", "Wall", "Fire").
* Subclasses implement create() (return a new instance) and tag().
*/
export abstract class TypeOnlySerializer extends Serializer {
_typeId: string;
constructor(typeId: string) {
super();
this._typeId = typeId;
}
store(piece: Piece): string {
return this._typeId;
}
example(): Piece {
return this.create([]);
}
template(): string {
return this._typeId;
}
}
/**
* Base support for serializers that escape/unescape pieces as part of their
* serialization key. Provides esc() and unesc() helpers for building and
* parsing keys that embed other pieces. Subclasses must implement create()
* and tag(), plus whichever of store()/example()/template() they need.
*/
export abstract class BaseSerializer extends Serializer {
/**
* Escape a piece reference for embedding inside another key.
* Replaces "|" with "^" so the nested key does not break pipe-splitting.
*/
esc(piece: Piece): string {
return Registry.serialize(piece).replaceAll("|", "^");
}
/**
* Unescape a piece reference embedded in a key arg.
* The Registry has already resolved "^"-escaped args into Piece instances
* before calling create(), so this helper is provided only for cases where
* manual resolution is needed outside of create().
*/
unesc<T extends Piece = Piece>(key: string): T {
return Registry.get(key.replaceAll("^", "|")) as T;
}
}