wip(unreal): VoxelForgeCore UBT module + asset adapter reproduce the standalone world

Luna, integration round 1 (BuildHost only; owner's project and assets untouched):
- New runtime module VoxelForgeCore: one shim per Standalone/Core/core_sources.txt row
  (sources stay canonical under Standalone/), NoPCH/no unity, manifest check; VoxelForge
  links it (no runtime routing yet). UE link-safety audit: 18 shims, 83,843 symbol lines
  vs 399 Unreal-style names, 0 clashes.
- Adapter (editor commandlet path) turns staged copies of the owner's DA_* assets into
  schema-v1 JSON; with clip_radius=3/max_clip_level=8 it reproduces all four Core hashes
  (0xdb2991c73215af4c, 0x8236c5edd7fc8e4f, 0x4c48fa75a543d58e, 0xbea22e76b34a4dfc) and
  walkability 5,642/5,642 at worker limits 1, 8 and 16.
- Noted: the owner's settings asset says max clip level 6 (standalone used 8); Core uses
  25 cm voxels vs the plugin runtime's 12.5 cm.
Not done yet: AVoxelWorld switch and Core runtime route (round 2).
Docs: CODEMAP, ARCHITECTURE, SHARED_CPP_LIBRARY_PLAN, UNREAL_INTEGRATION_REPORT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-08 19:38:18 +02:00
1 parent a1dfc0422e
commit 29ca99af7f
32 files changed
+919 -69

No files matched your search

@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Compat/StandaloneDataAssetGlue.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Compat/UnrealPerlin.cpp"
}
@@ -0,0 +1,9 @@
// The public API is standard-only; this UBT boundary supplies its module export token locally.
#ifndef DLLEXPORT
#if defined(_WIN32)
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __attribute__((visibility("default")))
#endif
#endif
#include "Core/src/VoxelForgeCore.cpp"
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelBiomeDefinition.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelCaveMorphology.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelDensityAblation.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelDensityOpStack.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelDensityProfile.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelDiffLayer.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelGenerator.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelHeightOpStack.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelSettings.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelStrateComposer.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelStrateManager.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelStrateMeasure.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelTerrainOpDefinition.cpp"
}
@@ -0,0 +1,7 @@
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
#define VFCORE_PRIVATE_IMPLEMENTATION 1
#include "CoreNamespacePreamble.h"
namespace vfcore::detail
{
#include "Source/VoxelForge/Private/VoxelWormField.cpp"
}
@@ -0,0 +1,7 @@
#pragma once
// The module entry must see UE's real CoreMinimal; the Core shims intentionally use Compat/CoreMinimal.
#ifndef VFCORE_ENGINE_COREMINIMAL_HEADER
#error VoxelForgeCore must provide the engine CoreMinimal header path for its module entry.
#endif
#include VFCORE_ENGINE_COREMINIMAL_HEADER
@@ -0,0 +1,6 @@
// Core module entry point. Le module garde ses wrappers Core isolés du PCH Unreal.
#include "CoreMinimal.h"
#include "ModuleManager.h"
IMPLEMENT_MODULE(FDefaultModuleImpl, VoxelForgeCore)
@@ -0,0 +1,132 @@
// VoxelForgeCore compiles the canonical Standalone sources in isolated, one-source shims.
// Le module compile les sources canoniques Standalone via des wrappers isolés.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnrealBuildTool;
public class VoxelForgeCore : ModuleRules
{
public VoxelForgeCore(ReadOnlyTargetRules Target) : base(Target)
{
string PluginRoot = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", ".."));
string StandaloneRoot = Path.Combine(PluginRoot, "Standalone");
string ManifestPath = Path.Combine(StandaloneRoot, "Core", "core_sources.txt");
string ShimRoot = Path.Combine(ModuleDirectory, "Private", "Manifest");
string CoreMinimalHeader = Path.Combine(
EngineDirectory, "Source", "Runtime", "Core", "Public", "CoreMinimal.h").Replace('\\', '/');
ValidateManifest(ManifestPath, ShimRoot, StandaloneRoot);
PublicIncludePaths.Add(Path.Combine(StandaloneRoot, "Core", "include"));
PrivateIncludePaths.AddRange(new string[]
{
StandaloneRoot,
Path.Combine(EngineDirectory, "Source", "Runtime", "Core", "Public", "Modules"),
Path.Combine(StandaloneRoot, "Core", "src"),
Path.Combine(StandaloneRoot, "Compat"),
Path.Combine(StandaloneRoot, "Source"),
Path.Combine(StandaloneRoot, "Source", "VoxelForge", "Public"),
Path.Combine(StandaloneRoot, "Source", "VoxelForge", "Private")
});
PrivateDefinitions.Add("VFCORE_ENGINE_COREMINIMAL_HEADER=\"" + CoreMinimalHeader + "\"");
PrivateDefinitions.Add("UE_BUILD_SHIPPING=" + (Target.Configuration == UnrealTargetConfiguration.Shipping ? "1" : "0"));
// The wrapped VoxelForge sources use the standalone compatibility layer, which excludes editor-only fields.
PrivateDefinitions.Add("WITH_EDITORONLY_DATA=0");
PublicDependencyModuleNames.Add("Core");
CppStandard = CppStandardVersion.Cpp20;
// Canonical Standalone code predates UE's stricter warning defaults; keep this narrow to legal local shadowing.
CppCompileWarningSettings.ShadowVariableWarningLevel = WarningLevel.Off;
FPSemantics = FPSemanticsMode.Precise;
PCHUsage = PCHUsageMode.NoPCHs;
bUseUnity = false;
bEnableExceptions = true;
bUseRTTI = true;
}
private static void ValidateManifest(string ManifestPath, string ShimRoot, string StandaloneRoot)
{
if (!File.Exists(ManifestPath))
{
throw new BuildException("VoxelForgeCore source manifest is missing: {0}", ManifestPath);
}
string Root = Path.GetFullPath(StandaloneRoot) + Path.DirectorySeparatorChar;
string[] Sources = File.ReadAllLines(ManifestPath)
.Select(Line => Line.Trim().Replace('\\', '/'))
.Where(Line => Line.Length != 0 && !Line.StartsWith("#", StringComparison.Ordinal))
.ToArray();
if (Sources.Length == 0)
{
throw new BuildException("VoxelForgeCore source manifest is empty: {0}", ManifestPath);
}
if (Sources.Distinct(StringComparer.Ordinal).Count() != Sources.Length)
{
throw new BuildException("VoxelForgeCore source manifest contains duplicate rows: {0}", ManifestPath);
}
if (!Directory.Exists(ShimRoot))
{
throw new BuildException("VoxelForgeCore manifest shim directory is missing: {0}", ShimRoot);
}
HashSet<string> ExpectedShimNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string Source in Sources)
{
if (Path.IsPathRooted(Source) || Source.Split('/').Any(Part => Part == ".."))
{
throw new BuildException("VoxelForgeCore manifest path escapes Standalone: {0}", Source);
}
string CanonicalPath = Path.GetFullPath(Path.Combine(StandaloneRoot, Source.Replace('/', Path.DirectorySeparatorChar)));
if (!CanonicalPath.StartsWith(Root, StringComparison.OrdinalIgnoreCase) || !File.Exists(CanonicalPath))
{
throw new BuildException("VoxelForgeCore canonical source is missing or outside Standalone: {0}", Source);
}
string ShimName = "VFCore_" + Regex.Replace(Source, "[^A-Za-z0-9]+", "_") + ".cpp";
ExpectedShimNames.Add(ShimName);
string ShimPath = Path.Combine(ShimRoot, ShimName);
if (!File.Exists(ShimPath))
{
throw new BuildException("VoxelForgeCore manifest row has no shim: {0} -> {1}", Source, ShimPath);
}
string Shim = File.ReadAllText(ShimPath);
string EscapedSource = Regex.Escape(Source);
if (Regex.Matches(Shim, "(?m)^\\s*#include\\s+\"" + EscapedSource + "\"\\s*$").Count != 1)
{
throw new BuildException("VoxelForgeCore shim must include its canonical manifest source exactly once: {0}", ShimPath);
}
bool IsApiBoundary = String.Equals(Source, "Core/src/VoxelForgeCore.cpp", StringComparison.Ordinal);
if (IsApiBoundary)
{
if (Regex.Matches(Shim, "(?m)^\\s*#include\\s+\"").Count != 1)
{
throw new BuildException("VoxelForgeCore API boundary shim must include only its canonical source: {0}", ShimPath);
}
}
else if (!Regex.IsMatch(Shim, "(?s)#include\\s+\"CoreNamespacePreamble\\.h\".*namespace\\s+vfcore::detail\\s*\\{.*#include\\s+\"" + EscapedSource + "\""))
{
throw new BuildException("VoxelForgeCore implementation shim must preload headers and wrap its source in vfcore::detail: {0}", ShimPath);
}
}
string[] ActualShims = Directory.GetFiles(ShimRoot, "*.cpp", SearchOption.TopDirectoryOnly)
.Select(Path.GetFileName)
.ToArray();
if (ActualShims.Length != ExpectedShimNames.Count
|| ActualShims.Any(Name => !ExpectedShimNames.Contains(Name)))
{
throw new BuildException(
"VoxelForgeCore shims and Core/core_sources.txt differ. Expected {0} shims under {1}; found {2}.",
ExpectedShimNames.Count, ShimRoot, ActualShims.Length);
}
}
}