Skip to content

Instantly share code, notes, and snippets.

@Angeschossen
Last active January 8, 2026 16:44
Show Gist options
  • Select an option

  • Save Angeschossen/37f0e2b2641e2980d4a0ee489de81715 to your computer and use it in GitHub Desktop.

Select an option

Save Angeschossen/37f0e2b2641e2980d4a0ee489de81715 to your computer and use it in GitHub Desktop.
public class LandsLevelRequirementsExample implements Listener {
private boolean anyLandRequirement = false;
private final me.angeschossen.lands.api.LandsIntegration api;
public LandsLevelRequirementsExample(Plugin plugin) {
this.api = me.angeschossen.lands.api.LandsIntegration.of(plugin);
api.onLoad(() -> { // requirements must be registered before Lands enables
// land level requirements
@Nullable Map<Level, ConfigurationSection> landLevels = api.getLevelsHandler().getLandSection();
if (landLevels != null) {
for (Map.Entry<Level, ConfigurationSection> entry : landLevels.entrySet()) {
ConfigurationSection requirement = entry.getValue().getConfigurationSection("requirements.upgradeablehoppers.hoppers");
if (requirement != null) {
int value = Math.max(requirement.getInt("required", 0), 0);
String reqName = StringUtils.colorize(requirement.getString("title", "Requirement Name"));
List<String> description = requirement.getStringList("description");
description.replaceAll(StringUtils::colorize);
entry.getKey().addRequirement(parseLandRequirement(reqName, description, value));
this.anyLandRequirement = true;
}
}
}
});
}
private me.angeschossen.lands.api.levels.requirement.Requirement parseLandRequirement(@NotNull String reqName, @NotNull List<String> description, int value) {
return new me.angeschossen.lands.api.levels.requirement.impl.Requirement(api, HolderType.LAND, "upgradeablehoppers_hoppers", reqName, description, value, String.valueOf(value)) {
@Override
public @NotNull String makeProgressDisplay(@NotNull MemberHolder memberHolder, float value) {
return (int) value + "/" + (int) getRequired();
}
@Override
public @NotNull CompletableFuture<Float> retrieveValue(@NotNull MemberHolder memberHolder) {
return CompletableFuture.supplyAsync(() -> {
final Land land = (Land) memberHolder;
float hoppers = 0;
for (IHopperWorld world : UpgradeableHoppers.getInstance().getDatabase().getWorlds()) {
Container container = land.getContainer(world.getWorld());
if (container == null) {
continue; // land has no claims in this world
}
for (ChunkCoordinate chunkCoordinate : container.getChunks()) {
// get the amount of hoppers of a claimed chunk. Does NOT require hoppers to be loaded
hoppers += world.getHoppersAmountByChunk(new IChunkCoordinate(chunkCoordinate.getX(), chunkCoordinate.getZ()));
}
}
return hoppers;
});
}
};
}
@Override
public void onEnable() {
Bukkit.getPluginManager().registerEvents(this, UpgradeableHoppers.getInstance());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onHopperBreak(HopperBreakEvent e) {
handleHopperAmountMod(e.getHopper().getPosition(), -1);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onHopperPlace(HopperPlaceEvent e) {
handleHopperAmountMod(e.getHopper().getPosition(), 1);
}
private void handleHopperAmountMod(@NotNull BlockPosition pos, int modify) {
if (!this.anyLandRequirement) {
return;
}
Land land = api.getLandByChunk(pos.getWorld(), pos.getChunkX(), pos.getChunkZ());
if (land == null) {
return; // location is wilderness
}
// add or remove from total amount in land
land.modifyRequirementCache("upgradeablehoppers_hoppers", modify, false, true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment