Removing slopes no longer leaves unowned seal cells; loading clears them
A slope's seal can sit in a cell its neighbour leaves open (a slope's open corner, or under a grate, screw or screen), but removal only cleared it when the neighbour was a sloped wall, so cutting a sloped belt next to a sloped filter or grate could leave a one-cell belt that nothing owned and nothing could remove. Removal now asks whether the neighbour fills that cell itself, and loading a world clears belt and screen cells that no block or seal owns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+18
-2
@@ -27,6 +27,22 @@ function slopeSealOwner(i) {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
// Does block b's own piece fill cell i (with a part, or else with a material)? A slope's seal can
|
||||
// sit in a cell its neighbour leaves open: a slope's open corner, or under a grate, screw or screen.
|
||||
function blockOwnsCell(b, i, asPart) {
|
||||
const c = blockP[b];
|
||||
if (!c || ((isSlope(c) || isSlopeBelt(c)) && !slopeCell(c, (i % W) & 3, ((i / W) | 0) & 3))) return false;
|
||||
return asPart ? isFilter(c) : !(isFilter(c) || c === BP_GRATE || c === BP_SCREW || c === BP_PIPE);
|
||||
}
|
||||
// Belt and screen cells that a removed slope left behind in an empty block (a removal bug in
|
||||
// older worlds): nothing owns them, so nothing could build there or take them away.
|
||||
function clearStraySeals() {
|
||||
for (let i = 0; i < N; i++) {
|
||||
if (mat[i] !== BELTL && mat[i] !== BELTR && part[i] !== P_FILTER) continue;
|
||||
if (blockP[(((i / W) | 0) >> 2) * BW + ((i % W) >> 2)] || slopeSealOwner(i) >= 0) continue;
|
||||
if (part[i] === P_FILTER) { part[i] = 0; wakeIdx(i); } else { setCell(i, EMPTY, temp[i], 0); markPow(i, false); }
|
||||
}
|
||||
}
|
||||
function wallCells(code, bx, by) {
|
||||
return blockCellList(bx, by).filter(i => !(isSlope(code) || isSlopeBelt(code)) || slopeCell(code, (i % W) & 3, ((i / W) | 0) & 3));
|
||||
}
|
||||
@@ -158,8 +174,8 @@ function removeBlock(bx, by) {
|
||||
if (isSlope(code) || isSlopeBelt(code)) {
|
||||
const i = slopeSeal(code, bx, by);
|
||||
if (i >= 0) {
|
||||
const nb = (((i / W) | 0) >> 2) * BW + ((i % W) >> 2), nc = blockP[nb];
|
||||
if ((!nc || (isSlope(nc) && !slopeCell(nc, (i % W) & 3, ((i / W) | 0) & 3))) && (mat[i] === (isBelt(code) ? (v ? BELTR : BELTL) : WALL_OF[v]) || (isFilter(code) && part[i] === P_FILTER)) && !(flags[i] & F_NAT)) { if (isFilter(code)) { part[i] = 0; wakeIdx(i); } else { setCell(i, EMPTY, temp[i], 0); if (isBelt(code)) markPow(i, false); } }
|
||||
const nb = (((i / W) | 0) >> 2) * BW + ((i % W) >> 2);
|
||||
if (!blockOwnsCell(nb, i, isFilter(code)) && (mat[i] === (isBelt(code) ? (v ? BELTR : BELTL) : WALL_OF[v]) || (isFilter(code) && part[i] === P_FILTER)) && !(flags[i] & F_NAT)) { if (isFilter(code)) { part[i] = 0; wakeIdx(i); } else { setCell(i, EMPTY, temp[i], 0); if (isBelt(code)) markPow(i, false); } }
|
||||
cleared.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@ function deserializeWorld(meta, buffers) {
|
||||
seen = new Uint8Array(NMAT); meta.seen.forEach((v, k) => { if (k < NMAT) seen[k] = v; });
|
||||
ledger = meta.ledger || {};
|
||||
Object.assign(stats, meta.stats || {});
|
||||
clearStraySeals();
|
||||
powerDirty = true; rebuildPower(); slopeCleatsTick(false); updateRoof();
|
||||
if (!weather.base) weather.base = worldWater(); // older saves: take the water it has now as its starting amount
|
||||
if (!meta.specks) clearHardSpecks(true); // older saves: tidy away tiny specks of too-hard rock once
|
||||
|
||||
Reference in New Issue
Block a user