Skip to main content
Everything about crops is in the org.lodemc.api.crop package. There are three ways to change how crops behave, and you can mix them: See Setting up first if your plugin doesn’t depend on Lode Items yet.

Example: crops that need a block nearby

This rule stops every custom crop growing unless a composter is within 4 blocks:
The crop still grows at its normal speed next to a composter, because the rule passes the chance on unchanged. To make it pop off when the composter is broken, and stop it being planted away from one, override canSurvive the same way.

LodeCrops

org.lodemc.api.crop.LodeCrops has static methods. All of them take Bukkit Blocks and are called from the main thread.

Finding crops

Collection<CustomCrop>
Every crop configured right now.
CustomCrop
The crop with this id, or null if there isn’t one. Also takes the id as a String (tomato_seeds means lodeitems:tomato_seeds). A crop’s id is its seed’s id.
PlantedCrop
The crop planted at block, with its current stage, or null if there’s no custom crop there.
boolean
Whether a custom crop is planted at block.
double
The growth factor vanilla uses for the crop at block: 1 on bare ground, higher with farmland under and around it (wet farmland counts 3 times as much), halved when the same crop is packed around it instead of in rows. Returns 0 if there’s no crop. The crop’s own speed: isn’t included.

Changing crops

boolean
Sets the crop at block to stage. The stage is kept between 0 and the ripe stage. With fireEvent (the default when you leave it out), a CropGrowEvent with cause PLUGIN fires first and can change or cancel it. Returns false if there’s no crop, the event was cancelled, or the stage didn’t change.
boolean
Grows the crop at block by stages (default 1). A negative number makes it younger. Works like setStage.
boolean
Plants crop id at block at stage (default 0), replacing whatever is there. The soil isn’t checked: call canPlant first if it matters. A crop that can’t survive where it is pops off the next time a block next to it changes.
boolean
Whether crop id could be planted at block: the spot can be replaced (air, grass…), the block below is one of the crop’s on: soils, and every crop rule’s canSurvive agrees.
boolean
Picks the crop at block the way a right-click does: only if it’s ripe and its harvest: option is on. Fires a CropHarvestEvent, drops the produce and replants it. player is optional and can be null. Returns true if it was picked.

Managing rules

void
Adds a crop rule for every crop. Rules run in the order they were added. The rule is removed when plugin disables, so you don’t need to remove it yourself.
CropRule
Adds a rule for crop id only; other crops skip it. Returns the rule that was really added, which is what you pass to removeRule.
void
Removes one rule.
void
Removes every rule plugin added.

CustomCrop

A crop as it’s configured. It’s read-only: change behaviour with rules and events. A reload makes new CustomCrop objects, so look crops up again after LodeItemsLoadEvent instead of keeping them.

PlantedCrop

What LodeCrops.at returns: a crop in the world at the moment you asked.

GrowCause

Why a crop changed stage, given by CropGrowEvent:

Crop rules

A CropRule changes the rules every crop follows. It has three methods, and you override only the ones you need. Each one gets the answer so far, from Lode Items and then from rules added before yours, and returns its own answer. To leave a crop alone, return what you were given.
boolean
Whether the crop can stay where it is. Returning false for a planted crop makes it pop off with its drops the next time a block next to it changes, like wheat on trampled farmland. While a player plants a seed, returning false stops the seed being planted. result starts as “the block below is one of its on: soils”.
double
The chance, from 0 to 1, that this growth tick grows the crop one stage. chance starts as vanilla’s crop formula, or 0 when it’s darker than the crop’s min-light. Return 0 to stop growth or 1 to grow it every tick. Ripe crops don’t get growth ticks, so this isn’t called for them.
boolean
Whether bone meal works on the crop. When it returns false, the bone meal isn’t used up. result starts as “its bone-meal: option is on and it isn’t ripe”.
Rules run inside the game’s own block logic, sometimes many times a tick. Keep them fast, read the world only through the CropContext, and don’t change blocks from a rule. Change blocks from an event instead.

Rules or events?

Both can stop growth, so use whichever fits:
  • Use a rule for anything about where a crop may stay or be planted, since only rules can answer that. Rules are also cheaper when you only change a number.
  • Use an event when you need to know about the change after it’s decided, change the target stage, or do something with the player or the world, such as messages, particles or placing blocks.
On each growth tick, rules run first and the CropGrowAttemptEvent gets the chance they returned.

CropContext

What a rule knows about the crop it’s being asked about. Reading blocks never loads chunks. A block in an unloaded chunk reads as null, and the isNear and countNear checks skip it. The box is centred on the crop, and the crop itself doesn’t count. radius and vertical can each be 0 to 32. A box of radius 4 and vertical 1 holds 242 blocks, so keep boxes small in rules that run on every growth tick.
A canSurvive rule is checked when a block next to the crop changes, not when something further away does. If your rule depends on a block 5 blocks away, breaking that block doesn’t pop the crop at once. It pops off the next time one of its neighbours changes, or you can check it yourself and break it from an event.