135 lines
4.1 KiB
Python
135 lines
4.1 KiB
Python
|
|
|
||
|
|
import os
|
||
|
|
|
||
|
|
path = "src/generation/CrystalSpiresGenerator.js"
|
||
|
|
with open(path, "r", encoding="utf-8") as f:
|
||
|
|
lines = f.readlines()
|
||
|
|
|
||
|
|
start_idx = -1
|
||
|
|
for i, line in enumerate(lines):
|
||
|
|
if "ensureGlobalConnectivity(spires) {" in line:
|
||
|
|
start_idx = i
|
||
|
|
break
|
||
|
|
|
||
|
|
if start_idx == -1:
|
||
|
|
print("Error: ensureGlobalConnectivity not found")
|
||
|
|
exit(1)
|
||
|
|
|
||
|
|
# Find end of method. It's likely the second to last closing brace, or indented " }".
|
||
|
|
# The previous `view_file` showed it ending at line 1212/1213.
|
||
|
|
# We will scan for " }" starting from start_idx.
|
||
|
|
end_idx = -1
|
||
|
|
for i in range(start_idx + 1, len(lines)):
|
||
|
|
if lines[i].rstrip() == " }":
|
||
|
|
end_idx = i
|
||
|
|
break
|
||
|
|
|
||
|
|
if end_idx == -1:
|
||
|
|
print("Error: Closing brace not found")
|
||
|
|
exit(1)
|
||
|
|
|
||
|
|
# New Content
|
||
|
|
new_code = """ ensureGlobalConnectivity(spires) {
|
||
|
|
if (!spires || spires.length === 0) return;
|
||
|
|
|
||
|
|
// 1. Build Adjacency Graph
|
||
|
|
// Map platform ID "sIdx:pIdx" -> {id, p, neighbors: Set<id>}
|
||
|
|
const adj = new Map();
|
||
|
|
const platById = new Map();
|
||
|
|
const getPlatId = (sIdx, pIdx) => `${sIdx}:${pIdx}`;
|
||
|
|
|
||
|
|
spires.forEach((s, sIdx) => {
|
||
|
|
s.platforms.forEach((p, pIdx) => {
|
||
|
|
const id = getPlatId(sIdx, pIdx);
|
||
|
|
adj.set(id, {id, p, neighbors: new Set()});
|
||
|
|
platById.set(id, p);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// Populate Neighbors from Bridges
|
||
|
|
this.generatedAssets.bridges.forEach(b => {
|
||
|
|
if (b.fromPlatIdx !== undefined && b.toPlatIdx !== undefined) {
|
||
|
|
const idA = getPlatId(b.fromSpire, b.fromPlatIdx);
|
||
|
|
const idB = getPlatId(b.toSpire, b.toPlatIdx);
|
||
|
|
if(adj.has(idA) && adj.has(idB)) {
|
||
|
|
adj.get(idA).neighbors.add(idB);
|
||
|
|
adj.get(idB).neighbors.add(idA);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// 2. Find Connected Components (BFS)
|
||
|
|
const visited = new Set();
|
||
|
|
const components = [];
|
||
|
|
|
||
|
|
for(const [id, node] of adj) {
|
||
|
|
if(!visited.has(id)) {
|
||
|
|
const comp = [];
|
||
|
|
const q = [id];
|
||
|
|
visited.add(id);
|
||
|
|
while(q.length > 0) {
|
||
|
|
const curr = q.shift();
|
||
|
|
comp.push(curr);
|
||
|
|
adj.get(curr).neighbors.forEach(nId => {
|
||
|
|
if(!visited.has(nId)) {
|
||
|
|
visited.add(nId);
|
||
|
|
q.push(nId);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
components.push(comp);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 3. Link Components
|
||
|
|
if (components.length > 1) {
|
||
|
|
// Identify Main Component (Largest)
|
||
|
|
components.sort((a,b) => b.length - a.length);
|
||
|
|
const targetComp = components[0];
|
||
|
|
const targetNodeId = targetComp[0];
|
||
|
|
const targetPlat = platById.get(targetNodeId);
|
||
|
|
|
||
|
|
for(let i=1; i<components.length; i++) {
|
||
|
|
const orphanComp = components[i];
|
||
|
|
const orphanNodeId = orphanComp[0];
|
||
|
|
const orphanPlat = platById.get(orphanNodeId);
|
||
|
|
|
||
|
|
this.placeTeleporter(targetPlat, orphanPlat);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
placeTeleporter(pA, pB) {
|
||
|
|
const findSpot = (p) => {
|
||
|
|
const r = p.radius - 1;
|
||
|
|
for(let x=Math.round(p.x-r); x<=Math.round(p.x+r); x++) {
|
||
|
|
for(let z=Math.round(p.z-r); z<=Math.round(p.z+r); z++) {
|
||
|
|
const y = Math.round(p.y);
|
||
|
|
const floor = this.grid.getCell(x, y, z);
|
||
|
|
const air = this.grid.getCell(x, y+1, z);
|
||
|
|
if (floor !== 0 && air === 0) {
|
||
|
|
return {x, y: y+1, z};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
};
|
||
|
|
|
||
|
|
const sA = findSpot(pA);
|
||
|
|
const sB = findSpot(pB);
|
||
|
|
|
||
|
|
if(sA && sB) {
|
||
|
|
this.grid.setCell(sA.x, sA.y, sA.z, 22);
|
||
|
|
this.grid.setCell(sB.x, sB.y, sB.z, 22);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
"""
|
||
|
|
|
||
|
|
# Replace
|
||
|
|
final_lines = lines[:start_idx] + [new_code] + lines[end_idx+1:]
|
||
|
|
|
||
|
|
with open(path, "w", encoding="utf-8") as f:
|
||
|
|
f.writelines(final_lines)
|
||
|
|
|
||
|
|
print("Update Complete")
|