From 4cb630d201bbae23e999894f0a3a37e63fbda8d4 Mon Sep 17 00:00:00 2001 From: Auxilor Date: Tue, 1 Mar 2022 10:24:38 +0000 Subject: [PATCH] Fixed crafting, deprecated now-unneeded API --- .../recipe/parts/GroupedTestableItems.java | 17 +++ .../recipe/parts/MaterialTestableItem.java | 9 +- .../java/com/willfp/eco/util/BlockUtils.java | 34 +----- .../spigot/proxy/v1_17_R1/BlockBreak.kt | 14 --- .../spigot/proxy/v1_18_R1/BlockBreak.kt | 14 --- .../eco/internal/spigot/EcoSpigotPlugin.kt | 9 +- .../spigot/recipes/ShapedRecipeListener.kt | 81 ------------- .../spigot/recipes/StackedRecipeListener.kt | 108 ++++++++++++++++++ .../spigot/recipes/listeners/ComplexInEco.kt | 68 ----------- .../internal/spigot/proxy/BlockBreakProxy.kt | 11 -- 10 files changed, 138 insertions(+), 227 deletions(-) delete mode 100644 eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/BlockBreak.kt delete mode 100644 eco-core/core-nms/v1_18_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_18_R1/BlockBreak.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/StackedRecipeListener.kt delete mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/listeners/ComplexInEco.kt delete mode 100644 eco-core/core-proxy/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/BlockBreakProxy.kt diff --git a/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/GroupedTestableItems.java b/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/GroupedTestableItems.java index 0cc5efd4..82d28baa 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/GroupedTestableItems.java +++ b/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/GroupedTestableItems.java @@ -57,6 +57,23 @@ public class GroupedTestableItems implements TestableItem { throw new IllegalStateException("Empty group of children!"); } + /** + * Get matching child for an ItemStack. + * + * @param itemStack The ItemStack. + * @return The matching child, or null if the item matches nothing. + */ + @Nullable + public TestableItem getMatchingChild(@NotNull final ItemStack itemStack) { + for (TestableItem child : children) { + if (child.matches(itemStack)) { + return child; + } + } + + return null; + } + /** * Get the children. * diff --git a/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/MaterialTestableItem.java b/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/MaterialTestableItem.java index a791f05e..e0d474a2 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/MaterialTestableItem.java +++ b/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/MaterialTestableItem.java @@ -1,5 +1,6 @@ package com.willfp.eco.core.recipe.parts; +import com.willfp.eco.core.items.Items; import com.willfp.eco.core.items.TestableItem; import org.apache.commons.lang.Validate; import org.bukkit.Material; @@ -35,7 +36,13 @@ public class MaterialTestableItem implements TestableItem { */ @Override public boolean matches(@Nullable final ItemStack itemStack) { - return itemStack != null && itemStack.getType() == material; + boolean simpleMatches = itemStack != null && itemStack.getType() == material; + + if (!simpleMatches) { + return false; + } + + return !Items.isCustomItem(itemStack); } @Override diff --git a/eco-api/src/main/java/com/willfp/eco/util/BlockUtils.java b/eco-api/src/main/java/com/willfp/eco/util/BlockUtils.java index 24d9081f..6afea843 100644 --- a/eco-api/src/main/java/com/willfp/eco/util/BlockUtils.java +++ b/eco-api/src/main/java/com/willfp/eco/util/BlockUtils.java @@ -1,6 +1,5 @@ package com.willfp.eco.util; -import org.apache.commons.lang.Validate; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; @@ -9,28 +8,16 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; import org.bukkit.persistence.PersistentDataType; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.function.BiConsumer; /** * Utilities / API methods for blocks. */ public final class BlockUtils { - /** - * If the meta set function has been set. - */ - private static boolean initialized = false; - - /** - * The block break function. - */ - private static BiConsumer blockBreakConsumer = null; - private static Set getNearbyBlocks(@NotNull final Block start, @NotNull final List allowedMaterials, @NotNull final Set blocks, @@ -75,12 +62,11 @@ public final class BlockUtils { * * @param player The player to break the block as. * @param block The block to break. + * @deprecated Added into spigot API in 1.17.1 */ + @Deprecated(since = "6.26.2", forRemoval = true) public static void breakBlock(@NotNull final Player player, @NotNull final Block block) { - Validate.isTrue(initialized, "Must be initialized!"); - Validate.notNull(blockBreakConsumer, "Must be initialized!"); - Location location = block.getLocation(); World world = location.getWorld(); assert world != null; @@ -89,7 +75,7 @@ public final class BlockUtils { return; } - blockBreakConsumer.accept(player, block); + player.breakBlock(block); } /** @@ -107,20 +93,6 @@ public final class BlockUtils { ); } - /** - * Initialize the block break function. - * - * @param function The function. - */ - @ApiStatus.Internal - public static void initialize(@NotNull final BiConsumer function) { - Validate.isTrue(!initialized, "Already initialized!"); - - blockBreakConsumer = function; - - initialized = true; - } - private BlockUtils() { throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); } diff --git a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/BlockBreak.kt b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/BlockBreak.kt deleted file mode 100644 index ab03241e..00000000 --- a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/BlockBreak.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.willfp.eco.internal.spigot.proxy.v1_17_R1 - -import com.willfp.eco.internal.spigot.proxy.BlockBreakProxy -import org.bukkit.block.Block -import org.bukkit.entity.Player - -class BlockBreak : BlockBreakProxy { - override fun breakBlock( - player: Player, - block: Block - ) { - player.breakBlock(block) - } -} \ No newline at end of file diff --git a/eco-core/core-nms/v1_18_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_18_R1/BlockBreak.kt b/eco-core/core-nms/v1_18_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_18_R1/BlockBreak.kt deleted file mode 100644 index a8f5ba33..00000000 --- a/eco-core/core-nms/v1_18_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_18_R1/BlockBreak.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.willfp.eco.internal.spigot.proxy.v1_18_R1 - -import com.willfp.eco.internal.spigot.proxy.BlockBreakProxy -import org.bukkit.block.Block -import org.bukkit.entity.Player - -class BlockBreak : BlockBreakProxy { - override fun breakBlock( - player: Player, - block: Block - ) { - player.breakBlock(block) - } -} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt index e4edb715..ffc64e49 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt @@ -106,15 +106,13 @@ import com.willfp.eco.internal.spigot.integrations.mcmmo.McmmoIntegrationImpl import com.willfp.eco.internal.spigot.integrations.multiverseinventories.MultiverseInventoriesIntegration import com.willfp.eco.internal.spigot.integrations.shop.ShopShopGuiPlus import com.willfp.eco.internal.spigot.math.evaluateExpression -import com.willfp.eco.internal.spigot.proxy.BlockBreakProxy import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy import com.willfp.eco.internal.spigot.proxy.SkullProxy import com.willfp.eco.internal.spigot.proxy.TPSProxy import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener +import com.willfp.eco.internal.spigot.recipes.StackedRecipeListener import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInComplex -import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInEco import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInVanilla -import com.willfp.eco.util.BlockUtils import com.willfp.eco.util.NumberUtils import com.willfp.eco.util.ServerUtils import com.willfp.eco.util.SkullUtils @@ -158,7 +156,6 @@ abstract class EcoSpigotPlugin : EcoPlugin() { Entities.registerArgParser(EntityArgParserEquipment()) ShapedRecipeListener.registerListener(ComplexInComplex()) - ShapedRecipeListener.registerListener(ComplexInEco()) ShapedRecipeListener.registerListener(ComplexInVanilla()) SegmentParserGroup().register() @@ -170,9 +167,6 @@ abstract class EcoSpigotPlugin : EcoPlugin() { { meta -> skullProxy.getSkullTexture(meta) } ) - val blockBreakProxy = getProxy(BlockBreakProxy::class.java) - BlockUtils.initialize { player, block -> blockBreakProxy.breakBlock(player, block) } - val tpsProxy = getProxy(TPSProxy::class.java) ServerUtils.initialize { tpsProxy.getTPS() } @@ -322,6 +316,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() { ArmorListener(), EntityDeathByEntityListeners(this), ShapedRecipeListener(), + StackedRecipeListener(this), GUIListener(this), ArrowDataListener(this), ArmorChangeEventListeners(this), diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/ShapedRecipeListener.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/ShapedRecipeListener.kt index 5e295071..18c83085 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/ShapedRecipeListener.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/ShapedRecipeListener.kt @@ -2,95 +2,14 @@ package com.willfp.eco.internal.spigot.recipes import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.recipe.Recipes -import com.willfp.eco.core.recipe.parts.TestableStack import org.bukkit.Keyed import org.bukkit.event.EventHandler -import org.bukkit.event.EventPriority import org.bukkit.event.Listener import org.bukkit.event.inventory.CraftItemEvent import org.bukkit.event.inventory.PrepareItemCraftEvent import org.bukkit.event.player.PlayerRecipeDiscoverEvent -import org.bukkit.inventory.ShapedRecipe class ShapedRecipeListener : Listener { - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - fun stackedRecipeListener(event: CraftItemEvent) { - val recipe = event.recipe as? ShapedRecipe ?: return - - if (!EcoPlugin.getPluginNames().contains(recipe.key.namespace)) { - return - } - - val matrix = event.inventory.matrix - - val wrapped = WrappedCraftItemEvent(event) - - if (validators.any { it.validate(wrapped) }) { - return - } - - val matched = Recipes.getMatch(matrix) - - if (matched == null) { - wrapped.deny() - return - } - - var isStackedRecipe = false - var upperBound = 64 - for (i in 0..8) { - val inMatrix = event.inventory.matrix.getOrNull(i) - val inRecipe = matched.parts[i] - - if (inRecipe is TestableStack) { - val max = Math.floorDiv(inMatrix!!.amount, inRecipe.amount) - if (max < upperBound) { - upperBound = max - } - isStackedRecipe = true - } else if (inMatrix != null) { - val max = inMatrix.amount - if (max < upperBound) { - upperBound = max - } - } - } - - if (!isStackedRecipe) { - return - } - - val toGivePerRecipe = event.recipe.result.amount - val maxStackSize = event.recipe.result.maxStackSize - while (toGivePerRecipe * upperBound > maxStackSize) { - upperBound-- - } - - for (i in 0..8) { - val inMatrix = event.inventory.matrix[i] - val inRecipe = matched.parts[i] - - if (inRecipe is TestableStack) { - if (event.isShiftClick) { - var amount = inMatrix.amount + 1 - for (j in 0..upperBound) { - amount -= inRecipe.amount - } - inMatrix.amount = amount - } else { - inMatrix.amount = inMatrix.amount - (inRecipe.amount - 1) - } - } - } - - if (event.isShiftClick) { - val result = event.inventory.result ?: return - - result.amount = result.amount * upperBound - event.inventory.result = result - } - } - @EventHandler fun preventLearningDisplayedRecipes(event: PlayerRecipeDiscoverEvent) { if (!EcoPlugin.getPluginNames().contains(event.recipe.namespace)) { diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/StackedRecipeListener.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/StackedRecipeListener.kt new file mode 100644 index 00000000..81329e87 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/StackedRecipeListener.kt @@ -0,0 +1,108 @@ +package com.willfp.eco.internal.spigot.recipes + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.recipe.Recipes +import com.willfp.eco.core.recipe.parts.GroupedTestableItems +import com.willfp.eco.core.recipe.parts.TestableStack +import org.bukkit.Bukkit +import org.bukkit.Material +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.inventory.CraftingInventory +import kotlin.math.max +import kotlin.math.min + +class StackedRecipeListener( + private val plugin: EcoPlugin +) : Listener { + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + fun handleStacks(event: InventoryClickEvent) { + val inventory = event.clickedInventory as? CraftingInventory ?: return + if (event.slot != 0) { + return + } + + val matrix = inventory.matrix + + val recipe = Recipes.getMatch(matrix) ?: return + + var isStackedRecipe = false + var maxCraftable = Int.MAX_VALUE + + // Start by calculating the maximum number of items to craft + for (i in 0..8) { + val item = inventory.matrix.getOrNull(i) ?: continue + val part = recipe.parts[i].let { + if (it is GroupedTestableItems) { + it.getMatchingChild(item) + } else it + } ?: continue + + if (part is TestableStack) { + isStackedRecipe = true + } + + maxCraftable = min(maxCraftable, Math.floorDiv(item.amount, part.item.amount)) + } + + if (!isStackedRecipe) { + return + } + + // Don't allow crafting above the max stack size of the output + maxCraftable = min(maxCraftable, Math.floorDiv(recipe.output.maxStackSize, recipe.output.amount)) + + Bukkit.getLogger().info("Amount to craft: $maxCraftable") + + // Deduct the correct number of items from the inventory + for (i in 0..8) { + val item = inventory.matrix.getOrNull(i) ?: continue + val part = recipe.parts[i].let { + if (it is GroupedTestableItems) { + it.getMatchingChild(item) + } else it + } ?: continue + + val amount = max( + if (event.isShiftClick) { + item.amount - (part.item.amount * maxCraftable) + } else { + item.amount - part.item.amount + }, 0 + ) + + println("Setting amount of ${item.type} to $amount") + + // Anti-Underflow + if (amount == 0) { + item.type = Material.AIR + } + item.amount = amount + + val newItem = item.clone() + + // Do it twice because spigot hates me + // Everything has to be cloned because the inventory changes the item + inventory.matrix[i] = item // Use un-cloned version first + plugin.scheduler.run { + println("Setting ${inventory.matrix[i]} to $newItem") + inventory.matrix[i] = newItem + inventory.setItem(i + 1, newItem) + // Just to be safe, modify the instance (safe check) Using ?. causes a warning. + if (inventory.matrix[i] != null) { + inventory.matrix[i].amount = amount + } + } + } + + // Multiply the result by the amount to craft if shift-clicking + if (event.isShiftClick) { + val result = inventory.result ?: return + + result.amount *= maxCraftable + inventory.result = result + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/listeners/ComplexInEco.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/listeners/ComplexInEco.kt deleted file mode 100644 index d115f12f..00000000 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/recipes/listeners/ComplexInEco.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.willfp.eco.internal.spigot.recipes.listeners - -import com.willfp.eco.core.items.Items -import com.willfp.eco.core.items.TestableItem -import com.willfp.eco.core.recipe.Recipes -import com.willfp.eco.core.recipe.parts.GroupedTestableItems -import com.willfp.eco.core.recipe.parts.MaterialTestableItem -import com.willfp.eco.core.recipe.parts.ModifiedTestableItem -import com.willfp.eco.core.recipe.parts.TestableStack -import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe -import com.willfp.eco.internal.spigot.recipes.GenericCraftEvent -import com.willfp.eco.internal.spigot.recipes.RecipeListener -import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener -import org.bukkit.inventory.ItemStack - -class ComplexInEco : RecipeListener { - override fun handle(event: GenericCraftEvent) { - val craftingRecipe = Recipes.getRecipe(event.recipe.key) - - if (craftingRecipe !is ShapedCraftingRecipe) { - return - } - - if (ShapedRecipeListener.validators.any { it.validate(event) }) { - return - } - - for (i in 0..8) { - val itemStack = event.inventory.matrix[i] ?: continue - val part = craftingRecipe.parts[i] - if (part.isCustomWhenShouldNotBe(itemStack)) { - event.deny() - } - } - } -} - -private fun TestableItem.isCustomWhenShouldNotBe(itemStack: ItemStack): Boolean { - when (this) { - is MaterialTestableItem -> { - if (Items.isCustomItem(itemStack)) { - return true - } - } - is ModifiedTestableItem -> { - if (this.handle is MaterialTestableItem) { - if (Items.isCustomItem(itemStack)) { - return true - } - } - } - is TestableStack -> { - if (this.handle is MaterialTestableItem) { - if (Items.isCustomItem(itemStack)) { - return true - } - } - } - is GroupedTestableItems -> { - // This will fail if and only if there is a complex item grouped with a simple item of the same type - if (this.children.any { it.isCustomWhenShouldNotBe(itemStack) && it.matches(itemStack) }) { - return true - } - } - } - - return false -} \ No newline at end of file diff --git a/eco-core/core-proxy/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/BlockBreakProxy.kt b/eco-core/core-proxy/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/BlockBreakProxy.kt deleted file mode 100644 index b3f6c8a4..00000000 --- a/eco-core/core-proxy/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/BlockBreakProxy.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.willfp.eco.internal.spigot.proxy - -import org.bukkit.block.Block -import org.bukkit.entity.Player - -interface BlockBreakProxy { - fun breakBlock( - player: Player, - block: Block - ) -} \ No newline at end of file