218 lines
7.2 KiB
Python
218 lines
7.2 KiB
Python
|
|
import os
|
|
|
|
path = "src/generation/CrystalSpiresGenerator.js"
|
|
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
lines = f.readlines()
|
|
|
|
# Line numbers (1-based) to 0-based indices
|
|
# remove 780-944, 1070-1170, 1172-1234, 1345-1450
|
|
# Note: Python slices are [start:end] where start is inclusive, end is exclusive.
|
|
# Line N -> Index N-1.
|
|
|
|
# Block 1: 1 to 779 (Index 0 to 779)
|
|
chunk1 = lines[:779]
|
|
|
|
# Block 2: Skip 780-944 (Index 779-944)
|
|
# Keep 945-1069 (Index 944-1069)
|
|
chunk2 = lines[944:1069]
|
|
|
|
# Block 3: Skip 1070-1170 (Index 1069-1170)
|
|
# Keep 1171 (Index 1170)
|
|
chunk3 = lines[1170:1171]
|
|
|
|
# Block 4: Skip 1172-1234 (Index 1171-1234)
|
|
# Keep 1235-1344 (Index 1234-1344)
|
|
chunk4 = lines[1234:1344]
|
|
|
|
# Block 5: Skip 1345-1450 (Index 1344-1450)
|
|
# Keep 1451-End (Index 1450:)
|
|
chunk5 = lines[1450:]
|
|
|
|
# New Content Strings
|
|
new_buildBridge = """ buildBridge(start, end, fromCenter = null, minDist = 2.0) {
|
|
// Wrapper for generateBezierBridge
|
|
// Simple Bezier logic for compatibility check
|
|
const p0 = start;
|
|
const p2 = end;
|
|
|
|
const midX = (p0.x + p2.x) / 2;
|
|
const midZ = (p0.z + p2.z) / 2;
|
|
const midY = (p0.y + p2.y) / 2;
|
|
|
|
const dx = p2.x - p0.x;
|
|
const dz = p2.z - p0.z;
|
|
const dist = Math.sqrt(dx*dx + dz*dz);
|
|
|
|
const nx = dx / dist;
|
|
const nz = dz / dist;
|
|
|
|
const arcFactor = dist < 5.0 ? 0.5 : (dist / 8.0);
|
|
const archHeight = 3.0 * arcFactor; // Simplified random
|
|
const curveMag = 0; // Straight arch for simple builds (or random if rng available?)
|
|
// We don't have RNG access easily here unless we use this.rng
|
|
// Assume this.rng exists.
|
|
if (this.rng) {
|
|
const cm = this.rng.range(-dist/4, dist/4);
|
|
const ah = this.rng.range(1, 4) * arcFactor;
|
|
// Recalc
|
|
}
|
|
|
|
// Re-use generateBezierBridge logic?
|
|
// "generateBezierBridge" requires pA, pB (Platforms).
|
|
// Here we have points.
|
|
// We'll duplicate logic briefly to ensure it works.
|
|
|
|
const p1 = {x: midX, y: midY + archHeight, z: midZ};
|
|
|
|
const steps = Math.ceil(dist * 2.5);
|
|
const pathVoxels = [];
|
|
const visited = new Set();
|
|
|
|
for(let i=0; i<=steps; i++) {
|
|
const t = i / steps;
|
|
const invT = 1 - t;
|
|
const x = invT*invT*p0.x + 2*invT*t*p1.x + t*t*p2.x;
|
|
const y = invT*invT*p0.y + 2*invT*t*p1.y + t*t*p2.y;
|
|
const z = invT*invT*p0.z + 2*invT*t*p1.z + t*t*p2.z;
|
|
const ix = Math.round(x);
|
|
const iy = Math.round(y);
|
|
const iz = Math.round(z);
|
|
const key = `${ix},${iy},${iz}`;
|
|
if (!visited.has(key)) {
|
|
visited.add(key);
|
|
pathVoxels.push({x: ix, y: iy, z: iz});
|
|
}
|
|
}
|
|
|
|
// VALIDATION
|
|
for (let i=0; i<pathVoxels.length; i++) {
|
|
const v = pathVoxels[i];
|
|
if (!this.grid.isValidBounds(v.x, v.y, v.z)) return false;
|
|
const id = this.grid.getCell(v.x, v.y, v.z);
|
|
if (id !== 0 && id !== 20 && id !== 22) {
|
|
const dStart = (v.x-p0.x)**2 + (v.y-p0.y)**2 + (v.z-p0.z)**2;
|
|
const dEnd = (v.x-p2.x)**2 + (v.y-p2.y)**2 + (v.z-p2.z)**2;
|
|
if (dStart > 4 && dEnd > 4) return false;
|
|
}
|
|
const h1 = this.grid.getCell(v.x, v.y+1, v.z);
|
|
const h2 = this.grid.getCell(v.x, v.y+2, v.z);
|
|
if (h1 !== 0 || h2 !== 0) return false;
|
|
if (i > 0) {
|
|
if (Math.abs(v.y - pathVoxels[i-1].y) > 1) return false;
|
|
}
|
|
}
|
|
|
|
// PLACEMENT
|
|
for (const v of pathVoxels) {
|
|
if (this.grid.getCell(v.x, v.y, v.z) === 0) {
|
|
this.grid.setCell(v.x, v.y, v.z, 20);
|
|
}
|
|
}
|
|
return true;
|
|
}\n\n"""
|
|
|
|
new_connectivity = """ /**
|
|
* Ensure Connectivity via Flood Fill & Teleporters.
|
|
*/
|
|
ensureGlobalConnectivity(spires) {
|
|
if (!spires || spires.length === 0) return;
|
|
|
|
let startPt = {x: spires[0].x, y: spires[0].platforms[0].y + 1, z: spires[0].z};
|
|
|
|
const visited = new Set();
|
|
const q = [{x: Math.round(startPt.x), y: Math.round(startPt.y), z: Math.round(startPt.z)}];
|
|
visited.add(`${q[0].x},${q[0].y},${q[0].z}`);
|
|
|
|
const MAX_ITER = 50000;
|
|
let iter = 0;
|
|
|
|
// Flood Fill
|
|
while(q.length > 0 && iter < MAX_ITER) {
|
|
iter++;
|
|
const curr = q.shift();
|
|
|
|
const dirs = [{x:1,z:0},{x:-1,z:0},{x:0,z:1},{x:0,z:-1}];
|
|
for(const d of dirs) {
|
|
const nx = curr.x+d.x;
|
|
const nz = curr.z+d.z;
|
|
// Y-scan
|
|
const candidates = [curr.y, curr.y+1, curr.y-1];
|
|
for(const ny of candidates) {
|
|
if (this.grid.isValidBounds(nx, ny, nz)) {
|
|
const floor = this.grid.getCell(nx, ny-1, nz);
|
|
const feet = this.grid.getCell(nx, ny, nz);
|
|
const h1 = this.grid.getCell(nx, ny+1, nz);
|
|
const h2 = this.grid.getCell(nx, ny+2, nz);
|
|
|
|
const pass = (floor!==0 && (feet===0||feet===20||feet===22) && h1===0 && h2===0);
|
|
if(pass) {
|
|
const key = `${nx},${ny},${nz}`;
|
|
if(!visited.has(key)) {
|
|
visited.add(key);
|
|
q.push({x:nx, y:ny, z:nz});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Identify Orphans
|
|
const orphans = [];
|
|
spires.forEach(s => {
|
|
s.platforms.forEach(p => {
|
|
// Check if any point on/near platform is visited
|
|
let connected = false;
|
|
const r = p.radius - 1;
|
|
for(let x=p.x-r; x<=p.x+r; x++) {
|
|
for(let z=p.z-r; z<=p.z+r; z++) {
|
|
const key = `${Math.round(x)},${Math.round(p.y+1)},${Math.round(z)}`;
|
|
if(visited.has(key)) { connected = true; break; }
|
|
}
|
|
if(connected) break;
|
|
}
|
|
if (!connected) orphans.push(p);
|
|
});
|
|
});
|
|
|
|
// Fix Orphans with Teleporters
|
|
orphans.forEach(orp => {
|
|
const ox = Math.round(orp.x);
|
|
const oz = Math.round(orp.z);
|
|
const oy = Math.round(orp.y + 1); // Stand on top
|
|
|
|
// Find target (Spawn/Spire 0)
|
|
const target = spires[0].platforms[0];
|
|
const tx = Math.round(target.x);
|
|
const tz = Math.round(target.z);
|
|
const ty = Math.round(target.y + 1);
|
|
|
|
if(this.grid.isValidBounds(ox, oy, oz) && this.grid.isValidBounds(tx, ty, tz)) {
|
|
this.grid.setCell(ox, oy, oz, 22); // Teleporter
|
|
this.grid.setCell(tx, ty, tz, 22); // Teleporter
|
|
// Logic linkage would be separate asset, but visual ID 22 is enough for now.
|
|
// console.log("Teleporter Placed");
|
|
}
|
|
});
|
|
}\n\n"""
|
|
|
|
# Assemble
|
|
final_content = (
|
|
chunk1 +
|
|
[" // A* Removed\n"] +
|
|
chunk2 +
|
|
[new_buildBridge] +
|
|
chunk3 +
|
|
[" // Legacy Removed\n"] +
|
|
chunk4 +
|
|
[new_connectivity] +
|
|
chunk5
|
|
)
|
|
|
|
# Write back
|
|
with open(path, "w", encoding="utf-8") as f:
|
|
f.writelines(final_content)
|
|
|
|
print("Refactor Complete")
|