From 0ac427e1fc04ccd38d5f31aecfe78304c9f37e4f Mon Sep 17 00:00:00 2001 From: Eygwi <245492840+eygwi@users.noreply.github.com> Date: Mon, 22 Dec 2025 21:48:41 +0700 Subject: [PATCH 1/3] add features and fix item warning --- .vscode/settings.json | 3 + pom.xml | 33 ++- .../slimecustomizer/Events.java | 1 - .../objects/CustomMachine.java | 37 ++- .../slimecustomizer/objects/CustomSCItem.java | 19 +- .../objects/NPCustomSCItem.java | 17 +- .../slimecustomizer/objects/SCAGenerator.java | 2 +- .../slimecustomizer/objects/SCMachine.java | 211 +++++++++--------- .../registration/Machines.java | 9 +- src/main/resources/generators.yml | 7 + src/main/resources/machines.yml | 22 +- 11 files changed, 216 insertions(+), 145 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6a1a780 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "commentTranslate.hover.enabled": false +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 62118e0..c4e061e 100644 --- a/pom.xml +++ b/pom.xml @@ -8,22 +8,17 @@ 1.21.x-EXPERIMENTAL - 1.8 - 1.8 + 21 + 21 UTF-8 - paper-repo - https://repo.destroystokyo.com/repository/maven-public/ + papermc + https://repo.papermc.io/repository/maven-public/ - - - spigot-repo - https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - - + jitpack.io https://jitpack.io @@ -54,7 +49,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.4 + 3.6.0 @@ -87,16 +82,16 @@ - org.spigotmc - spigot-api - 1.16.5-R0.1-SNAPSHOT + io.papermc.paper + paper-api + 1.21.4-R0.1-SNAPSHOT provided - io.github.TheBusyBiscuit + com.github.Slimefun Slimefun4 - 3ea21da + experimental-SNAPSHOT provided @@ -109,15 +104,15 @@ org.bstats bstats-bukkit - 2.2.1 + 3.1.0 compile org.projectlombok lombok - 1.18.20 + 1.18.34 provided - + \ No newline at end of file diff --git a/src/main/java/io/ncbpfluffybear/slimecustomizer/Events.java b/src/main/java/io/ncbpfluffybear/slimecustomizer/Events.java index 43de0c9..9b18710 100644 --- a/src/main/java/io/ncbpfluffybear/slimecustomizer/Events.java +++ b/src/main/java/io/ncbpfluffybear/slimecustomizer/Events.java @@ -15,7 +15,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; diff --git a/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/CustomMachine.java b/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/CustomMachine.java index 6732157..acaf8b0 100644 --- a/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/CustomMachine.java +++ b/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/CustomMachine.java @@ -16,7 +16,6 @@ import java.util.LinkedHashMap; import java.util.List; - /** * The {@link CustomMachine} class is a generified * {@link AContainer}. @@ -34,10 +33,13 @@ public class CustomMachine extends AContainer implements RecipeDisplayItem { private final ItemStack progressItem; private final int energyConsumption; private final int energyBuffer; + + // Changed to double to support decimal multipliers + private final double speed; private final LinkedHashMap, Integer> customRecipes; public CustomMachine(ItemGroup category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, - String id, Material progressItem, int energyConsumption, int energyBuffer, + String id, Material progressItem, int energyConsumption, int energyBuffer, double speed, LinkedHashMap, Integer> customRecipes) { super(category, item, recipeType, recipe); @@ -45,6 +47,7 @@ public CustomMachine(ItemGroup category, SlimefunItemStack item, RecipeType reci this.progressItem = new ItemStack(progressItem); this.energyConsumption = energyConsumption; this.energyBuffer = energyBuffer; + this.speed = speed; this.customRecipes = customRecipes; getMachineProcessor().setProgressBar(getProgressBar()); @@ -70,19 +73,31 @@ public int getEnergyConsumption() { @Override public int getSpeed() { + // We return 1 here because we handle the speed calculation + // directly in the recipe registration below. return 1; } + + // Helper method to get the raw multiplier if needed + public double getSpeedMultiplier() { + return speed; + } @Override protected void registerDefaultRecipes() { - if (customRecipes == null) { - return; - } - - customRecipes.forEach((recipe, time) -> - registerRecipe(time, recipe.getFirstValue().clone(), recipe.getSecondValue().clone()) - ); - + if (customRecipes == null) return; + + customRecipes.forEach((recipe, time) -> { + // Calculate new time: Base Time / Speed Multiplier + // Example: 10s / 2.0 = 5s (Faster) + // Example: 10s / 0.5 = 20s (Slower) + int finalTime = (int) (time / speed); + + // Ensure time is at least 1 second + if (finalTime < 1) finalTime = 1; + + registerRecipe(finalTime, recipe.getFirstValue().clone(), recipe.getSecondValue().clone()); + }); } @Override @@ -111,4 +126,4 @@ public List getDisplayRecipes() { public String getMachineIdentifier() { return id; } -} +} \ No newline at end of file diff --git a/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/CustomSCItem.java b/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/CustomSCItem.java index ab99691..5f8d5f6 100644 --- a/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/CustomSCItem.java +++ b/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/CustomSCItem.java @@ -1,9 +1,9 @@ package io.ncbpfluffybear.slimecustomizer.objects; -import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; -import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; +import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; +import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import org.bukkit.inventory.ItemStack; /** @@ -15,10 +15,19 @@ public class CustomSCItem extends SlimefunItem { public CustomSCItem(ItemGroup category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack output) { - super(category, item, recipeType, recipe, output); + // Force the template item to 1 to satisfy Slimefun's registry checks. + super(category, fixStackSize(item), recipeType, recipe, output); } public CustomSCItem(ItemGroup category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { - super(category, item, recipeType, recipe); + // Clone the item to preserve the original stack size (e.g., 6) for the recipe output, + // while the main item gets sanitized to 1 by the primary constructor. + this(category, item, recipeType, recipe, item.clone().item()); + } + + // Quick fix: Slimefun warns if the base item stack size is > 1. + private static SlimefunItemStack fixStackSize(SlimefunItemStack item) { + item.setAmount(1); + return item; } -} +} \ No newline at end of file diff --git a/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/NPCustomSCItem.java b/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/NPCustomSCItem.java index bfb513c..64824f9 100644 --- a/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/NPCustomSCItem.java +++ b/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/NPCustomSCItem.java @@ -4,7 +4,6 @@ import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; -import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable; import org.bukkit.inventory.ItemStack; /** @@ -16,10 +15,20 @@ public class NPCustomSCItem extends SlimefunItem implements SCNotPlaceable { public NPCustomSCItem(ItemGroup category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack output) { - super(category, item, recipeType, recipe, output); + // Force the template item to 1 to satisfy Slimefun's registry checks. + // The actual desired amount is handled via the 'output' parameter. + super(category, fixStackSize(item), recipeType, recipe, output); } public NPCustomSCItem(ItemGroup category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { - super(category, item, recipeType, recipe); + // Clone the item to preserve the original stack size (e.g., 6) for the recipe output, + // while the main item gets sanitized to 1 by the primary constructor. + this(category, item, recipeType, recipe, item.clone().item()); } -} + + // Quick fix: Slimefun warns if the base item stack size is > 1. + private static SlimefunItemStack fixStackSize(SlimefunItemStack item) { + item.setAmount(1); + return item; + } +} \ No newline at end of file diff --git a/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/SCAGenerator.java b/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/SCAGenerator.java index 28deb85..d7ffef3 100644 --- a/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/SCAGenerator.java +++ b/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/SCAGenerator.java @@ -25,8 +25,8 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset; import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow; +import io.github.thebusybiscuit.slimefun4.libraries.commons.lang.Validate; import io.github.thebusybiscuit.slimefun4.libraries.dough.items.CustomItemStack; -import org.apache.commons.lang.Validate; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; diff --git a/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/SCMachine.java b/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/SCMachine.java index fc80c77..8b6e475 100644 --- a/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/SCMachine.java +++ b/src/main/java/io/ncbpfluffybear/slimecustomizer/objects/SCMachine.java @@ -1,7 +1,11 @@ + package io.ncbpfluffybear.slimecustomizer.objects; import dev.j3fftw.extrautils.utils.LoreBuilderDynamic; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; +import io.github.thebusybiscuit.slimefun4.utils.LoreBuilder; +import io.github.thebusybiscuit.slimefun4.core.attributes.MachineTier; +import io.github.thebusybiscuit.slimefun4.core.attributes.MachineType; import io.ncbpfluffybear.slimecustomizer.Utils; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; @@ -11,13 +15,13 @@ import org.bukkit.inventory.meta.ItemMeta; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.stream.Collectors; import java.util.stream.Stream; /** - * This class encompasses all machines and generators. + * Handles custom machines and generators. * * @author NCBPFluffyBear */ @@ -34,168 +38,173 @@ public class SCMachine { private int energyConsumption = 0; private int energyProduction = 0; private int energyBuffer = 0; + + // Internal stats + // Speed is a double to allow for decimal modifiers (e.g. 0.5x or 1.5x) + private double speed = 1.0; + private MachineTier tier = MachineTier.MEDIUM; + private final ItemStack[] recipe; private final RecipeType recipeType; private SlimefunItemStack machineStack; - public SCMachine(Config config, String key, String machineType) { this.config = config; this.key = key; + + // Load base config values materialString = config.getString(key + ".block-type").toUpperCase(); progressItem = Material.getMaterial(config.getString(key + ".progress-bar-item").toUpperCase()); this.machineType = machineType; - validateMachineSettings(); + validate(); Utils.updateCraftingRecipeFormat(config, key); Utils.updateCategoryFormat(config, key); + recipeType = Utils.getRecipeType(config.getString(key + ".crafting-recipe-type"), key); - if (recipeType == null) {valid = false;} + if (recipeType == null) valid = false; + recipe = Utils.buildCraftingRecipe(config, key, recipeType); - if (recipe == null) {valid = false;} - buildMachineStack(); + if (recipe == null) valid = false; + + if (valid) { + buildStack(); + } } - private void validateMachineSettings() { - /* Machine block type */ + private void validate() { + // Ensure the block type is valid Material material = Material.getMaterial(materialString); if ((material == null || !material.isBlock()) && !materialString.startsWith("SKULL")) { - Utils.disable("The block-type for " + key + " MUST be a block!"); + Utils.disable("Block-type for " + key + " must be a valid block."); + valid = false; } else if (material != null && material.isBlock()) { block = new ItemStack(material); } else if (materialString.startsWith("SKULL")) { block = SlimefunUtils.getCustomHead(materialString.replace("SKULL", "").toLowerCase()); } - /* Progress bar type */ + // Ensure progress bar item is valid if (progressItem == null) { - Utils.disable("The progress-bar-item for " + key + " is not a valid vanilla ID!"); + Utils.disable("Invalid progress-bar-item for " + key); + valid = false; + } + + // Parse Machine Tier from config + if (config.getConfiguration().contains(key + ".tier")) { + String tierName = config.getString(key + ".tier").toUpperCase(Locale.ROOT); + try { + this.tier = MachineTier.valueOf(tierName); + } catch (IllegalArgumentException e) { + // Fallback for common aliases or typos in the config + if (tierName.contains("BASIC")) this.tier = MachineTier.BASIC; + else if (tierName.contains("ADVANCED")) this.tier = MachineTier.ADVANCED; + else if (tierName.contains("END")) this.tier = MachineTier.END_GAME; + else if (tierName.contains("GOOD")) this.tier = MachineTier.GOOD; + else if (tierName.contains("AVG")) this.tier = MachineTier.AVERAGE; + else this.tier = MachineTier.MEDIUM; + } } if (machineType.equalsIgnoreCase("machine")) { - /* Energy consumption and Energy buffer */ try { energyConsumption = Integer.parseInt(config.getString(key + ".stats.energy-consumption")); energyBuffer = Integer.parseInt(config.getString(key + ".stats.energy-buffer")); + + // Load speed as double to support decimals + this.speed = config.getConfiguration().getDouble(key + ".stats.speed", 1.0); + } catch (NumberFormatException e) { - Utils.disable("The energy-consumption and energy-buffer for " + key + " must be a positive integer!"); + Utils.disable("Stats for " + key + " must be valid numbers."); + valid = false; } - if (energyConsumption < 0 || energyBuffer < 0) { - Utils.disable("The energy-consumption and energy-buffer for " + key + " must be a positive integer!"); + // Sanity check: Energy stats cannot be negative, and speed must be > 0 + if (energyConsumption < 0 || energyBuffer < 0 || speed <= 0) { + Utils.disable("Stats for " + key + " cannot be negative (and speed must be greater than 0)."); + valid = false; } } else if (machineType.equalsIgnoreCase("generator")) { - /* Energy production and Energy buffer */ try { energyProduction = Integer.parseInt(config.getString(key + ".stats.energy-production")); energyBuffer = Integer.parseInt(config.getString(key + ".stats.energy-buffer")); } catch (NumberFormatException e) { - Utils.disable("The energy-consumption and energy-buffer for " + key + " must be a positive integer!"); + Utils.disable("Generator stats for " + key + " must be integers."); + valid = false; } if (energyProduction < 0 || energyBuffer < 0) { - Utils.disable("The energy-production and energy-buffer for " + key + " must be a positive integer!"); + Utils.disable("Generator stats for " + key + " cannot be negative."); + valid = false; } } - } - private void buildMachineStack() { - // Check and update if the old lore system is still being used + private void buildStack() { + if (!valid) return; + Utils.updateLoreFormat(config, key, machineType); - // Building lore + List statsLore = new ArrayList<>(); + + if (machineType.equalsIgnoreCase("machine")) { + statsLore.add(""); + // Construct visual stats for the lore + statsLore.add(LoreBuilder.machine(this.tier, MachineType.MACHINE)); + + // Cast double to float here because LoreBuilder expects a float + statsLore.add(LoreBuilder.speed((float) this.speed)); + + statsLore.add(LoreBuilderDynamic.powerPerTick(getEnergyExchange())); + // Manually add the buffer capacity line + statsLore.add(LoreBuilder.powerBuffer(energyBuffer)); + } else { + // Visual stats for generator + statsLore.add(""); + // [UPDATED] Add Tier display for Generators too + statsLore.add(LoreBuilder.machine(this.tier, MachineType.GENERATOR)); + statsLore.add(LoreBuilder.powerBuffer(energyBuffer)); + // Show Base Energy. The actual output multiplier is shown in the recipe view in CustomGenerator + statsLore.add(LoreBuilderDynamic.powerPerTick(getEnergyExchange())); + } + + // Pull custom lore lines from config if they exist + List loreFromConfig = config.getConfiguration().getStringList(key + "." + machineType + "-lore"); + + // Merge config lore with generated stats lore List itemLore = Utils.colorList(Stream.concat( - config.getStringList(key + "." + machineType + "-lore").stream(), - new ArrayList<>(Arrays.asList("", getMachineTag(), - LoreBuilderDynamic.powerBuffer(energyBuffer), - LoreBuilderDynamic.powerPerTick(getEnergyExchange()))).stream() + loreFromConfig != null ? loreFromConfig.stream() : Stream.empty(), + statsLore.stream() ).collect(Collectors.toList())); - // Two types of tempStacks for and without skull textures machineStack = new SlimefunItemStack(key, block, config.getString(key + "." + machineType + "-name")); - // Adding lore ItemMeta tempMeta = machineStack.getItemMeta(); - tempMeta.setLore(itemLore); - machineStack.setItemMeta(tempMeta); + if (tempMeta != null) { + tempMeta.setLore(itemLore); + machineStack.setItemMeta(tempMeta); + } } - private String getMachineTag() { - if (machineType.equalsIgnoreCase("machine")) { - return "&b" + Utils.capitalize(machineType); - } else if (machineType.equalsIgnoreCase("generator")) { - return "&a" + Utils.capitalize(machineType); - } + // --- Getters --- - return null; - } + public double getSpeed() { return speed; } + + public MachineTier getTier() { return tier; } - /** - * Returns the energy production or consumption - * based on the machineType - * - * @return energy the energy generated or consumed - */ private int getEnergyExchange() { - if (machineType.equalsIgnoreCase("machine")) { - return energyConsumption; - } else if (machineType.equalsIgnoreCase("generator")) { - return energyProduction; - } - + if (machineType.equalsIgnoreCase("machine")) return energyConsumption; + if (machineType.equalsIgnoreCase("generator")) return energyProduction; return 0; } - public Material getProgressItem() { - return progressItem; - } - - /** - * Returns the energy production - * Only relevant for generators - * - * @return energyProduction the energy production - */ - public int getEnergyProduction() { - return energyProduction; - } - - /** - * Returns the energy consumption - * Only relevant for machines - * - * @return energyConsumption the energy consumption - */ - public int getEnergyConsumption() { - return energyConsumption; - } - - /** - * Returns the energy buffer - * Relevant for both generators and machines - * - * @return energyBuffer the energy buffer - */ - public int getEnergyBuffer() { - return energyBuffer; - } - - public ItemStack[] getRecipe() { - return recipe; - } - - public SlimefunItemStack getMachineStack() { - return machineStack; - } - - public RecipeType getRecipeType() { - return recipeType; - } - - public boolean isValid() { - return valid; - } - + public Material getProgressItem() { return progressItem; } + public int getEnergyProduction() { return energyProduction; } + public int getEnergyConsumption() { return energyConsumption; } + public int getEnergyBuffer() { return energyBuffer; } + public ItemStack[] getRecipe() { return recipe; } + public SlimefunItemStack getMachineStack() { return machineStack; } + public RecipeType getRecipeType() { return recipeType; } + public boolean isValid() { return valid; } } diff --git a/src/main/java/io/ncbpfluffybear/slimecustomizer/registration/Machines.java b/src/main/java/io/ncbpfluffybear/slimecustomizer/registration/Machines.java index 09b9c23..10fc1d0 100644 --- a/src/main/java/io/ncbpfluffybear/slimecustomizer/registration/Machines.java +++ b/src/main/java/io/ncbpfluffybear/slimecustomizer/registration/Machines.java @@ -204,10 +204,15 @@ public static boolean register(Config machines) { } + // Added 'machine.getSpeed()' to the constructor new CustomMachine(category, machine.getMachineStack(), machine.getRecipeType(), machine.getRecipe(), - machineKey, machine.getProgressItem(), machine.getEnergyConsumption(), machine.getEnergyBuffer(), + machineKey, + machine.getProgressItem(), + machine.getEnergyConsumption(), + machine.getEnergyBuffer(), + machine.getSpeed(), customRecipe).register(SlimeCustomizer.getInstance()); Utils.notify("Machine " + machineKey + " has been registered!"); @@ -217,4 +222,4 @@ public static boolean register(Config machines) { return true; } -} +} \ No newline at end of file diff --git a/src/main/resources/generators.yml b/src/main/resources/generators.yml index d200a65..769ad5e 100644 --- a/src/main/resources/generators.yml +++ b/src/main/resources/generators.yml @@ -4,11 +4,18 @@ EXAMPLE_GENERATOR: generator-name: "&bExample Generator" generator-lore: - "&7This is an example generator!" + + # [NEW] Set the Tier here (Optional). Default is MEDIUM. + # Options: BASIC, GOOD, MEDIUM, AVERAGE, ADVANCED, END_GAME + tier: BASIC + block-type: SKULLe707c7f6c3a056a377d4120028405fdd09acfcd5ae804bfde0f653be866afe39 progress-bar-item: FLINT_AND_STEEL + stats: energy-production: 16 energy-buffer: 64 + crafting-recipe-type: ENHANCED_CRAFTING_TABLE crafting-recipe: 1: diff --git a/src/main/resources/machines.yml b/src/main/resources/machines.yml index 016bf14..f0e21c6 100644 --- a/src/main/resources/machines.yml +++ b/src/main/resources/machines.yml @@ -1,14 +1,31 @@ -#READ THE WIKI BEFORE CREATING A MACHINE! https://github.com/NCBPFluffyBear/SlimeCustomizer/blob/master/README.md +# READ THE WIKI BEFORE CREATING A MACHINE! https://github.com/NCBPFluffyBear/SlimeCustomizer/blob/master/README.md + EXAMPLE_MACHINE: category: slime_customizer machine-name: "&bExample Machine" + + # [NEW FEATURE] TIER SETTING + # Define the rarity/tier label displayed at the top of the item lore. + # Available options: BASIC, AVERAGE, MEDIUM, GOOD, ADVANCED, END_GAME + # If removed or invalid, it defaults to MEDIUM. + tier: MEDIUM + machine-lore: - "&7This is an example machine!" block-type: FURNACE progress-bar-item: FLINT_AND_STEEL + stats: energy-consumption: 16 energy-buffer: 64 + + # [NEW FEATURE] SPEED MULTIPLIER + # Determines how fast the machine processes items compared to the base time. + # 1 = Normal Speed (1x) + # 2 = Double Speed (2x) + # 64 = Instant (64x) + speed: 1 + crafting-recipe-type: ENHANCED_CRAFTING_TABLE crafting-recipe: 1: @@ -47,8 +64,11 @@ EXAMPLE_MACHINE: type: VANILLA id: IRON_BLOCK amount: 1 + recipes: 1: + # This is the BASE duration. + # If 'speed' in stats is 2, this 5 seconds becomes 2.5 seconds. speed-in-seconds: 5 input: 1: From 2571e21b52f18c9779ab9e3ed01872a8ed4cc835 Mon Sep 17 00:00:00 2001 From: Eygwi <245492840+eygwi@users.noreply.github.com> Date: Mon, 22 Dec 2025 21:52:16 +0700 Subject: [PATCH 2/3] bruh --- .vscode/settings.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 6a1a780..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "commentTranslate.hover.enabled": false -} \ No newline at end of file From 76dcec8a354c5bf4a7167944126895e8e4e17ffc Mon Sep 17 00:00:00 2001 From: Eygwi <245492840+eygwi@users.noreply.github.com> Date: Tue, 23 Dec 2025 05:34:25 +0700 Subject: [PATCH 3/3] fix(core): resolve crash in categories menu and add pagination --- .../slimecustomizer/SlimeCustomizer.java | 100 ++++++++++++++---- 1 file changed, 79 insertions(+), 21 deletions(-) diff --git a/src/main/java/io/ncbpfluffybear/slimecustomizer/SlimeCustomizer.java b/src/main/java/io/ncbpfluffybear/slimecustomizer/SlimeCustomizer.java index 99463d3..79c1b56 100644 --- a/src/main/java/io/ncbpfluffybear/slimecustomizer/SlimeCustomizer.java +++ b/src/main/java/io/ncbpfluffybear/slimecustomizer/SlimeCustomizer.java @@ -263,27 +263,11 @@ public boolean onCommand(CommandSender sender, Command command, String label, St return true; } - SCMenu menu = new SCMenu("&6Category Namespace Guide"); - menu.setSize(54); - int slot = 0; - for (ItemGroup group : Slimefun.getRegistry().getAllItemGroups()) { - ItemStack catItem = group.getItem(p).clone(); - ItemMeta catMeta = catItem.getItemMeta(); - List catLore = catMeta.getLore(); - - catLore.set(catLore.size() - 1, Utils.color( - "&6ID: " + group.getKey().getNamespace() + ":" + group.getKey().getKey()) - ); // Replaces the "Click to Open" line - catMeta.setLore(catLore); - catItem.setItemMeta(catMeta); - menu.replaceExistingItem(slot, catItem); - menu.addMenuClickHandler(slot, ChestMenuUtils.getEmptyClickHandler()); - slot++; - } + // --- FIXED: Use pagination logic instead of dumping everything into one GUI --- + List allGroups = new ArrayList<>(Slimefun.getRegistry().getAllItemGroups()); + openCategoriesMenu(p, allGroups, 1); + // ---------------------------------------------------------------------------- - menu.setPlayerInventoryClickable(false); - menu.setBackgroundNonClickable(true); - menu.open(p); } else { Utils.send(sender, "&eAll commands can be found at &9" + Links.COMMANDS); } @@ -355,6 +339,80 @@ private void populateMenu(SCMenu menu, List> items, int } + /** + * Handles the pagination for the categories menu. + * Prevents IndexOutOfBoundsException when there are too many Slimefun addons. + * + * @param p The player + * @param groups The list of all item groups + * @param page The current page number + */ + private void openCategoriesMenu(Player p, List groups, int page) { + SCMenu menu = new SCMenu("&6Category Namespace Guide (Page " + page + ")"); + menu.setSize(54); + + int itemsPerPage = 45; + int startIndex = (page - 1) * itemsPerPage; + int endIndex = Math.min(startIndex + itemsPerPage, groups.size()); + + int slot = 0; + + for (int i = startIndex; i < endIndex; i++) { + ItemGroup group = groups.get(i); + ItemStack catItem = group.getItem(p).clone(); + ItemMeta catMeta = catItem.getItemMeta(); + + if (catMeta != null) { + List catLore = catMeta.getLore(); + if (catLore == null) { + catLore = new ArrayList<>(); + } + + String namespaceInfo = Utils.color("&6ID: " + group.getKey().getNamespace() + ":" + group.getKey().getKey()); + + if (!catLore.isEmpty()) { + catLore.set(catLore.size() - 1, namespaceInfo); + } else { + catLore.add(namespaceInfo); + } + catMeta.setLore(catLore); + catItem.setItemMeta(catMeta); + } + + menu.replaceExistingItem(slot, catItem); + menu.addMenuClickHandler(slot, ChestMenuUtils.getEmptyClickHandler()); + slot++; + } + + // Navigation Buttons + if (page > 1) { + menu.replaceExistingItem(46, CustomItemStack.create(Material.LIME_STAINED_GLASS_PANE, "&aPrevious Page")); + menu.addMenuClickHandler(46, (pl, s, is, action) -> { + openCategoriesMenu(p, groups, page - 1); + return false; + }); + } + + if (endIndex < groups.size()) { + menu.replaceExistingItem(52, CustomItemStack.create(Material.LIME_STAINED_GLASS_PANE, "&aNext Page")); + menu.addMenuClickHandler(52, (pl, s, is, action) -> { + openCategoriesMenu(p, groups, page + 1); + return false; + }); + } + + // Fill background for non-navigation slots in the bottom row + for (int i = 45; i < 54; i++) { + if (i != 46 && i != 52) { + menu.replaceExistingItem(i, ChestMenuUtils.getBackground()); + } + } + + menu.setPlayerInventoryClickable(false); + menu.setBackgroundNonClickable(true); + menu.open(p); + } + private ItemStack getItemOrNull(List> items, int index) { ItemStack item; try { @@ -399,4 +457,4 @@ public static SlimeCustomizer getInstance() { return instance; } -} +} \ No newline at end of file