DPC Zettelkasten Open in the explorer

Spatial Value Types

Positions are stored as plain records holding a world UUID and numbers, never as live Bukkit objects, and are converted at the boundary.

The records that get persisted do not hold Bukkit objects. The area package supplies four plain types — a precise position, a block, a chunk, and a cuboid — each carrying a world UUID and numbers, and each crossing into Bukkit only through an explicit named conversion.

Why a UUID and not a world

A World is a live server object; a UUID is a value. Storing the identifier rather than the reference is what lets these records be written to columns by jOOQ Persistence, survive a restart, and be held across a thread boundary without violating Main Thread Safety.

The conversions back are correspondingly nullable: toBukkitLocation() and toBukkitBlock() resolve the world by UUID and yield null if the server has no such world loaded. Every caller has to decide what an unresolvable position means, rather than receiving a stale object.

The cuboid is derived, not stored

MfCuboidArea keeps only two corners and computes everything else — minPosition and maxPosition per axis, height, width, depth, centre, the full block list, and a contains test. Its init block rejects a pair of corners in different worlds outright, so a mixed-world area cannot exist even briefly.

It also carries distanceSquared, which clamps the query point onto the box per axis before measuring — the distance to the nearest face, not to the centre, and squared to avoid a square root.

Who uses them

These are the vocabulary the rest of the model is written in. A Gate stores an MfCuboidArea plus a trigger MfBlockPosition; a Locked Block is a block position with an owner; a Duel snapshots both participants as MfPosition, yaw and pitch included, so it can put them back exactly as they stood.

Adoption is not uniform. Claimed Chunk predates or sidesteps the pattern — MfClaimedChunk stores worldId, x and z as loose fields and merely offers a convenience constructor taking an MfChunkPosition. Whether that is history or intent is not recorded anywhere in the repository.

The same instinct — replace a primitive or a framework object with a small purpose-built type — appears at the identity layer as Value Class Identifier. Here it buys persistence and thread safety; there it buys type safety between otherwise identical strings.

Sources

Linked from