Fixed alchemy shift-click exceptions on older MC versions Fixes #5046 Fixes #5039

This commit is contained in:
nossr50 2024-07-13 14:47:42 -07:00
parent 99d8b64589
commit ce8464fcfe
2 changed files with 42 additions and 20 deletions

View File

@ -1,4 +1,5 @@
Version 2.2.017 Version 2.2.017
Fixed shift-clicking ingredients into the brewing stand not working on older versions of Minecraft
Added a setting in advanced.yml to ignore attack cooldowns (see notes) Added a setting in advanced.yml to ignore attack cooldowns (see notes)
Fixed a bug with Mace permissions (thanks SrBedrock) Fixed a bug with Mace permissions (thanks SrBedrock)
Updated zh_CN locale (thanks libook) Updated zh_CN locale (thanks libook)

View File

@ -23,12 +23,29 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
// TODO: Update to use McMMOPlayer // TODO: Update to use McMMOPlayer
public final class AlchemyPotionBrewer { public final class AlchemyPotionBrewer {
/*
* Compatibility with older versions where InventoryView used to be an abstract class and became an interface.
* This was introduced in Minecraft 1.21 if we drop support for versions older than 1.21 this can be removed.
*/
private static final Method getItem, setItem;
static {
try {
final Class<?> clazz = Class.forName("org.bukkit.inventory.InventoryView");
getItem = clazz.getDeclaredMethod("getItem", int.class);
setItem = clazz.getDeclaredMethod("setItem", int.class, ItemStack.class);
} catch (NoSuchMethodException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@Deprecated(forRemoval = true, since = "2.2.010") @Deprecated(forRemoval = true, since = "2.2.010")
public static boolean isValidBrew(Player player, ItemStack[] contents) { public static boolean isValidBrew(Player player, ItemStack[] contents) {
if (!isValidIngredientByPlayer(player, contents[Alchemy.INGREDIENT_SLOT])) { if (!isValidIngredientByPlayer(player, contents[Alchemy.INGREDIENT_SLOT])) {
@ -240,18 +257,23 @@ public final class AlchemyPotionBrewer {
public static boolean transferItems(InventoryView view, int fromSlot, ClickType click) { public static boolean transferItems(InventoryView view, int fromSlot, ClickType click) {
boolean success = false; boolean success = false;
if (click.isLeftClick()) { try {
success = transferItems(view, fromSlot); if (click.isLeftClick()) {
} else if (click.isRightClick()) { success = transferItems(view, fromSlot);
success = transferOneItem(view, fromSlot); } else if (click.isRightClick()) {
success = transferOneItem(view, fromSlot);
}
} catch (InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
} }
return success; return success;
} }
private static boolean transferOneItem(InventoryView view, int fromSlot) { private static boolean transferOneItem(InventoryView view, int fromSlot)
ItemStack from = view.getItem(fromSlot).clone(); throws InvocationTargetException, IllegalAccessException {
ItemStack to = view.getItem(Alchemy.INGREDIENT_SLOT).clone(); final ItemStack from = ((ItemStack) getItem.invoke(view, fromSlot)).clone();
ItemStack to = ((ItemStack) getItem.invoke(view, Alchemy.INGREDIENT_SLOT)).clone();
if (isEmpty(from)) { if (isEmpty(from)) {
return false; return false;
@ -271,8 +293,8 @@ public final class AlchemyPotionBrewer {
} }
from.setAmount(fromAmount - 1); from.setAmount(fromAmount - 1);
view.setItem(Alchemy.INGREDIENT_SLOT, to); setItem.invoke(view, Alchemy.INGREDIENT_SLOT, to);
view.setItem(fromSlot, from); setItem.invoke(view, fromSlot, from);
return true; return true;
} }
@ -283,16 +305,15 @@ public final class AlchemyPotionBrewer {
/** /**
* Transfer items between two ItemStacks, returning the leftover status * Transfer items between two ItemStacks, returning the leftover status
*/ */
private static boolean transferItems(InventoryView view, int fromSlot) { private static boolean transferItems(InventoryView view, int fromSlot)
ItemStack from = view.getItem(fromSlot).clone(); throws InvocationTargetException, IllegalAccessException {
ItemStack to = view.getItem(Alchemy.INGREDIENT_SLOT).clone(); final ItemStack from = ((ItemStack) getItem.invoke(view, fromSlot)).clone();
final ItemStack to = ((ItemStack) getItem.invoke(view, Alchemy.INGREDIENT_SLOT)).clone();
if (isEmpty(from)) { if (isEmpty(from)) {
return false; return false;
} else if (isEmpty(to)) { } else if (isEmpty(to)) {
view.setItem(Alchemy.INGREDIENT_SLOT, from); setItem.invoke(view, Alchemy.INGREDIENT_SLOT, from);
view.setItem(fromSlot, null); setItem.invoke(view, fromSlot, null);
return true; return true;
} else if (from.isSimilar(to)) { } else if (from.isSimilar(to)) {
int fromAmount = from.getAmount(); int fromAmount = from.getAmount();
@ -303,17 +324,17 @@ public final class AlchemyPotionBrewer {
int left = fromAmount + toAmount - maxSize; int left = fromAmount + toAmount - maxSize;
to.setAmount(maxSize); to.setAmount(maxSize);
view.setItem(Alchemy.INGREDIENT_SLOT, to); setItem.invoke(view, Alchemy.INGREDIENT_SLOT, to);
from.setAmount(left); from.setAmount(left);
view.setItem(fromSlot, from); setItem.invoke(view, fromSlot, from);
return true; return true;
} }
to.setAmount(fromAmount + toAmount); to.setAmount(fromAmount + toAmount);
view.setItem(fromSlot, null); setItem.invoke(view, fromSlot, null);
view.setItem(Alchemy.INGREDIENT_SLOT, to); setItem.invoke(view, Alchemy.INGREDIENT_SLOT, to);
return true; return true;
} }