mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2026-04-04 06:27:24 +02:00
Merge b80dc94e1b into 23871b3311
This commit is contained in:
commit
bfd1a20183
3 changed files with 54 additions and 5 deletions
|
|
@ -260,7 +260,14 @@ function getName(id) {
|
|||
}
|
||||
|
||||
function getGraph(currentGraph) {
|
||||
const newGraph = shouldRegenerateGrid(currentGraph, seed) ? generateGrid() : structuredClone(currentGraph);
|
||||
if (shouldRegenerateGrid(currentGraph, seed)) return generateGrid();
|
||||
|
||||
// Deep clone avoiding non-cloneable properties (like D3 quadtrees with functions)
|
||||
const newGraph = JSON.parse(JSON.stringify(currentGraph));
|
||||
// Recreate voronoi cells since JSON doesn't preserve typed arrays or circular refs
|
||||
const {cells, vertices} = calculateVoronoi(newGraph.points, newGraph.boundary);
|
||||
newGraph.cells = cells;
|
||||
newGraph.vertices = vertices;
|
||||
delete newGraph.cells.h;
|
||||
return newGraph;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,48 @@ import {
|
|||
import type { River } from "./river-generator";
|
||||
import type { Point } from "./voronoi";
|
||||
|
||||
/**
|
||||
* Deeply clones an object, omitting properties that cannot be cloned with structuredClone.
|
||||
* D3 quadtrees store accessor functions that fail structuredClone, so they're excluded.
|
||||
*/
|
||||
const safeDeepClone = <T>(obj: T): T => {
|
||||
if (obj === null || typeof obj !== "object") {
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Handle typed arrays - slice() creates a copy with a new underlying buffer
|
||||
if (ArrayBuffer.isView(obj) && !(obj instanceof DataView)) {
|
||||
return (obj as any).slice() as T;
|
||||
}
|
||||
|
||||
// Handle arrays
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((item) => safeDeepClone(item)) as T;
|
||||
}
|
||||
|
||||
// Handle objects - skip quadtree (has functions) and other non-clonable properties
|
||||
const cloned: Record<string, unknown> = {};
|
||||
for (const key in obj) {
|
||||
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
|
||||
|
||||
const value = (obj as Record<string, unknown>)[key];
|
||||
|
||||
// Skip quadtree properties (D3 quadtrees have _x and _y functions)
|
||||
if (value && typeof value === "object" && "_x" in (value as object)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip functions
|
||||
if (typeof value === "function") {
|
||||
continue;
|
||||
}
|
||||
|
||||
cloned[key] = safeDeepClone(value);
|
||||
}
|
||||
|
||||
return cloned as T;
|
||||
};
|
||||
|
||||
declare global {
|
||||
var Resample: Resampler;
|
||||
}
|
||||
|
|
@ -495,9 +537,9 @@ class Resampler {
|
|||
process(options: ResamplerProcessOptions): void {
|
||||
const { projection, inverse, scale } = options;
|
||||
const parentMap = {
|
||||
grid: structuredClone(grid),
|
||||
pack: structuredClone(pack),
|
||||
notes: structuredClone(notes),
|
||||
grid: safeDeepClone(grid),
|
||||
pack: safeDeepClone(pack),
|
||||
notes: safeDeepClone(notes),
|
||||
};
|
||||
const riversData = this.saveRiversData(pack.rivers);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export interface PackedGraph {
|
|||
p: [number, number][]; // cell polygon points
|
||||
b: boolean[]; // cell is on border
|
||||
h: TypedArray; // cell heights
|
||||
q: Quadtree<[number, number, number]>; // cell quadtree index
|
||||
q?: Quadtree<[number, number, number]>; // cell quadtree index (optional, not cloned)
|
||||
/** Terrain type */
|
||||
t: TypedArray; // cell terrain types
|
||||
r: TypedArray; // river id passing through cell
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue