You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Self-review: removing one chunk from a big selection deleted 143 others (#144)
`normalizeRects` sliced its INPUT at 256 rectangles, and the removal path
expanded the selection to one rectangle per chunk before filtering. So a
20x20 region — one rectangle, 400 chunks — became 400 rectangles, then
399, then the first 256. A hundred and forty-three chunks disappeared
with no error, no warning, and nothing to say which ones.
The first test used a row of four chunks, which is exactly why it stayed
green. Restoring the slice now fails with "removing one chunk from 400
left 256".
Removal no longer expands anything. It splits the rectangle AROUND the
chunk into the at most four pieces beside it, which touches only the
rectangle involved and cannot grow the list by more than three, whatever
the selection's size. The test now removes an interior chunk, a corner,
an edge, the only chunk, and one that was never selected — and checks
every one of the other 399 is covered exactly once, so a split that
overlapped would fail too.
The same slice had two more consequences, both fixed by refusing instead
of trimming:
An API caller who POSTed a hundred scattered chunks got a 200 with
sixty-four of them stored. `checkArea` counted the chunks and the
emptiness but never noticed rectangles had been dropped. There is now
a named `too-many-rects`, documented beside `too-many-chunks`, and the
cap is checked before normalising as well as after — a shape too
complex to store is refused, never silently trimmed. Three hundred
chunks in a ROW still pass, because they merge to one rectangle.
The panel's own tidy had no cap at all, so above 256 it and the app
disagreed about what had been selected. The panel now splits the same
way, and the smoke checks its answer against `subtractChunk`'s on the
400-chunk case rather than only on four.
Also: the desktop editor was permanently open, against its own comment
saying it should not be — drawing areas and editing them are two
decisions, which is how the web panel already had it. And
`forgetServerAreas` was written, documented as "called when a server is
forgotten", and called by nothing; `removeServer` calls it now, so a
later server issued the same id cannot inherit someone else's
annotations.
Verified: 12/12 gates.
Copy file name to clipboardExpand all lines: docs/openapi.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -2887,7 +2887,7 @@
2887
2887
"post": {
2888
2888
"operationId": "postServersIdAreas",
2889
2889
"summary": "Create an area, or edit one by passing `areaId`.",
2890
-
"description": "Scope `settings` on the server.\n\nBody fields:\n- `areaId` — Omit to create; pass an existing id to replace that area.\n- `name` — Shown on hover and on click. 1-48 characters.\n- `note` — The second line of the tooltip, e.g. who owns the area. Up to 280 characters.\n- `colour` — `#rrggbb` (`#rgb` is expanded). Anything else falls back to the first palette colour.\n- `dim` — `overworld` | `nether` | `end`, or a modded key. An area belongs to exactly one.\n- `rects` — Array of `{x1,z1,x2,z2}` in CHUNK coordinates, inclusive, corners in any order.\n- `hidden` — Keep it off every map but the operator's own.\n\nRectangles are tidied on the way in: duplicates and contained rects are dropped and neighbours that share a full edge are merged, so the stored shape covers exactly the chunks you sent. Refusals name themselves: `name-required`, `name-too-long`, `note-too-long`, `no-chunks`, `too-many-chunks` (max 65536), `too-many-areas` (max 200), `area-not-found`.",
2890
+
"description": "Scope `settings` on the server.\n\nBody fields:\n- `areaId` — Omit to create; pass an existing id to replace that area.\n- `name` — Shown on hover and on click. 1-48 characters.\n- `note` — The second line of the tooltip, e.g. who owns the area. Up to 280 characters.\n- `colour` — `#rrggbb` (`#rgb` is expanded). Anything else falls back to the first palette colour.\n- `dim` — `overworld` | `nether` | `end`, or a modded key. An area belongs to exactly one.\n- `rects` — Array of `{x1,z1,x2,z2}` in CHUNK coordinates, inclusive, corners in any order.\n- `hidden` — Keep it off every map but the operator's own.\n\nRectangles are tidied on the way in: duplicates and contained rects are dropped and neighbours that share a full edge are merged, so the stored shape covers exactly the chunks you sent. Refusals name themselves: `name-required`, `name-too-long`, `note-too-long`, `no-chunks`, `too-many-chunks` (max 65536), `too-many-rects` (a shape of more than 64 separate pieces after tidying, or more than 1024 sent), `too-many-areas` (max 200), `area-not-found`. A shape too complex to store is refused, never silently trimmed.",
rects: 'Array of `{x1,z1,x2,z2}` in CHUNK coordinates, inclusive, corners in any order.',
220
220
hidden: 'Keep it off every map but the operator\'s own.'
221
221
},
222
-
notes: 'Rectangles are tidied on the way in: duplicates and contained rects are dropped and neighbours that share a full edge are merged, so the stored shape covers exactly the chunks you sent. Refusals name themselves: `name-required`, `name-too-long`, `note-too-long`, `no-chunks`, `too-many-chunks` (max 65536), `too-many-areas` (max 200), `area-not-found`.'
222
+
notes: 'Rectangles are tidied on the way in: duplicates and contained rects are dropped and neighbours that share a full edge are merged, so the stored shape covers exactly the chunks you sent. Refusals name themselves: `name-required`, `name-too-long`, `note-too-long`, `no-chunks`, `too-many-chunks` (max 65536), `too-many-rects` (a shape of more than 64 separate pieces after tidying, or more than 1024 sent), `too-many-areas` (max 200), `area-not-found`. A shape too complex to store is refused, never silently trimmed.'
223
223
},
224
224
{method: 'DELETE',path: '/servers/{id}/areas',gate: 'settings',group: 'areas',summary: 'Delete one area.',params: [serverId,{name: 'areaId',in: 'query',required: true,description: 'Area to delete.'}]},
0 commit comments