feat(runtime): the composed world can BE the game world
Jahni: "can you not implement those settings? as in, have them be live in
game?" This is that. The composer stops being a lab tool.
THE ARCHITECTURAL LINE, which is the whole design (COMPOSER-NOTES §3.1):
COMPOSITION stays editor-only, EVALUATION becomes runtime. Rolling,
measuring, preview, selection, promotion, the corpus -- none of it reaches
a player's machine. What crosses into the runtime is exactly two things:
reading a season manifest, and materialising a recipe into an op stack.
UVoxelSeasonAsset a cookable UPrimaryDataAsset holding the manifest,
so a season ships in a packaged game. The JSON
stays the reviewable, git-diffable artefact.
UVoxelSettings::Season optional. Unset => behaviour is exactly as today.
GetEffective*() season seed / spine radius / world radius / season
number override the authored values when assigned.
The test deliberately sets DIFFERENT authored
values, so "the season is authoritative" is proved
rather than coincidental.
⭐ MULTIPLAYER DETERMINISM, PROVED: two independent runtime managers built
the same season and compared 393,216 density samples BIT-IDENTICALLY. This
is the property the whole multiplayer model rests on -- replicate seed +
layout + diff, never geometry.
⭐ AND A STALE SEASON IS DETECTABLE, NOT SILENT. Initialize() now returns
bool and an assigned-but-invalid season NEVER falls back to the authored
pool. Falling back would hand a client a world that looks fine and is not
the season -- silent divergence, the worst failure mode in a shared world.
GetCurrentSeasonContentHash() is exposed BlueprintPure to compare at join.
HasComposerRecipeOverride() is gone. It force-classified every custom recipe
as Mixed, which was correct while box verdicts were only proved for
hand-written stacks -- but 8e346a3 made EffectOverBox correct in ISOLATION,
proved on a stack no builder produces. Keeping the force would have cost
tile skipping on every composed world forever.
VF_RollStrateRegionCount moved behind WITH_EDITOR while the partition-seed
helpers stayed runtime: rolling out, evaluation in. Lateral regions remain
gated off.
⚠️ Sol hit its usage limit mid-task, so the edits arrived unvalidated. I
built and ran them myself rather than assume -- and they did not compile:
VoxelForgeComposerSeasonTest.cpp was missing UObject/Package.h, which every
other test picks up transitively through the shared fixture it does not use.
One include; every NewObject/GetTransientPackage in the file was failing.
Editor build clean. SHIPPING BUILD SUCCEEDS -- the invariant that proves no
composer roller is linked into a packaged game. 30 succeeded / 0 failed.
⚠️ UNVERIFIED: whether it looks right on screen. Nothing headless can tell
us that; it needs Jahni to assign a season asset and press play.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU
This commit is contained in:
1 parent
088b40216d
commit
faa62d419e
21 files changed
+1268
-287
No files matched your search
@@ -28,6 +28,7 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#if WITH_EDITOR
|
||||
namespace
|
||||
{
|
||||
constexpr float GJitterFraction = 0.15f;
|
||||
@@ -2262,27 +2263,6 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
bool FVoxelStrateMeasuredMetrics::IsUsable() const
|
||||
{
|
||||
return bValid
|
||||
&& NumSampled > 0
|
||||
&& NumAir > 0
|
||||
&& NumSolid > 0
|
||||
&& NumSampled == NumAir + NumSolid
|
||||
&& NumAirComponents > 0
|
||||
&& LargestComponentCells > 0
|
||||
&& AirComponentCells.Num() == NumAirComponents
|
||||
&& FMath::IsFinite(AirFraction)
|
||||
&& FMath::IsFinite(LargestComponentShare)
|
||||
&& FMath::IsFinite(WalkableFraction)
|
||||
&& FMath::IsFinite(WalkableFloorAreaFraction)
|
||||
&& FMath::IsFinite(LargestWalkableSurfaceShare)
|
||||
&& FMath::IsFinite(MedianFeatureScale)
|
||||
&& FMath::IsFinite(LargestComponentPoint.X)
|
||||
&& FMath::IsFinite(LargestComponentPoint.Y)
|
||||
&& FMath::IsFinite(LargestComponentPoint.Z);
|
||||
}
|
||||
|
||||
FVoxelStrateMeasuredMetrics VF_SummarizeStrateMetrics(
|
||||
const FVoxelStrateMetrics& Metrics)
|
||||
{
|
||||
@@ -3901,22 +3881,6 @@ uint32 FVoxelStrateCorpus::GetContentsHash() const
|
||||
return Hash;
|
||||
}
|
||||
|
||||
const TCHAR* VF_GetStrateArchetypeName(ECaveGeneratorType Archetype)
|
||||
{
|
||||
switch (Archetype)
|
||||
{
|
||||
case ECaveGeneratorType::TunnelNetwork: return TEXT("TunnelNetwork");
|
||||
case ECaveGeneratorType::FlatPlain: return TEXT("FlatPlain");
|
||||
case ECaveGeneratorType::CrystalChamber: return TEXT("CrystalChamber");
|
||||
case ECaveGeneratorType::Maze: return TEXT("Maze");
|
||||
case ECaveGeneratorType::SurfaceWorld: return TEXT("SurfaceWorld");
|
||||
case ECaveGeneratorType::VerticalShafts: return TEXT("VerticalShafts");
|
||||
case ECaveGeneratorType::FloatingIslands: return TEXT("FloatingIslands");
|
||||
case ECaveGeneratorType::Underwater: return TEXT("Underwater");
|
||||
}
|
||||
return TEXT("Unknown");
|
||||
}
|
||||
|
||||
const TCHAR* VF_GetStrateCorpusProvenanceName(EVoxelStrateCorpusProvenance Provenance)
|
||||
{
|
||||
switch (Provenance)
|
||||
@@ -4400,6 +4364,7 @@ bool FVoxelStrateCorpus::SetMeasuredMetrics(
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // WITH_EDITOR — corpus loading, promotion and parameter/structure roll implementation
|
||||
|
||||
void VF_SetStrateArchetypeRuntimeBounds(
|
||||
FVoxelStrateArchetypeParams& Params, float TopWorldZ, float BottomWorldZ)
|
||||
@@ -4589,11 +4554,13 @@ namespace VoxelStrateRegionPrivate
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
int32 VF_RollStrateRegionCount(int32 Seed, int32 StrateIndex)
|
||||
{
|
||||
return 1 + static_cast<int32>(VoxelHash::Cell(
|
||||
StrateIndex, StrateIndex ^ 0x6D, static_cast<uint32>(Seed) ^ 0x524F4C4Cu) % 3u);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32 VF_GetStrateRegionPartitionSeed(int32 Seed, int32 StrateIndex)
|
||||
{
|
||||
@@ -4753,6 +4720,7 @@ FVoxelStrateRegionBoxProof VF_AnalyzeStrateRegionBox(
|
||||
return Proof;
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
FVoxelStrateRollInfo VF_RollStrateParamsDetailed(const FVoxelStrateCorpus& Corpus,
|
||||
int32 Seed, int32 Index)
|
||||
{
|
||||
@@ -5694,3 +5662,4 @@ bool VF_AreStrateStructureRecipesIdentical(const FVoxelOpStackRecipe& A,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // WITH_EDITOR — no roller/corpus entry point is compiled into Shipping
|
||||
Reference in new issue
Block a user