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.
76 lines
3.1 KiB
C#
76 lines
3.1 KiB
C#
namespace IslaApocalypse.Core
|
|
{
|
|
/// <summary>
|
|
/// A row in the TERRAIN material schema — what the natural world is made of.
|
|
/// → `Design - Data - Material Schema.md` §1, D-054.
|
|
///
|
|
/// PROPERTIES-FROM-TYPE: a column run stores only a <see cref="MaterialKey"/>. Every property
|
|
/// lives here and is reached by registry lookup. Nothing is ever stored per-run.
|
|
/// → `Design - Data - Column Model.md`.
|
|
///
|
|
/// ⚠ THERE IS NO MESH-STYLE FIELD ON THIS ROW, AND THERE MUST NEVER BE ONE.
|
|
/// Mesh style is per-ORIGIN, not per-material: natural terrain meshes smooth, player-placed
|
|
/// blocks mesh as cubes, and the same material can be both. The origin flag lives on the run
|
|
/// (<see cref="RunOrigin"/>), which is where the mesher reads it.
|
|
/// → D-054 open notes ("material does not override mesh style"), `Design - Rendering - Mesher.md`.
|
|
///
|
|
/// APPEND-ONLY. Adding a material is one new row in <see cref="MaterialRegistry"/> — never a
|
|
/// code change anywhere else. No material logic is hardcoded anywhere.
|
|
/// </summary>
|
|
public sealed class TerrainMaterial
|
|
{
|
|
/// <summary>Identity. A registry key, not an ordinal. → <see cref="MaterialKey"/>.</summary>
|
|
public MaterialKey Key { get; }
|
|
|
|
/// <summary>Human-facing name. Presentation only — never an identity, never a lookup key.</summary>
|
|
public string DisplayName { get; }
|
|
|
|
/// <summary>Mining difficulty. Units deliberately unfixed this phase; relative for now.</summary>
|
|
public float Hardness { get; }
|
|
|
|
/// <summary>
|
|
/// What a mined voxel gives. SEAM: the resource/item schema is deferred, so this currently
|
|
/// names a material key. When resources become their own schema this becomes a resource key
|
|
/// — one field's type, not a redesign.
|
|
/// </summary>
|
|
public MaterialKey YieldKey { get; }
|
|
|
|
/// <summary>How much <see cref="YieldKey"/> one mined voxel gives.</summary>
|
|
public int YieldPerVoxel { get; }
|
|
|
|
/// <summary>
|
|
/// How much structural support this material carries as NATURAL terrain.
|
|
/// Consumed by `Design - Systems - Structural Integrity.md` (stability scalar, D-055).
|
|
/// Natural terrain is a LAZY anchor there — this is the value it anchors with.
|
|
/// </summary>
|
|
public float NaturalSupportStrength { get; }
|
|
|
|
/// <summary>
|
|
/// Runtime-only dense index, assigned by the registry in registration order.
|
|
///
|
|
/// ⚠⚠ NEVER SERIALIZE THIS. NEVER SEND IT OVER A WIRE. NEVER STORE IT IN A BLUEPRINT.
|
|
/// It exists solely so hot loops can index dense arrays instead of hashing strings. It
|
|
/// changes whenever registration order changes — which a mod adding a row will do. The
|
|
/// identity that persists is <see cref="Key"/>, always.
|
|
/// </summary>
|
|
public int RuntimeIndex { get; internal set; } = -1;
|
|
|
|
public TerrainMaterial(
|
|
MaterialKey key,
|
|
string displayName,
|
|
float hardness,
|
|
MaterialKey yieldKey,
|
|
int yieldPerVoxel,
|
|
float naturalSupportStrength)
|
|
{
|
|
Key = key;
|
|
DisplayName = displayName;
|
|
Hardness = hardness;
|
|
YieldKey = yieldKey;
|
|
YieldPerVoxel = yieldPerVoxel;
|
|
NaturalSupportStrength = naturalSupportStrength;
|
|
}
|
|
|
|
public override string ToString() => $"TerrainMaterial({Key})";
|
|
}
|
|
}
|