wip(assembler): M3 round 3 -- separated islands + Unreal island route (owner build 18:46)

Islands read as separate (91.89% open sky at mid-height), underside cavity closed,
rim teeth were capture shading. Island manifest import + BuildHost proof passed on the
pre-cache tree; M1 SurfaceWorld and M2 V1/V2 gates passed.

Known open: final XY-column cache compiled in the owner build but is unverified;
island LOD0 p95 ~155 ms misses the 133 ms sprint deadline (legacy ~43 ms); the island
manifest only fits the BuildHost fixture layout (owner's world: Core init fails,
empty world) -> round 4 builds plans inside Unreal.

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-10 20:53:03 +02:00
1 parent 4afea7c802
commit 48fa028086
37 files changed
+3788 -107

No files matched your search

+150 -4
View File
@@ -8,6 +8,7 @@
#include <charconv>
#include <chrono>
#include <cmath>
#include <iomanip>
#include <limits>
#include <sstream>
@@ -403,9 +404,91 @@ namespace world_assembly_detail
HashWord(hash, manifest.schemaVersion, 4);
HashWord(hash, manifest.recipe.contentHash, 8);
HashWord(hash, manifest.plan.contentHash, 8);
// Preserve the historical SurfaceWorld manifest digest when no island plan is attached.
if (!manifest.floatingIslands.empty())
{
HashWord(hash, 0x464c4f415449534cull, 8);
HashWord(hash, manifest.floatingIslands.size(), 4);
for (const auto& islands : manifest.floatingIslands)
{
HashWord(hash, static_cast<std::uint32_t>(islands.strateIndex), 4);
HashWord(hash, static_cast<std::uint32_t>(islands.topChunkZ), 4);
HashWord(hash, static_cast<std::uint32_t>(islands.bottomChunkZ), 4);
HashWord(hash, islands.manifest.contentHash, 8);
}
}
return hash;
}
inline void AppendJsonString(std::ostringstream& out, std::string_view value)
{
out << '"';
for (const unsigned char ch : value)
{
switch (ch)
{
case '"': out << "\\\""; break;
case '\\': out << "\\\\"; break;
case '\b': out << "\\b"; break;
case '\f': out << "\\f"; break;
case '\n': out << "\\n"; break;
case '\r': out << "\\r"; break;
case '\t': out << "\\t"; break;
default:
if (ch < 0x20) out << "\\u00" << std::hex << std::setw(2)
<< std::setfill('0') << static_cast<unsigned int>(ch) << std::dec;
else out << static_cast<char>(ch);
break;
}
}
out << '"';
}
inline void AppendJsonValue(std::ostringstream& out, const VFJson::Value& value)
{
if (std::holds_alternative<std::nullptr_t>(value.Data)) out << "null";
else if (const auto* boolean = std::get_if<bool>(&value.Data)) out << (*boolean ? "true" : "false");
else if (const auto* number = std::get_if<double>(&value.Data))
{
char buffer[64];
const auto result = std::to_chars(buffer, buffer + sizeof(buffer), *number,
std::chars_format::general, std::numeric_limits<double>::max_digits10);
if (result.ec == std::errc{}) out.write(buffer, result.ptr - buffer);
else out << '0';
}
else if (const auto* string = std::get_if<std::string>(&value.Data)) AppendJsonString(out, *string);
else if (const auto* array = std::get_if<VFJson::Value::Array>(&value.Data))
{
out << '[';
for (std::size_t i = 0; i < array->size(); ++i)
{ if (i) out << ','; AppendJsonValue(out, (*array)[i]); }
out << ']';
}
else
{
const auto& object = std::get<VFJson::Value::Object>(value.Data);
std::vector<std::string_view> keys;
keys.reserve(object.size());
for (const auto& entry : object) keys.push_back(entry.first);
std::sort(keys.begin(), keys.end());
out << '{';
for (std::size_t i = 0; i < keys.size(); ++i)
{
if (i) out << ',';
AppendJsonString(out, keys[i]); out << ':';
AppendJsonValue(out, object.at(std::string(keys[i])));
}
out << '}';
}
}
inline std::string JsonText(const VFJson::Value& value)
{
std::ostringstream out;
AppendJsonValue(out, value);
return out.str();
}
inline bool ParseRecipe(const VFJson::Value& value, WorldAssemblyRecipeV1& recipe,
std::string& error)
{
@@ -566,6 +649,26 @@ namespace world_assembly_detail
if (error.empty()) error = "world assembly manifest is missing a required field";
return std::nullopt;
}
const VFJson::Value& islandPlans = value.Get("floating_islands");
if (!std::holds_alternative<std::nullptr_t>(islandPlans.Data))
{
if (!islandPlans.IsArray() || islandPlans.AsArray().size() > MaxStrateCount)
{ error = "world assembly floating-island plans must be an array of at most sixty-four entries"; return std::nullopt; }
for (const VFJson::Value& islandValue : islandPlans.AsArray())
{
WorldAssemblyFloatingIslandPlanV1 entry;
if (!islandValue.IsObject()
|| !ReadI32(islandValue.Get("strate_index"), entry.strateIndex)
|| !ReadI32(islandValue.Get("top_chunk_z"), entry.topChunkZ)
|| !ReadI32(islandValue.Get("bottom_chunk_z"), entry.bottomChunkZ))
{ error = "world assembly floating-island slot is missing its resolved strate bounds"; return std::nullopt; }
const std::string nestedJson = JsonText(islandValue.Get("manifest"));
auto parsedIsland = FloatingIslandManifestV1::FromJson(nestedJson, error);
if (!parsedIsland) return std::nullopt;
entry.manifest = std::move(*parsedIsland);
manifest.floatingIslands.push_back(std::move(entry));
}
}
if (!manifest.validate(error)) return std::nullopt;
return manifest;
}
@@ -1292,8 +1395,10 @@ bool WorldAssemblyManifest::finalize(std::string& error)
if (schemaVersion != WorldAssemblySchemaVersion || plan.schemaVersion != WorldAssemblySchemaVersion
|| !world_assembly_detail::ValidateRecipe(recipe, error))
{ if (error.empty()) error = "world assembly manifest or plan version is unsupported"; return false; }
if (plan.strates.empty() || plan.strates.size() > world_assembly_detail::MaxStrateCount)
{ error = "world assembly plan must contain one to sixty-four finite strates"; return false; }
if ((plan.strates.empty() && floatingIslands.empty())
|| plan.strates.size() > world_assembly_detail::MaxStrateCount
|| floatingIslands.size() > world_assembly_detail::MaxStrateCount)
{ error = "world assembly must contain SurfaceWorld or floating-island plans within the sixty-four-strate limit"; return false; }
std::vector<std::int32_t> strateIds;
for (auto& stratum : plan.strates)
{
@@ -1323,6 +1428,25 @@ bool WorldAssemblyManifest::finalize(std::string& error)
strateIds.push_back(stratum.strateIndex);
stratum.contentHash = world_assembly_detail::HashStratum(stratum);
}
std::vector<std::int32_t> islandStrateIds;
for (auto& islands : floatingIslands)
{
if (islands.strateIndex < 0 || islands.topChunkZ < islands.bottomChunkZ
|| std::find(islandStrateIds.begin(), islandStrateIds.end(), islands.strateIndex) != islandStrateIds.end())
{ error = "world assembly contains invalid or duplicate floating-island strate bounds"; return false; }
if (!islands.manifest.validate(error)) return false;
if (islands.manifest.recipe.seed != recipe.seed)
{ error = "floating-island seed does not match the world assembly season seed"; return false; }
constexpr std::int64_t CoreVoxelsPerLegacyChunk = 16;
const std::int64_t bottomQ = static_cast<std::int64_t>(islands.bottomChunkZ)
* CoreVoxelsPerLegacyChunk * WorldAssemblySubvoxelsPerVoxel;
const std::int64_t topQ = (static_cast<std::int64_t>(islands.topChunkZ) + 1)
* CoreVoxelsPerLegacyChunk * WorldAssemblySubvoxelsPerVoxel;
if (islands.manifest.recipe.layoutMinimumZSubvoxels < bottomQ
|| islands.manifest.recipe.layoutMaximumZSubvoxels > topQ)
{ error = "floating-island recipe layout escapes the resolved 12.5 cm legacy strate bounds"; return false; }
islandStrateIds.push_back(islands.strateIndex);
}
recipe.contentHash = world_assembly_detail::HashRecipe(recipe);
plan.contentHash = world_assembly_detail::HashPlan(plan);
contentHash = world_assembly_detail::HashManifest(*this);
@@ -1337,13 +1461,19 @@ bool WorldAssemblyManifest::validate(std::string& error) const
const std::uint64_t expectedManifest = contentHash;
std::vector<std::uint64_t> expectedStrates;
for (const auto& stratum : plan.strates) expectedStrates.push_back(stratum.contentHash);
std::vector<std::uint64_t> expectedIslandManifests;
for (const auto& islands : floatingIslands) expectedIslandManifests.push_back(islands.manifest.contentHash);
if (!copy.finalize(error)) return false;
if (expectedRecipe != copy.recipe.contentHash || expectedPlan != copy.plan.contentHash
|| expectedManifest != copy.contentHash || expectedStrates.size() != copy.plan.strates.size())
|| expectedManifest != copy.contentHash || expectedStrates.size() != copy.plan.strates.size()
|| expectedIslandManifests.size() != copy.floatingIslands.size())
{ error = "world assembly recipe, plan or manifest content hash does not match its fields"; return false; }
for (std::size_t i = 0; i < expectedStrates.size(); ++i)
if (expectedStrates[i] != copy.plan.strates[i].contentHash)
{ error = "world assembly stratum content hash does not match its fields"; return false; }
for (std::size_t i = 0; i < expectedIslandManifests.size(); ++i)
if (expectedIslandManifests[i] != copy.floatingIslands[i].manifest.contentHash)
{ error = "world assembly floating-island content hash does not match its fields"; return false; }
return true;
}
@@ -1474,7 +1604,23 @@ std::string WorldAssemblyManifest::ToJson() const
}
out << "]}";
}
out << "]}}";
if (value.floatingIslands.empty()) out << "]}}";
else
{
out << "]},\"floating_islands\":[";
for (std::size_t i = 0; i < value.floatingIslands.size(); ++i)
{
const auto& islands = value.floatingIslands[i];
if (i) out << ',';
const std::string nested = islands.manifest.ToJson();
if (nested.empty()) return {};
out << "{\"strate_index\":" << islands.strateIndex
<< ",\"top_chunk_z\":" << islands.topChunkZ
<< ",\"bottom_chunk_z\":" << islands.bottomChunkZ
<< ",\"manifest\":" << nested << '}';
}
out << "]}";
}
return out.str();
}