fix: L37 Core compile error (stray paren) and Unreal-side issues from review R2
ShapeWorldInternal.h kept an extra ')' after a diagnostic edit was restored post-build, so the L37 commit did not compile; the fixed build reproduces L37's verified owner-world hashes exactly. Unreal (uncompiled here): SetHardTransitionFallbackForAssembly is const over a mutable runtime flag (the adapter calls it through a const manager); the legacy fallback clears the flag; VoxelStrateManager includes <cmath> for std::llround. Adds research R2 (read-only Unreal compile/behaviour review). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
3e443bf81c
commit
7f2d84d2c7
5 files changed
+75
-3
No files matched your search
@@ -13,6 +13,7 @@
|
|||||||
#include "VoxelTerrainOpDefinition.h" // For UVoxelTerrainOpDefinition::ApplyTo
|
#include "VoxelTerrainOpDefinition.h" // For UVoxelTerrainOpDefinition::ApplyTo
|
||||||
#include "VoxelBiomeDefinition.h" // For UVoxelBiomeDefinition (biome context flatten)
|
#include "VoxelBiomeDefinition.h" // For UVoxelBiomeDefinition (biome context flatten)
|
||||||
#include "HAL/IConsoleManager.h"
|
#include "HAL/IConsoleManager.h"
|
||||||
|
#include <cmath> // std::llround
|
||||||
#include "Misc/CommandLine.h"
|
#include "Misc/CommandLine.h"
|
||||||
#include "Misc/Crc.h"
|
#include "Misc/Crc.h"
|
||||||
#include "Misc/Parse.h"
|
#include "Misc/Parse.h"
|
||||||
|
|||||||
@@ -7771,6 +7771,12 @@ void AVoxelWorld::FallBackToLegacyAfterCoreInitializationFailure(const FString&
|
|||||||
VoxelForgeCoreWorldAssemblyJson.Reset();
|
VoxelForgeCoreWorldAssemblyJson.Reset();
|
||||||
VoxelForgeCoreWorldAssemblyHash.Reset();
|
VoxelForgeCoreWorldAssemblyHash.Reset();
|
||||||
bUseVoxelForgeCore = false;
|
bUseVoxelForgeCore = false;
|
||||||
|
// The Core adapter sets this before validation; legacy generation must not inherit it.
|
||||||
|
// L'adaptateur Core l'active avant validation ; le générateur historique ne doit pas en hériter.
|
||||||
|
if (StrateManager != nullptr)
|
||||||
|
{
|
||||||
|
StrateManager->SetHardTransitionFallbackForAssembly(false);
|
||||||
|
}
|
||||||
CoreFallbackCenterLocalCm = FVector::ZeroVector;
|
CoreFallbackCenterLocalCm = FVector::ZeroVector;
|
||||||
if (Mesher != nullptr)
|
if (Mesher != nullptr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -248,7 +248,9 @@ public:
|
|||||||
// This is independent of Core's 32^3 tile width.
|
// This is independent of Core's 32^3 tile width.
|
||||||
float GetStrateLayoutChunkWidthVoxels() const { return StrateLayoutChunkWidthVoxels; }
|
float GetStrateLayoutChunkWidthVoxels() const { return StrateLayoutChunkWidthVoxels; }
|
||||||
uint32 GetStrateLayoutChunkSizeMicrometres() const { return StrateLayoutChunkSizeMicrometres; }
|
uint32 GetStrateLayoutChunkSizeMicrometres() const { return StrateLayoutChunkSizeMicrometres; }
|
||||||
void SetHardTransitionFallbackForAssembly(bool bEnabled)
|
// Called by the Core adapter through a const manager pointer; the flag is runtime routing
|
||||||
|
// state, not layout data, hence const + mutable.
|
||||||
|
void SetHardTransitionFallbackForAssembly(bool bEnabled) const
|
||||||
{ bHardTransitionFallbackForAssembly = bEnabled; }
|
{ bHardTransitionFallbackForAssembly = bEnabled; }
|
||||||
|
|
||||||
/** Layout/passage generation counter (bumped by every Initialize → GeneratePassages).
|
/** Layout/passage generation counter (bumped by every Initialize → GeneratePassages).
|
||||||
@@ -535,7 +537,7 @@ protected:
|
|||||||
// Resolved once from VoxelSettings::StrateLayoutChunkSizeMeters during Initialize().
|
// Resolved once from VoxelSettings::StrateLayoutChunkSizeMeters during Initialize().
|
||||||
float StrateLayoutChunkWidthVoxels = 32.0f;
|
float StrateLayoutChunkWidthVoxels = 32.0f;
|
||||||
uint32 StrateLayoutChunkSizeMicrometres = 8000000;
|
uint32 StrateLayoutChunkSizeMicrometres = 8000000;
|
||||||
bool bHardTransitionFallbackForAssembly = false;
|
mutable bool bHardTransitionFallbackForAssembly = false;
|
||||||
|
|
||||||
// Production keeps the legacy writer available only as a fail-closed fallback for a
|
// Production keeps the legacy writer available only as a fail-closed fallback for a
|
||||||
// non-native/malformed passage; native D-floors bypass it. This switch never changes the
|
// non-native/malformed passage; native D-floors bypass it. This switch never changes the
|
||||||
|
|||||||
@@ -1551,7 +1551,7 @@ public:
|
|||||||
if(passage.controlPoints.size()<2)continue;
|
if(passage.controlPoints.size()<2)continue;
|
||||||
const bool tileHasSupport=passageTileScopeMatches;
|
const bool tileHasSupport=passageTileScopeMatches;
|
||||||
if(!tileHasSupport
|
if(!tileHasSupport
|
||||||
||ActivePassageTileQueries->hasMouthSupport(passageIndex)))
|
||ActivePassageTileQueries->hasMouthSupport(passageIndex))
|
||||||
composeRouteMouthSupport(passage.upperStrateIndex,
|
composeRouteMouthSupport(passage.upperStrateIndex,
|
||||||
passage.upperMouthSubvoxels,true);
|
passage.upperMouthSubvoxels,true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# Research R2 — Unreal compile and behavior review
|
||||||
|
|
||||||
|
Read-only static review; no builds or tests run.
|
||||||
|
|
||||||
|
## Build baseline and Source history
|
||||||
|
|
||||||
|
The last recorded Windows BuildHost UBT pass is Round 18/S14, source commit `ec2afe9` (BuildHost UBT passed on its first attempt; the report lists `Source/VoxelForge/Private/VoxelWorld.cpp`). The older commit explicitly labelled “owner build” is `48fa028`; the newer BuildHost pass is the better compile baseline. No later UBT pass is recorded for these Source edits.
|
||||||
|
|
||||||
|
Since `ec2afe9`, the Unreal-side edits are:
|
||||||
|
|
||||||
|
- L11 `b1cfaf5`: `Private/VoxelWorld.cpp`
|
||||||
|
- L18 `dcf0763`: `Private/VoxelForgeCoreAdapter.cpp`, `Public/VoxelDensityPrimitives.h`
|
||||||
|
- L21 `8753f6d`: adapter
|
||||||
|
- L22 `55c26a0`: adapter, `Private/VoxelStrateManager.cpp`, `Public/VoxelSettings.h`, `Public/VoxelStrateManager.h`
|
||||||
|
- L23 `71d09a8`: adapter
|
||||||
|
- L24 `cb9236c`: adapter, `Public/VoxelStrateTypes.h`
|
||||||
|
- L25 `ef789aa`: adapter
|
||||||
|
- L27 `07b3fe2`: adapter
|
||||||
|
- L29 `63c7e56`: adapter, `Public/VoxelStrateTypes.h`
|
||||||
|
- L37 `3e443bf`: adapter
|
||||||
|
|
||||||
|
That is seven changed Source files: `VoxelForgeCoreAdapter.cpp`, `VoxelWorld.cpp`, `VoxelStrateManager.cpp`, `VoxelDensityPrimitives.h`, `VoxelSettings.h`, `VoxelStrateManager.h`, and `VoxelStrateTypes.h`.
|
||||||
|
|
||||||
|
## Findings
|
||||||
|
|
||||||
|
| File:line | Issue | Confidence | Suggested fix |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:822` | Calls non-const `SetHardTransitionFallbackForAssembly` through `const UVoxelStrateManager*`; this is a C++ compile error and remains in the current worktree. | certain | Pass a mutable manager through the serializer/attach path, or perform the state change at a non-const caller. |
|
||||||
|
| `Standalone/Core/src/ShapeWorldInternal.h` (tracked HEAD line 1554) | Tracked HEAD has an extra `)` in its mouth-support `if`; the current L38 worktree replaces that passage-mouth block in a larger Core rewrite. | certain (HEAD only) | Preserve and review the current L38 diff before the owner builds. |
|
||||||
|
| `Source/VoxelForge/Private/VoxelStrateManager.cpp:1179` | New `std::llround` call has no direct `<cmath>` include; it may currently arrive transitively. | check | Add `<cmath>` to this translation unit. |
|
||||||
|
| `Source/VoxelForge/Private/VoxelWorld.cpp:13048` | New `unordered_set::contains` requires C++20; `VoxelForge.Build.cs` does not pin the standard. | check | Pin `CppStandard=Cpp20` here or use `find(...) != end()` if older language modes must work. |
|
||||||
|
| `Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:137, 489, 543` | Route capsule dimensions are fixed in Core subvoxels; the Floating Islands recipe leaves `routeConstraints.version` zero, so Core fills 25 cm-sized defaults. At smaller Core voxel sizes, the proofs shrink in centimetres. | likely (when Core voxel size < 25 cm) | Set both route constraint sets from fixed gameplay dimensions in cm divided by `CoreVoxelSizeCm`. |
|
||||||
|
| `Source/VoxelForge/Private/VoxelWorld.cpp:7761` | Failed Core startup switches to legacy generation but does not clear the hard-transition flag set by the adapter at line 822; legacy parameter lookups then keep the Core-only hard fallback. | likely | Clear the flag in `FallBackToLegacyAfterCoreInitializationFailure`. |
|
||||||
|
|
||||||
|
No likely UHT blocker found in the changed headers: the new reflected setting is a `float` with numeric clamp metadata; the Blueprint enums remain `: uint8`; changed reflected declarations add no `uint64`/`int64` properties. UE documents `uint32`/`int64` as property integer types and metres as a supported unit. [UE Properties](https://dev.epicgames.com/documentation/unreal-engine/unreal-engine-uproperties?lang=en-US) · [UE Units](https://dev.epicgames.com/documentation/unreal-engine/units-of-measurement-in-unreal-engine?lang=en-US). `VoxelDensityPrimitives.h` adds inline shared helpers; the other header changes are layout state, comments, or the intentional Worm default. No designated initializers, `__restrict`, or suspicious new narrowing were found.
|
||||||
|
|
||||||
|
Core’s module pins C++20 and precise FP semantics. `CoreNamespacePreamble.h` selects a compiler-specific contraction control; the MSVC branch uses `#pragma fp_contract(off)`, and `World::compile` rejects a build if its FMA self-test fails. MS documents that pragma from VS2022 17.0 and that older compilers could contract under `/fp:precise`; confirm the owner’s toolset and check the startup self-test. [UE C++ standard](https://dev.epicgames.com/documentation/unreal-engine/epic-cplusplus-coding-standard-for-unreal-engine) · [MSVC `/fp`](https://learn.microsoft.com/en-us/cpp/build/reference/fp-specify-floating-point-behavior?view=msvc-170) · [MSVC `fp_contract`](https://learn.microsoft.com/en-us/cpp/preprocessor/fp-contract). Core unordered containers appear to serve lookup, membership, statistics, or lookup-table construction; I found no output-affecting hash iteration.
|
||||||
|
|
||||||
|
At final review, L38 had an uncommitted worktree diff across six files (136 insertions / 1,002 deletions), including removal of `terrainFollowingRoute` from the Core recipe and both plan producers; no live code references remain. This is a substantial in-progress evaluator change with no UBT confirmation. No other stale Core/adapter recipe-field mismatch was found in the current worktree.
|
||||||
|
|
||||||
|
## Behavior risks
|
||||||
|
|
||||||
|
- SurfaceWorld and FloatingIslands intentionally use different historical voxel conventions: SurfaceWorld layout chunks are 32 Core voxels (8 m at 25 cm); FloatingIslands converts 32 owner voxels (12.5 cm) through the owner/Core ratio (4 m at 25 cm). The L20/L22 research records this split. Do not blanket-apply the FI scale to SurfaceWorld; compare physical anchors and route clearances if using a non-25 cm Core size.
|
||||||
|
- Route proofs assume a 34 cm radius, 176 cm tall player capsule at 25 cm Core voxels. At 12.5 cm, the fixed Q values represent half those physical dimensions; the FI Core fallback also silently supplies fixed defaults because the adapter never sets `routeConstraints`.
|
||||||
|
- On adapter validation/export failure, the hard-transition flag set at adapter line 822 can leak into the legacy fallback path. This can make the fallback world differ from the normal legacy generator.
|
||||||
|
- FP behavior is fail-closed rather than silently divergent on unsupported MSVC: if contraction is detected, Core initialization refuses to generate. Linux1’s Clang/GCC checks do not validate the owner’s MSVC binary.
|
||||||
|
|
||||||
|
## What the owner should check first when he builds
|
||||||
|
|
||||||
|
1. Build the current worktree (including the current L38 Core rewrite); expect the adapter constness error first unless the implementation fixes it.
|
||||||
|
2. Check UHT, then confirm the owner project’s language mode accepts `unordered_set::contains`; add the direct `<cmath>` include if MSVC reports `llround` unresolved.
|
||||||
|
3. Confirm Core startup passes the FP self-test. Then validate one SurfaceWorld and one FloatingIslands route at the configured Core voxel size, especially if it is below 25 cm; inspect startup plan errors and the route capsule/support clearance.
|
||||||
|
|
||||||
|
## Orchestrator follow-up (Claude)
|
||||||
|
|
||||||
|
Both "certain" findings were confirmed and fixed in the same commit:
|
||||||
|
- **`ShapeWorldInternal.h:1554` stray `)`** — L37's committed Core did not compile. It was left when a temporary
|
||||||
|
support-off diagnostic was restored after the final build. Fixed; a clang build of the fixed HEAD reproduces L37's
|
||||||
|
verified owner-world hashes exactly (SurfaceWorld and FloatingIslands, L25 W12).
|
||||||
|
- **Adapter constness (`VoxelForgeCoreAdapter.cpp:823`)** — the setter is now `const` over a `mutable` runtime flag.
|
||||||
|
- Also applied: the legacy fallback clears that flag, and `<cmath>` is included in `VoxelStrateManager.cpp`.
|
||||||
|
- Left for the owner's build: `unordered_set::contains` (UE5 modules default to C++20), and the FI route-constraint
|
||||||
|
scaling at Core voxel sizes other than 25 cm (only matters if he changes it).
|
||||||
Reference in new issue
Block a user