During September, I worked on Minasty, a commissioned Minecraft project with interconnected farming, fertility, and mining systems. The gameplay involved crop conditions, soil wear and recovery, and supplementary ore rewards. Underneath that, I was building Java/Paper infrastructure that had to keep crop identity, persistent state, and physical Minecraft behavior in agreement.

The interesting part was deciding which system owned each fact. A crop’s physical representation, a chunk’s authored fertility, and the history of what happened there are related, but they need different lifecycles. I’ll explain the work through those boundaries rather than a week-by-week timeline.

Giving crops a reusable foundation

I built FarmingCore around crop identity and behavior. A namespaced ID identifies the logical crop; a behavior describes its physical representation: finding the base, recognizing member blocks, checking maturity, counting harvested units, and resetting or removing it.

That distinction matters beyond wheat. A vertical crop needs to preserve its root, a melon involves a stem and fruit, and a multi-block representation needs a canonical base. The lifecycle can coordinate planting and harvesting without assuming every crop is one ageable block.

Registrations belong to the contributing plugin. Their handles are idempotent, and an old handle cannot unregister a newer replacement with the same ID. Disabling an owner cleans up its registrations and callbacks. That keeps reload and shutdown behavior explicit and avoids retaining another plugin’s objects indefinitely.

FarmingCore supplies generic planting, growth, and yield evaluation, but it does not own Minasty’s progression or rewards. Fertility is an ordered finite value, with no framework-imposed percentage scale. One registered provider supplies it; a missing provider is an unavailable dependency, not permission to invent a number.

The harvest lifecycle developed in documented slices: I introduced reservations and policies, moved the vanilla break adapter onto that authoritative path, added post-commit observers, and then added exact tracking-only reconciliation for external representations. These extensions gave integrations specific entry points without exposing the core implementation.

Tracking identity without pretending to save the world

PostgreSQL had been chosen before I implemented persistence, so there was no existing storage layer to migrate. My reaction to the decision was mostly a joke: “Welp. One more line for my resume.”

Crop identity persists in PostgreSQL, keyed by world UUID and base-block coordinates. Normal occupancy queries use an in-memory projection and do not load chunks or query the database. Partial harvest progress and reservations remain process-local.

The distinction between “unavailable” and “gone” is important. A missing crop registration or unloaded world does not delete an identity. Loaded-chunk reconciliation removes it only when the registered behavior can establish definite physical invalidity. Uncertain validation retains occupancy.

That conservative choice feeds directly into fertility: an unavailable crop must not accidentally make its chunk look fallow.

Identity mutations commit durably before the corresponding memory state is published. A confirmed rollback preserves the old projection; an uncertain commit makes the service fail visibly. Returning an empty tracker after a database failure would turn a storage problem into a gameplay decision.

There is still no shared transaction between PostgreSQL and Minecraft world saves. A durable crop row can survive while its physical block does not, or physical removal can precede a failed database delete. Lazy reconciliation addresses definite mismatches. Abnormal Minasty placements also go into a reconciliation journal, whose automated recovery scan remained deferred.

Adding Minasty’s rules without duplicating crop mechanics

MinastyFarming maps configured minasty:* crops onto FarmingCore. For vanilla representations, I reused the exact existing behavior under a separate logical identity.

That creates a deliberate ambiguity: the same wheat block can match both the generic and Minasty registration. FarmingCore does not choose whichever registration appears first. MinastyFarming supplies explicit identity after checking the configured planting conditions and optional Agriculture requirements. Technology-based crop restrictions use a similar progression gate, but their API hook was delivered separately after September, once the other developer made the Technology API available.

Planting commits on the next server tick after observing the final placement event. Before committing, the adapter rechecks the physical state and its runtime generation, so work scheduled before a reload cannot register an outdated crop. The first version permits only one Minasty crop per vanilla template; distinguishing more would require an actual placement discriminator.

Reload has another precise boundary. The public catalog exposes an immutable old or new snapshot through one stable service object. The underlying crop registry only offers individual registration operations, so its replacement is not atomic for direct concurrent readers. Failed replacement reconstructs the old registrations; failed rollback disables the integration instead of publishing a partial catalog.

I developed harvest outputs separately: a pure quantity calculator, then a post-commit observer, then live validation. Configured amounts are multiplied by the available yield multiplier and rounded half up. They apply once per completed harvest, independently of physical harvested units. Delivery supports vanilla items as drops or inventory inserts, with overflow dropped at the crop.

ResourceCore: authored values at chunk granularity

ResourceCore models a resource as a namespaced numeric definition and assignments addressed by world UUID and chunk X/Z. The Resources host embeds the engine and publishes its service. Fertility and ore density can share that assignment infrastructure without sharing gameplay behavior.

Chunk granularity gives the content team an area-authoring model. A selected rectangle can receive fertility or ore-density values without creating a separate runtime “deposit” object. ResourceCore stores the authored baseline; consuming plugins decide what it means.

An explicit assignment equal to the default remains different from no assignment. Clearing a value restores default resolution; setting zero records an intentional zero. That distinction also matters to previews and undo.

Reads capture immutable state. Validated bulk writes commit as one PostgreSQL transaction before publishing a replacement snapshot. Conditional mutations compare expected explicit assignments under the writer lock, so an overlapping administrator edit rejects the entire confirmation or undo.

The command layer keeps world and player access on the server thread and hands immutable requests to a bounded worker. Undo is session-local, and value comparison cannot detect an intervening change that later restores exactly the same state. Those are documented limits, not a persistent audit-history system.

Fertility needed a clock and an ordered history

MinastyFertility owns depletion and crop history separately from ResourceCore’s baseline. Changing the baseline does not erase accumulated wear. Effective fertility subtracts remaining depletion, subject to a configured floor that cannot raise fertility above the baseline.

Passive recovery uses FarmingCore’s durable cumulative unoccupied-time clock. Recovery accrues only while the chunk contains no tracked crops, including unoccupied downtime across restart. It is calculated lazily from memory snapshots, rather than updated in PostgreSQL every tick.

Crop cycles needed more than a current occupancy query. FarmingCore journals committed planting and harvest receipts in source order, including exact crop identity, harvest disposition, and unoccupied time at the transition. MinastyFertility commits its soil changes and receipt cursor together, then acknowledges consumption.

The storage migrations record that expansion: crop identity first, then the sparse occupancy clock, then lifecycle receipts. MinastyFertility’s later migration added history and a persisted consumption cursor without rewriting its original migration.

If a crash happens before that transaction, the receipt can replay. If the transaction committed but acknowledgment did not, the persisted cursor prevents applying wear again. Replay uses the receipt’s own time snapshot, so later occupancy changes do not alter the recovery calculation for an earlier planting. Missing history or an epoch mismatch fails visibly.

This is recoverable coordination across plugins, not one transaction spanning both. FarmingCore has already committed the crop action when fertility processes it; a soil-write failure cannot roll that action back.

Replanting semantics are explicit. The default mode applies wear to genuine planting and records a removal time after a REMOVED harvest. A RESET starts another physical growth cycle without applying planting wear. An alternative mode treats reset as immediate same-crop replanting.

Repeat penalties and rotation compare exact CropIds. Rapid-replant multiplication applies to positive wear before rotation credit. Recovery-rate changes materialize elapsed recovery under the old rate before switching. The shipped wear, recovery, rotation, and rapid-window settings are zero: I implemented the mechanics without presenting sample values as final gameplay balance.

Respecting the mechanics an adapter can actually control

Growth evaluation gates existing vanilla opportunities with probabilities from zero to one. It can slow or suppress growth; it cannot accelerate it beyond vanilla. Custom growth scheduling remained outside the foundation.

Paper’s event provenance limits the policy. Some BlockGrowEvent paths are shared with bonemeal, so I cannot honestly label all matching events natural growth. Kelp and cave-vine extension have usable natural spread paths; bamboo’s shared spread path does not provide the distinction needed for that integration.

The Nexo investigation established a larger boundary. In the verified 1.28.0 version, furniture placement was exposed, but native crop evolution lacked the supported transition and complete physical-lifecycle contracts needed by the planned adapter. Generic FarmingCore lifecycle extensions could not supply that missing upstream control. Nexo syntax remained parseable, but runtime crop candidates were rejected and the full adapter stayed deferred.

Harvest authorization has similar limits. FarmingCore’s vanilla adapter uses the authoritative reservation-based lifecycle, and observers run after successful completion. A raw canceled break event is not a harvest receipt. Its cancellation ordering also cannot guarantee compatibility with every later protection listener; I did not claim a universal authorization boundary.

Supplementary ores, with provenance as persistent state

MinastyOres uses ResourceCore independently of farming. For each eligible host break, it reads one coherent density snapshot and rolls matching ore definitions independently. Density controls chance; Fortune changes quantity after a successful roll. Authored density does not deplete through mining.

The integration observes confirmed Survival mining with an eligible pickaxe and enabled drops. It correlates the break with the drop event and retains the captured tool, so switching items cannot change that break’s Fortune or Silk Touch decision. Silk Touch suppresses supplementary rewards. Configured Mining requirements can gate individual extra rewards; the later Technology API hook added equivalent restrictions based on unlocked Technology. Vanilla drops and XP remain unchanged.

Persistent provenance prevents ordinary place-and-break loops. Supported placement, formation, and movement paths durably mark eligible host destinations as untrusted before allowing the change. Confirmed removal deletes only the observed marker generation, so stale cleanup cannot erase a replacement marker. Uncertain provenance stops rewards rather than treating the block as natural.

The protection cannot reconstruct pre-existing blocks’ history or observe arbitrary plugin edits. Those limits matter when choosing a mining world.

Supplementary item spawning is deferred and process-local. A crash or unavailable chunk can lose a reward. Partial or uncertain spawning disables delivery instead of retrying items that might already exist. Durable provenance does not imply durable reward delivery.

Verification and the handoff boundary

Verification covered domain rules, lifecycle behavior, and real database semantics. FarmingCore’s documented suites exercise ambiguity, ownership, stale operations, timing, observer reentrancy, and failure isolation. PostgreSQL acceptance cases cover restart restoration, commit failures, receipt ordering, retention, and concurrent projection reads. Resource administration tests cover conditional batches and rollback, including a 512-target set/clear case. Fertility and ore integrations have their own disposable PostgreSQL acceptance suites.

The documented crop smoke test on Paper 26.2 verified placement, deferred tracking, four accepted harvest hits, physical reset, and exactly one reward after completion. It also checked inventory overflow and runtime stack limits: 130 wheat split into 64 + 64 + 2, while 35 snowballs split into 16 + 16 + 3. Ore and resource-admin live smoke tests were still identified separately; I cannot extend the crop result to them.

I delivered the five server plugins and their operator handbooks in September 2026, completing my agreed scope. API and developer artifacts were separate from the deployable plugins. Once the separately maintained Technology API became available, a follow-up delivery added its progression checks for crop planting and supplementary mining rewards.

Other investigated or deferred capabilities—including the full Nexo crop adapter, custom-item outputs, Skills-based harvest restrictions, broader crop protection, and automated placement-journal reconciliation—were not unfinished obligations from the September handoff.

September’s result was a set of connected systems with explicit ownership and failure semantics. Crops retain identity, fertility consumes ordered facts, and ores preserve vanilla mining while adding their own policy. The useful engineering story is in those contracts—and in keeping their limits visible.