SOURCE / PINNED RELEASE
Made of little things.
Napcraft
- Release
- ee47ac6a25df…
- Author-recorded commit
- 410dea87e109…
- License
- LICENSE
- Author’s source reference
- nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-52f9e22f5ce
Archive hash verified: 9e6e0cabb18d0d46…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
import { cell, top } from './world';
import type { World } from './world';
type Point = { x: number; y: number };
type Project = (x: number, y: number, z: number) => Point;
function inside(point: Point, polygon: Point[]) {
let sign = 0;
for (let i = 0; i < polygon.length; i++) {
const a = polygon[i], b = polygon[(i + 1) % polygon.length];
const cross = (b.x-a.x)*(point.y-a.y)-(b.y-a.y)*(point.x-a.x);
if (Math.abs(cross) < 0.001) continue;
const next = Math.sign(cross);
if (sign && next !== sign) return false;
sign = next;
}
return true;
}
// Reverse the renderer's painter order: a visible wall must win over a hidden
// top face behind it. Selection still edits the top of this supported column.
export function pickColumn(world: World, project: Project, sx: number, sy: number) {
const point = {x:sx,y:sy};
for (let sum = 34; sum >= 0; sum--) {
for (let x = 17; x >= 0; x--) {
const z = sum-x;
if (z < 0 || z > 17) continue;
for (let y = top(world,x,z); y >= 0; y--) {
if (!world.blocks[cell(x,y,z)]) continue;
const a=project(x,y+1,z), b=project(x+1,y+1,z),
d=project(x,y+1,z+1), e=project(x+1,y+1,z+1), bottom=project(x+1,y,z+1);
if (inside(point,[a,b,e,d]) ||
inside(point,[b,e,bottom,project(x+1,y,z)]) ||
inside(point,[d,e,bottom,project(x,y,z+1)])) return {x,z};
}
}
}
}
