Stands up the CODE_REPO the rewrite is written into (D-049, D-058). Godot 4.7.2 /
.NET 8 / Godot.NET.Sdk 4.7.2. Nothing is generated, meshed, or ported — this is the
shell and the two data contracts.
Four layers, each with its boundary stated in a directory README:
Core/ math + data only, and engine-free — depends on nothing above it
Server/ authoritative logic (empty this phase)
Client/ rendering (empty this phase)
Tools/ the offline generator — may NOT reference Client (Phase 1 fills it)
Contracts (compiling stubs, no algorithms):
- Column model (D-053): a 2D grid of columns, each a stack of (material, thickness)
runs, any material at any depth. Air is the TOP RUN — there is no air-vs-solid
height branch, and no surface-height accessor exists to reintroduce one. Water is
not a band; it stays an overlay.
- Material schemas (D-054): terrain and building as two append-only registries,
bridged by a recipe seam that is deliberately EMPTY. Identity is a registry key,
never a serialized ordinal. Mesh style is per-ORIGIN and is not a material field.
Rails, so Phase 1 inherits them rather than rediscovering them:
- GenerationScale: MapSize is a parameter, everything derives from it, nothing uses
a raw pixel number. Tightening over the reference — decorrelation offsets are
declared in map widths, not pixels (chat1/00 §4.2).
- ToolingPaths: config/blueprint/output paths all env-overridable, resolved in one
place, so a batch cannot touch the developer's live files.
- FileSafety: the permanent no-deletion rules as throws rather than sentences.
user:// isolation: project name and use_custom_user_dir both pin the runtime dir to
~/.local/share/islaApocalypse-v2/, away from the old prototype's preserved seeds and
batches. Tools/Scenes/UserDirProbe.tscn confirms it rather than assuming it.
47 lines
2.1 KiB
C#
47 lines
2.1 KiB
C#
using System;
|
|
|
|
namespace IslaApocalypse.Core
|
|
{
|
|
/// <summary>
|
|
/// A material's IDENTITY. → `Design - Data - Material Schema.md`, D-054.
|
|
///
|
|
/// ⚠⚠ IDENTITY IS A REGISTRY KEY, NEVER A POSITIONAL ORDINAL.
|
|
///
|
|
/// This is deliberately a stable string key and not an enum. The prototype's blueprint format
|
|
/// keyed on enum ordinals, which made the enum's DECLARATION ORDER a wire format: inserting a
|
|
/// value in the middle silently reinterpreted every world already generated
|
|
/// (→ `Design - Tooling - Offline Generation.md`: "anything that changes its format or its enum
|
|
/// ordinals breaks every world already generated"). The registry is also the mod surface
|
|
/// (→ D-011, D-043) — a mod adds rows, and rows cannot be given ordinals by a third party.
|
|
///
|
|
/// So: adding a material is one new row, appended anywhere, in any order, by anyone, forever.
|
|
///
|
|
/// No serialization is built this phase. This type exists so that when it is, the identity it
|
|
/// writes is already the key rather than a position.
|
|
/// </summary>
|
|
public readonly struct MaterialKey : IEquatable<MaterialKey>
|
|
{
|
|
/// <summary>The stable identity. Lowercase, dot-namespaced: "core.limestone", "mod.basalt".</summary>
|
|
public readonly string Value;
|
|
|
|
public MaterialKey(string value)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
throw new ArgumentException("A material key may not be null or blank.", nameof(value));
|
|
Value = value;
|
|
}
|
|
|
|
/// <summary>The unset key. Distinguishable from any real row; never registered.</summary>
|
|
public static readonly MaterialKey None = default;
|
|
|
|
public bool IsNone => Value == null;
|
|
|
|
public bool Equals(MaterialKey other) => string.Equals(Value, other.Value, StringComparison.Ordinal);
|
|
public override bool Equals(object obj) => obj is MaterialKey k && Equals(k);
|
|
public override int GetHashCode() => Value == null ? 0 : StringComparer.Ordinal.GetHashCode(Value);
|
|
public override string ToString() => Value ?? "<none>";
|
|
|
|
public static bool operator ==(MaterialKey a, MaterialKey b) => a.Equals(b);
|
|
public static bool operator !=(MaterialKey a, MaterialKey b) => !a.Equals(b);
|
|
}
|
|
}
|