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.
68 lines
3.4 KiB
C#
68 lines
3.4 KiB
C#
using Godot;
|
|
using IslaApocalypse.Core;
|
|
|
|
namespace IslaApocalypse.Tools
|
|
{
|
|
/// <summary>
|
|
/// A print-and-quit diagnostic: resolves and reports this project's user:// directory, then
|
|
/// exits. It generates nothing and writes nothing.
|
|
///
|
|
/// ═══ WHY IT EXISTS ═══
|
|
///
|
|
/// The old prototype is named "islaApocalypse" and owns
|
|
/// ~/.local/share/godot/app_userdata/islaApocalypse/, which holds the PRESERVED reference
|
|
/// seeds, blueprints and batches. A v2 project sharing that name would read and clobber them
|
|
/// at runtime. project.godot pins the isolation two ways (distinct name + custom user dir);
|
|
/// this probe CONFIRMS the pin actually resolves, rather than trusting that it does.
|
|
///
|
|
/// Run it after any change to project.godot's [application] block:
|
|
///
|
|
/// Godot_v4.7.2-stable_mono_linux.x86_64 --headless \
|
|
/// --path ~/celerNexus/islaApocalypse-v2 res://Tools/Scenes/UserDirProbe.tscn
|
|
///
|
|
/// --headless is fine HERE — it hangs only on the snapshot capture's render-frame awaits, and
|
|
/// this awaits nothing. → Tools/README.md, `Design - Tooling - Iteration and Batching.md`.
|
|
/// </summary>
|
|
public partial class UserDirProbe : Node
|
|
{
|
|
public override void _Ready()
|
|
{
|
|
string userDir = OS.GetUserDataDir();
|
|
|
|
// Hand Core the engine-resolved directory — Core is engine-free and never asks Godot itself.
|
|
ToolingPaths.Configure(userDir);
|
|
|
|
GD.Print("==================================================================");
|
|
GD.Print(" user:// PROBE — islaApocalypse-v2");
|
|
GD.Print("==================================================================");
|
|
GD.Print($"project name : {ProjectSettings.GetSetting("application/config/name")}");
|
|
GD.Print($"custom user dir : {ProjectSettings.GetSetting("application/config/use_custom_user_dir")} " +
|
|
$"(\"{ProjectSettings.GetSetting("application/config/custom_user_dir_name")}\")");
|
|
GD.Print($"user:// resolves : {userDir}");
|
|
GD.Print($"globalized : {ProjectSettings.GlobalizePath("user://")}");
|
|
GD.Print("------------------------------------------------------------------");
|
|
GD.Print(" ISOLATION CHECK");
|
|
GD.Print("------------------------------------------------------------------");
|
|
|
|
// The one path this project must never resolve to.
|
|
const string forbidden = "app_userdata/islaApocalypse";
|
|
bool clash = userDir.Replace('\\', '/').TrimEnd('/').EndsWith(forbidden, System.StringComparison.Ordinal);
|
|
GD.Print(clash
|
|
? " ✗ FAIL — resolves to the OLD prototype's dir. Do not run anything else."
|
|
: " ✓ PASS — not the old prototype's app_userdata/islaApocalypse/.");
|
|
|
|
GD.Print("------------------------------------------------------------------");
|
|
GD.Print(" RESOLVED TOOLING PATHS (env-overridable)");
|
|
GD.Print("------------------------------------------------------------------");
|
|
GD.Print(ToolingPaths.Describe());
|
|
GD.Print("------------------------------------------------------------------");
|
|
GD.Print($" Core self-check: {MaterialRegistry.TerrainCount} terrain materials, " +
|
|
$"{MaterialRegistry.BuildingCount} building materials, " +
|
|
$"{RecipeRegistry.Count} recipes (0 is correct — the seam is deliberately empty).");
|
|
GD.Print($" Scale self-check: {new GenerationScale(10240)}");
|
|
GD.Print("==================================================================");
|
|
|
|
GetTree().Quit(clash ? 1 : 0);
|
|
}
|
|
}
|
|
}
|