Initial commit: Fix resource packaging and instant-bonemeal logic

This commit is contained in:
Professor Doom 2026-05-19 14:06:26 -05:00
commit 9f5876480c
19 changed files with 446 additions and 0 deletions

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# QuickComposter
A lightweight Minecraft plugin for Paper/Folia that allows players to quickly fill composters by right-clicking with compostable items. (or any item, can be configured)

65
pom.xml Normal file
View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://www.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>kcompost</groupId>
<artifactId>QuickComposter</artifactId>
<version>1.0</version>
<name>QuickComposter</name>
<url>https://coldfiles.dev/</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<copy file="${project.build.directory}/${project.build.finalName}.jar" todir="/home/bunchy7s/"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,28 @@
package kcompost;
import org.bukkit.plugin.java.JavaPlugin;
import kcompost.managers.PluginManager;
import kcompost.listeners.PlayerListener;
public class QuickComposter extends JavaPlugin {
@Override
public void onEnable() {
// Save default config
saveDefaultConfig();
// Initialize managers
PluginManager.getInstance().initialize();
// Register listeners
getServer().getPluginManager().registerEvents(new PlayerListener(this), this);
getLogger().info("QuickComposter has been enabled!");
}
@Override
public void onDisable() {
getLogger().info("QuickComposter has been disabled!");
}
}

View file

@ -0,0 +1,156 @@
package kcompost.listeners;
import kcompost.QuickComposter;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.data.Levelled;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.EquipmentSlot;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class PlayerListener implements Listener {
private final QuickComposter plugin;
public PlayerListener(QuickComposter plugin) {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onComposterInteract(PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
if (event.getHand() != EquipmentSlot.HAND) return;
Block block = event.getClickedBlock();
if (block == null || block.getType() != Material.COMPOSTER) return;
Player player = event.getPlayer();
ItemStack itemInHand = player.getInventory().getItemInMainHand();
Material type = itemInHand.getType();
if (type == Material.AIR) return;
// Config checks
boolean useAnyItem = plugin.getConfig().getBoolean("use-any-item", false);
if (!useAnyItem) {
List<String> supported = plugin.getConfig().getStringList("supported-items");
boolean found = false;
for (String s : supported) {
if (s.equalsIgnoreCase(type.name())) {
found = true;
break;
}
}
if (!found) return;
}
Levelled composter = (Levelled) block.getBlockData();
if (composter.getLevel() >= composter.getMaximumLevel()) return;
if (handleQuickCompost(player, block, itemInHand)) {
event.setCancelled(true);
}
}
private boolean handleQuickCompost(Player player, Block block, ItemStack item) {
Levelled composter = (Levelled) block.getBlockData();
int currentLevel = composter.getLevel();
int maxLevel = composter.getMaximumLevel();
int targetLevel = maxLevel - 1;
int amountInHand = item.getAmount();
boolean instantBonemeal = plugin.getConfig().getBoolean("instant-bonemeal", false);
if (instantBonemeal) {
int needed = targetLevel - currentLevel;
if (amountInHand < needed) {
return false;
}
}
// Folia compatibility check
boolean isFolia = false;
try {
Class.forName("io.papermc.paper.threadedregions.RegionScheduler");
isFolia = true;
} catch (ClassNotFoundException ignored) {}
if (isFolia) {
Bukkit.getRegionScheduler().execute(plugin, block.getLocation(), () -> {
processCompost(player, block, item);
});
} else {
processCompost(player, block, item);
}
return true;
}
private void processCompost(Player player, Block block, ItemStack item) {
if (block.getType() != Material.COMPOSTER) return;
Levelled composter = (Levelled) block.getBlockData();
int currentLevel = composter.getLevel();
int maxLevel = composter.getMaximumLevel();
// In Minecraft, level 7 is full, level 8 is ready to harvest (bonemeal)
int targetLevel = maxLevel - 1;
if (currentLevel >= targetLevel) return;
int amountInHand = item.getAmount();
if (amountInHand <= 0) return;
int itemsConsumed = 0;
boolean instantBonemeal = plugin.getConfig().getBoolean("instant-bonemeal", false);
if (instantBonemeal) {
int needed = targetLevel - currentLevel;
if (amountInHand >= needed) {
itemsConsumed = needed;
composter.setLevel(0);
block.setBlockData(composter);
block.getWorld().dropItemNaturally(block.getLocation().add(0, 1, 0), new ItemStack(Material.BONE_MEAL));
}
} else {
while (currentLevel < targetLevel && itemsConsumed < amountInHand) {
itemsConsumed++;
currentLevel++;
}
composter.setLevel(currentLevel);
block.setBlockData(composter);
}
if (itemsConsumed > 0) {
final int finalConsumed = itemsConsumed;
// Folia compatibility check for entity scheduler
boolean isFolia = false;
try {
Class.forName("io.papermc.paper.threadedregions.EntityScheduler");
isFolia = true;
} catch (ClassNotFoundException ignored) {}
if (isFolia) {
player.getScheduler().execute(plugin, () -> {
item.setAmount(amountInHand - finalConsumed);
}, null, 0);
} else {
item.setAmount(amountInHand - finalConsumed);
}
// Play sound and effect
block.getWorld().playEffect(block.getLocation(), org.bukkit.Effect.COMPOSTER_FILL_ATTEMPT, 0);
block.getWorld().playSound(block.getLocation(), org.bukkit.Sound.BLOCK_COMPOSTER_FILL, 1.0f, 1.0f);
}
}
}

View file

@ -0,0 +1,16 @@
package kcompost.managers;
public class PluginManager {
private static PluginManager instance;
public static PluginManager getInstance() {
if (instance == null) {
instance = new PluginManager();
}
return instance;
}
public void initialize() {
// Initialize your managers here
}
}

View file

@ -0,0 +1,21 @@
package kcompost.utils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public class Utils {
public static Component colorize(String msg) {
if (msg.contains("<") && msg.contains(">")) {
return MiniMessage.miniMessage().deserialize(msg);
}
return LegacyComponentSerializer.legacyAmpersand().deserialize(msg);
}
public static String legacyColorize(String msg) {
return LegacyComponentSerializer.legacyAmpersand().serialize(
LegacyComponentSerializer.legacyAmpersand().deserialize(msg)
);
}
}

View file

@ -0,0 +1,63 @@
# QuickComposter Configuration
# If true, the composter will instantly drop bonemeal when it reaches the max level.
# If false, it will stay at the full level (7) and require one more interaction or wait for the vanilla process.
instant-bonemeal: false
# If true, any item can be used to compost.
# If false, only items in the 'supported-items' list will work.
use-any-item: false
# list of items that can be used for composting if 'use-any-item' is false.
# it uses the standard material names
supported-items:
- WHEAT_SEEDS
- PUMPKIN_SEEDS
- MELON_SEEDS
- BEETROOT_SEEDS
- DRIED_KELP
- GLOW_BERRIES
- SHORT_GRASS
- FERN
- HANGING_ROOTS
- MANGROVE_ROOTS
- MOSS_CARPET
- SMALL_DRIPLEAF
- SUNFLOWER
- LILAC
- ROSE_BUSH
- PEONY
- PITCHER_PLANT
- BIG_DRIPLEAF
- WHEAT
- POTATO
- CARROT
- BEETROOT
- SUGAR_CANE
- KELP
- CACTUS
- BAMBOO
- MELON_SLICE
- PUMPKIN
- MELON
- APPLE
- BREAD
- COOKIE
- CAKE
- PIE
- MUSHROOM_STEW
- NETHER_WART
- SEA_PICKLE
- SHROOMLIGHT
- CRIMSON_FUNGUS
- WARPED_FUNGUS
- CRIMSON_ROOTS
- WARPED_ROOTS
- NETHER_SPROUTS
- WEEPING_VINES
- TWISTING_VINES
- AZALEA
- FLOWERING_AZALEA
- MOSS_BLOCK
- PINK_PETALS
- DRAGON_EGG

View file

@ -0,0 +1,6 @@
main: kcompost.QuickComposter
version: 1.0
name: QuickComposter
author: bunchy7s
api-version: 1.21
folia-supported: true

Binary file not shown.

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="maven-antrun-" default="main">
<target name="main">
<copy file="/home/bunchy7s/programs/mcplugins/QuickCompost/QuickComposter/target/QuickComposter-1.0.jar" todir="/home/bunchy7s/" />
</target>
</project>

63
target/classes/config.yml Normal file
View file

@ -0,0 +1,63 @@
# QuickComposter Configuration
# If true, the composter will instantly drop bonemeal when it reaches the max level.
# If false, it will stay at the full level (7) and require one more interaction or wait for the vanilla process.
instant-bonemeal: false
# If true, any item can be used to compost.
# If false, only items in the 'supported-items' list will work.
use-any-item: false
# list of items that can be used for composting if 'use-any-item' is false.
# it uses the standard material names
supported-items:
- WHEAT_SEEDS
- PUMPKIN_SEEDS
- MELON_SEEDS
- BEETROOT_SEEDS
- DRIED_KELP
- GLOW_BERRIES
- SHORT_GRASS
- FERN
- HANGING_ROOTS
- MANGROVE_ROOTS
- MOSS_CARPET
- SMALL_DRIPLEAF
- SUNFLOWER
- LILAC
- ROSE_BUSH
- PEONY
- PITCHER_PLANT
- BIG_DRIPLEAF
- WHEAT
- POTATO
- CARROT
- BEETROOT
- SUGAR_CANE
- KELP
- CACTUS
- BAMBOO
- MELON_SLICE
- PUMPKIN
- MELON
- APPLE
- BREAD
- COOKIE
- CAKE
- PIE
- MUSHROOM_STEW
- NETHER_WART
- SEA_PICKLE
- SHROOMLIGHT
- CRIMSON_FUNGUS
- WARPED_FUNGUS
- CRIMSON_ROOTS
- WARPED_ROOTS
- NETHER_SPROUTS
- WEEPING_VINES
- TWISTING_VINES
- AZALEA
- FLOWERING_AZALEA
- MOSS_BLOCK
- PINK_PETALS
- DRAGON_EGG

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,6 @@
main: kcompost.QuickComposter
version: 1.0
name: QuickComposter
author: bunchy7s
api-version: 1.21
folia-supported: true

View file

@ -0,0 +1,5 @@
#Generated by Maven
#Tue May 19 14:00:54 CDT 2026
artifactId=QuickComposter
groupId=kcompost
version=1.0

View file

@ -0,0 +1,4 @@
kcompost/utils/Utils.class
kcompost/managers/PluginManager.class
kcompost/listeners/PlayerListener.class
kcompost/QuickComposter.class

View file

@ -0,0 +1,4 @@
/home/bunchy7s/programs/mcplugins/QuickCompost/QuickComposter/src/main/java/kcompost/QuickComposter.java
/home/bunchy7s/programs/mcplugins/QuickCompost/QuickComposter/src/main/java/kcompost/listeners/PlayerListener.java
/home/bunchy7s/programs/mcplugins/QuickCompost/QuickComposter/src/main/java/kcompost/managers/PluginManager.java
/home/bunchy7s/programs/mcplugins/QuickCompost/QuickComposter/src/main/java/kcompost/utils/Utils.java