q
This commit is contained in:
parent
810ad6f5cb
commit
de7c6c32bd
123 changed files with 13201 additions and 6213 deletions
|
|
@ -1,7 +1,28 @@
|
|||
import { generateMap } from "./mapPipeline.js";
|
||||
import { generateMap, generateMapDraft, generateMapTerrainDraft } from "./mapPipeline.js";
|
||||
import { collectTransferableBuffers } from "./transferUtils.js";
|
||||
import { compactRawPatchCandidate, summarizeRawPatchCandidate } from "./rawPatchCandidate.js";
|
||||
|
||||
|
||||
function prepareDraftForTransfer(candidate) {
|
||||
if (!candidate || typeof candidate !== "object") return candidate;
|
||||
// generateMapFeatures exposes cityPopulationCap as a closure over production
|
||||
// terrain fields. Functions are not structured-cloneable, so materialize the
|
||||
// exact per-city caps before transferring a resident draft to the coordinator.
|
||||
// finishMapOutput consumes and removes this temporary numeric field when the
|
||||
// winning draft is finalized; no approximation is introduced.
|
||||
const features = candidate.features;
|
||||
const capFn = features?.cityPopulationCap;
|
||||
if (typeof capFn === "function") {
|
||||
for (const city of features?.modernCities || []) {
|
||||
const cap = Number(capFn(city));
|
||||
if (Number.isFinite(cap)) city.__productionPopulationCap = cap;
|
||||
}
|
||||
delete features.cityPopulationCap;
|
||||
}
|
||||
if (typeof candidate.cityPopulationCap === "function") delete candidate.cityPopulationCap;
|
||||
return candidate;
|
||||
}
|
||||
|
||||
function scopeTaskProgress(event = {}, taskId) {
|
||||
const scoped = { ...event };
|
||||
if (event?.workUnitId != null && String(event.workUnitId).length > 0) {
|
||||
|
|
@ -13,19 +34,22 @@ function scopeTaskProgress(event = {}, taskId) {
|
|||
if (typeof self !== "undefined") {
|
||||
self.onmessage = (event) => {
|
||||
const message = event.data || {};
|
||||
if (message.type !== "generate-raw-patch-candidate") return;
|
||||
const taskId = String(message.taskId || `raw-${message.id || 0}`);
|
||||
const terrainScoutOnly = message.type === "generate-raw-patch-terrain-scout";
|
||||
const draftOnly = message.type === "generate-raw-patch-draft";
|
||||
if (!terrainScoutOnly && !draftOnly && message.type !== "generate-raw-patch-candidate") return;
|
||||
const taskId = String(message.taskId || `${terrainScoutOnly ? "terrain-scout" : draftOnly ? "draft" : "raw"}-${message.id || 0}`);
|
||||
const startedAt = typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
|
||||
try {
|
||||
let candidate = generateMap(Number(message.seed) >>> 0, {
|
||||
const generator = terrainScoutOnly ? generateMapTerrainDraft : draftOnly ? generateMapDraft : generateMap;
|
||||
let candidate = generator(Number(message.seed) >>> 0, {
|
||||
...(message.mapOptions || {}),
|
||||
// A boolean sentinel is sufficient: mapPipeline only records whether a
|
||||
// boundary world exists. Actual seam/quality work remains in the parent
|
||||
// patch worker after this raw candidate has been transferred back.
|
||||
// patch worker after this raw candidate/draft has been transferred back.
|
||||
boundaryWorld: true,
|
||||
onProgress: (progress) => {
|
||||
self.postMessage({
|
||||
type: "raw-patch-candidate-progress",
|
||||
type: terrainScoutOnly ? "raw-patch-terrain-scout-progress" : draftOnly ? "raw-patch-draft-progress" : "raw-patch-candidate-progress",
|
||||
id: message.id,
|
||||
taskId,
|
||||
progress: scopeTaskProgress(progress, taskId),
|
||||
|
|
@ -33,12 +57,47 @@ if (typeof self !== "undefined") {
|
|||
},
|
||||
});
|
||||
const elapsedMs = (typeof performance !== "undefined" && performance.now ? performance.now() : Date.now()) - startedAt;
|
||||
let transferSummary;
|
||||
if (terrainScoutOnly) {
|
||||
const transferables = [...collectTransferableBuffers(candidate)];
|
||||
transferSummary = {
|
||||
transferableBytes: transferables.reduce((sum, buffer) => sum + Number(buffer?.byteLength || 0), 0),
|
||||
transferableCount: transferables.length,
|
||||
};
|
||||
self.postMessage({
|
||||
type: "raw-patch-terrain-scout-result",
|
||||
id: message.id, taskId, ok: true, elapsedMs, transferSummary, candidate,
|
||||
}, transferables);
|
||||
return;
|
||||
}
|
||||
if (draftOnly) {
|
||||
candidate = prepareDraftForTransfer(candidate);
|
||||
// Drafts stay complete because the finalist reuses terrain, geographic
|
||||
// basis and features verbatim. Transferable buffers move ownership to
|
||||
// the coordinator without copying while the helper Worker remains alive
|
||||
// for the next lane task.
|
||||
const transferables = [...collectTransferableBuffers(candidate)];
|
||||
transferSummary = {
|
||||
transferableBytes: transferables.reduce((sum, buffer) => sum + Number(buffer?.byteLength || 0), 0),
|
||||
transferableCount: transferables.length,
|
||||
};
|
||||
self.postMessage({
|
||||
type: "raw-patch-draft-result",
|
||||
id: message.id,
|
||||
taskId,
|
||||
ok: true,
|
||||
elapsedMs,
|
||||
transferSummary,
|
||||
candidate,
|
||||
}, transferables);
|
||||
return;
|
||||
}
|
||||
// Transfer only the roots consumed by mapPatch. Full-map geography/debug
|
||||
// graphs can exceed the actual patch payload and are never consulted by
|
||||
// candidate merge/quality logic. Dropping them before structured clone
|
||||
// creates a hard cross-worker memory bound for large tiled operations.
|
||||
candidate = compactRawPatchCandidate(candidate);
|
||||
const transferSummary = summarizeRawPatchCandidate(candidate);
|
||||
transferSummary = summarizeRawPatchCandidate(candidate);
|
||||
const transferables = [...collectTransferableBuffers(candidate)];
|
||||
self.postMessage({
|
||||
type: "raw-patch-candidate-result",
|
||||
|
|
@ -51,11 +110,11 @@ if (typeof self !== "undefined") {
|
|||
}, transferables);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
type: "raw-patch-candidate-result",
|
||||
type: terrainScoutOnly ? "raw-patch-terrain-scout-result" : draftOnly ? "raw-patch-draft-result" : "raw-patch-candidate-result",
|
||||
id: message.id,
|
||||
taskId,
|
||||
ok: false,
|
||||
code: error?.code || "raw-patch-candidate-error",
|
||||
code: error?.code || (terrainScoutOnly ? "raw-patch-terrain-scout-error" : draftOnly ? "raw-patch-draft-error" : "raw-patch-candidate-error"),
|
||||
error: error?.message || String(error),
|
||||
stack: error?.stack || "",
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue