From fd16306b6108d785d7f92c2c2d861e5043353e70 Mon Sep 17 00:00:00 2001 From: TheBusyBiscuit Date: Sat, 27 Mar 2021 22:26:15 +0100 Subject: [PATCH] Auto-Crafters can now be turned on and off via the gui --- CHANGELOG.md | 1 + .../autocrafters/AbstractAutoCrafter.java | 87 ++++++++++++++++--- .../items/autocrafters/AbstractRecipe.java | 26 ++++++ .../autocrafters/SlimefunAutoCrafter.java | 11 ++- .../autocrafters/VanillaAutoCrafter.java | 20 +++-- .../slimefun4/utils/HeadTexture.java | 3 +- src/main/resources/languages/messages_en.yml | 17 +++- 7 files changed, 137 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0b26d83c..a65e0cd63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ * Added "Smart-Filling" mode to Cargo Input nodes * Added "Netherite Ingot -> Netherite Block" recipe to Electric Press * Added Armor Forge Auto Crafter +* Auto-Crafters can now be turned on and off #### Changes * Removed all functionality from the old Automated Crafting Chamber diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/AbstractAutoCrafter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/AbstractAutoCrafter.java index 2dea241be..01342fc05 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/AbstractAutoCrafter.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/AbstractAutoCrafter.java @@ -9,7 +9,6 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import org.apache.commons.lang.Validate; -import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -35,6 +34,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.listeners.AutoCrafterListener; import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask; import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils; +import io.github.thebusybiscuit.slimefun4.utils.HeadTexture; import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; import io.papermc.lib.PaperLib; import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult; @@ -73,6 +73,11 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy */ protected final NamespacedKey recipeStorageKey; + /** + * The {@link NamespacedKey} used to determine whether the recipe is enabled. + */ + protected final NamespacedKey recipeEnabledKey; + // @formatter:off protected final int[] background = { 0, 1, 2, 3, 4, 5, 6, 7, 8, @@ -88,6 +93,7 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy super(category, item, recipeType, recipe); recipeStorageKey = new NamespacedKey(SlimefunPlugin.instance(), "recipe_key"); + recipeEnabledKey = new NamespacedKey(SlimefunPlugin.instance(), "recipe_enabled"); addItemHandler(new BlockTicker() { @@ -142,19 +148,28 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy } } + /** + * This method performs one tick for the {@link AbstractAutoCrafter}. + * + * @param b + * The block for this {@link AbstractAutoCrafter} + * @param data + * The data stored on this block + */ protected void tick(@Nonnull Block b, @Nonnull Config data) { AbstractRecipe recipe = getSelectedRecipe(b); - if (recipe == null || getCharge(b.getLocation(), data) < getEnergyConsumption()) { - // No valid recipe selected, abort... + if (recipe == null || !recipe.isEnabled() || getCharge(b.getLocation(), data) < getEnergyConsumption()) { + // No recipe / disabled recipe / no energy, abort... return; } - Block chest = b.getRelative(BlockFace.DOWN); + // The block below where we would expect our inventory holder. + Block targetBlock = b.getRelative(BlockFace.DOWN); // Make sure this is a Chest - if (isValidInventory(chest)) { - BlockState state = PaperLib.getBlockState(chest, false).getState(); + if (isValidInventory(targetBlock)) { + BlockState state = PaperLib.getBlockState(targetBlock, false).getState(); if (state instanceof InventoryHolder) { Inventory inv = ((InventoryHolder) state).getInventory(); @@ -236,6 +251,9 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy if (recipe == null) { // Clear the value from persistent data storage PersistentDataAPI.remove((Skull) state, recipeStorageKey); + + // Also remove the "enabled" state since this should be per-recipe. + PersistentDataAPI.remove((Skull) state, recipeEnabledKey); } else { // Store the value to persistent data storage PersistentDataAPI.setString((Skull) state, recipeStorageKey, recipe.toString()); @@ -271,14 +289,29 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy ChestMenuUtils.drawBackground(menu, background); ChestMenuUtils.drawBackground(menu, 45, 46, 47, 48, 50, 51, 52, 53); - menu.addItem(49, new CustomItem(Material.BARRIER, ChatColor.RED + SlimefunPlugin.getLocalization().getMessage(p, "messages.auto-crafting.remove"))); - menu.addMenuClickHandler(49, (pl, item, slot, action) -> { - setSelectedRecipe(b, null); - pl.closeInventory(); - p.playSound(p.getLocation(), Sound.UI_BUTTON_CLICK, 1, 1); - SlimefunPlugin.getLocalization().sendMessage(p, "messages.auto-crafting.recipe-removed"); - return false; - }); + if (recipe.isEnabled()) { + menu.addItem(49, new CustomItem(Material.BARRIER, SlimefunPlugin.getLocalization().getMessages(p, "messages.auto-crafting.tooltips.enabled"))); + menu.addMenuClickHandler(49, (pl, item, slot, action) -> { + if (action.isRightClicked()) { + deleteRecipe(pl, b); + } else { + setRecipeEnabled(pl, b, false); + } + + return false; + }); + } else { + menu.addItem(49, new CustomItem(HeadTexture.EXCLAMATION_MARK.getAsItemStack(), SlimefunPlugin.getLocalization().getMessages(p, "messages.auto-crafting.tooltips.disabled"))); + menu.addMenuClickHandler(49, (pl, item, slot, action) -> { + if (action.isRightClicked()) { + deleteRecipe(pl, b); + } else { + setRecipeEnabled(pl, b, true); + } + + return false; + }); + } // This makes the slots cycle through different ingredients AsyncRecipeChoiceTask task = new AsyncRecipeChoiceTask(); @@ -293,6 +326,32 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy } } + @ParametersAreNonnullByDefault + private void setRecipeEnabled(Player p, Block b, boolean enabled) { + p.closeInventory(); + p.playSound(p.getLocation(), Sound.UI_BUTTON_CLICK, 1, 1); + BlockState state = PaperLib.getBlockState(b, false).getState(); + + // Make sure the block is still a Skull + if (state instanceof Skull) { + if (enabled) { + PersistentDataAPI.remove((Skull) state, recipeEnabledKey); + SlimefunPlugin.getLocalization().sendMessage(p, "messages.auto-crafting.re-enabled"); + } else { + PersistentDataAPI.setByte((Skull) state, recipeEnabledKey, (byte) 1); + SlimefunPlugin.getLocalization().sendMessage(p, "messages.auto-crafting.temporarily-disabled"); + } + } + } + + @ParametersAreNonnullByDefault + private void deleteRecipe(Player p, Block b) { + setSelectedRecipe(b, null); + p.closeInventory(); + p.playSound(p.getLocation(), Sound.UI_BUTTON_CLICK, 1, 1); + SlimefunPlugin.getLocalization().sendMessage(p, "messages.auto-crafting.recipe-removed"); + } + /** * This method checks whether the given {@link Predicate} matches the provided {@link ItemStack}. * diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/AbstractRecipe.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/AbstractRecipe.java index 1a8b23f01..c1444d7cc 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/AbstractRecipe.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/AbstractRecipe.java @@ -44,6 +44,11 @@ public abstract class AbstractRecipe { */ private final ItemStack result; + /** + * Whether this recipe is enabled. + */ + private boolean enabled; + /** * Protected constructor. For implementation classes only. * @@ -83,6 +88,27 @@ public abstract class AbstractRecipe { return result; } + /** + * This returns whether or not this recipe has been enabled. + * A disabled recipe will not be crafted. + * + * @return Whether this recipe is enabled + */ + public boolean isEnabled() { + return enabled; + } + + /** + * This method enables or disables this recipe. + * A disabled recipe will not be crafted. + * + * @param enabled + * Whether this recipe is enabled + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + /** * This will visually represent this {@link AbstractRecipe} in the given {@link ChestMenu}. * Any {@link MaterialChoice} will be cycled through using the {@link AsyncRecipeChoiceTask}. diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/SlimefunAutoCrafter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/SlimefunAutoCrafter.java index 0a7cfb83b..d42fd1b9e 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/SlimefunAutoCrafter.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/SlimefunAutoCrafter.java @@ -13,8 +13,9 @@ import org.bukkit.block.BlockState; import org.bukkit.block.Skull; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; -import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI; import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask; @@ -60,11 +61,15 @@ public class SlimefunAutoCrafter extends AbstractAutoCrafter { if (state instanceof Skull) { // Read the stored value from persistent data storage - String value = PersistentDataAPI.getString((Skull) state, recipeStorageKey); + PersistentDataContainer container = ((Skull) state).getPersistentDataContainer(); + String value = container.get(recipeStorageKey, PersistentDataType.STRING); SlimefunItem item = SlimefunItem.getByID(value); if (item != null) { - return AbstractRecipe.of(item, targetRecipeType); + boolean enabled = !container.has(recipeEnabledKey, PersistentDataType.BYTE); + AbstractRecipe recipe = AbstractRecipe.of(item, targetRecipeType); + recipe.setEnabled(enabled); + return recipe; } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/VanillaAutoCrafter.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/VanillaAutoCrafter.java index 0317fff6a..fc1e132a3 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/VanillaAutoCrafter.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/autocrafters/VanillaAutoCrafter.java @@ -21,8 +21,9 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Recipe; import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.ShapelessRecipe; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; -import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI; import io.github.thebusybiscuit.cscorelib2.item.CustomItem; import io.github.thebusybiscuit.slimefun4.core.services.MinecraftRecipeService; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; @@ -58,16 +59,12 @@ public class VanillaAutoCrafter extends AbstractAutoCrafter { @Override @Nullable public AbstractRecipe getSelectedRecipe(@Nonnull Block b) { - return AbstractRecipe.of(getRecipe(b)); - } - - @Nullable - private Recipe getRecipe(@Nonnull Block b) { BlockState state = PaperLib.getBlockState(b, false).getState(); if (state instanceof Skull) { // Read the stored value from persistent data storage - String value = PersistentDataAPI.getString((Skull) state, recipeStorageKey); + PersistentDataContainer container = ((Skull) state).getPersistentDataContainer(); + String value = container.get(recipeStorageKey, PersistentDataType.STRING); if (value != null) { String[] values = PatternUtils.COLON.split(value); @@ -79,8 +76,15 @@ public class VanillaAutoCrafter extends AbstractAutoCrafter { */ @SuppressWarnings("deprecation") NamespacedKey key = new NamespacedKey(values[0], values[1]); + Recipe keyedRecipe = SlimefunPlugin.getMinecraftRecipeService().getRecipe(key); - return SlimefunPlugin.getMinecraftRecipeService().getRecipe(key); + if (keyedRecipe != null) { + boolean enabled = !container.has(recipeEnabledKey, PersistentDataType.BYTE); + AbstractRecipe recipe = AbstractRecipe.of(keyedRecipe); + recipe.setEnabled(enabled); + + return recipe; + } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java index 337fd8d3b..7a76dc2f1 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/utils/HeadTexture.java @@ -115,7 +115,8 @@ public enum HeadTexture { NECROTIC_SKULL("7953b6c68448e7e6b6bf8fb273d7203acd8e1be19e81481ead51f45de59a8"), VANILLA_AUTO_CRAFTER("80a4334f6a61e40c0c63deb665fa7b581e6eb259f7a3207ced7a1ff8bdc8a9f9"), ENHANCED_AUTO_CRAFTER("5038298306a5e28584df39e88896917c38d40a326226d8c83070723c95798b24"), - ARMOR_AUTO_CRAFTER("5cbd9f5ec1ed007259996491e69ff649a3106cf920227b1bb3a71ee7a89863f"); + ARMOR_AUTO_CRAFTER("5cbd9f5ec1ed007259996491e69ff649a3106cf920227b1bb3a71ee7a89863f"), + EXCLAMATION_MARK("2e3f50ba62cbda3ecf5479b62fedebd61d76589771cc19286bf2745cd71e47c6"); private final String texture; private final UUID uuid; diff --git a/src/main/resources/languages/messages_en.yml b/src/main/resources/languages/messages_en.yml index 40403c4c3..9a3e1840b 100644 --- a/src/main/resources/languages/messages_en.yml +++ b/src/main/resources/languages/messages_en.yml @@ -151,9 +151,22 @@ messages: recipe-set: '&aYou have successfully set the recipe for this machine.' recipe-removed: '&eYou have successfully removed the recipe from this machine. You can set a new recipe at any time!' no-recipes: '&cWe could not find any valid recipes for the item you are holding.' - missing-chest: '&cMissing chest! Auto Crafters need to be placed above a chest.' + missing-chest: '&cMissing chest! Auto-Crafters need to be placed above a chest.' select: 'Select this recipe' - remove: 'Remove this recipe' + temporarily-disabled: '&eThis Auto-Crafter was temporarily disabled. You can re-enable it at any time!' + re-enabled: '&eThis Auto-Crafter was re-enabled!' + + tooltips: + enabled: + - '&aThis recipe is currently enabled' + - '' + - '&eLeft Click &7to temporarily disable the recipe' + - '&eRight Click &7to remove this recipe' + disabled: + - '&cThis recipe is currently disabled' + - '' + - '&eLeft Click &7to re-enable this recipe' + - '&eRight Click &7to remove this recipe' talisman: anvil: '&a&oYour Talisman saved your tool from breaking'