I have been experiencing an odd bug in my Spigot/Bukkit plugin lately which totally does not make any sense. Please note that this question may be long due to the fact that the project I am working on is fairly big and since the source code (provided below) contains classes that will not be included here I will try my best to describe my problem.
In Minecraft, using Bukkit API you can create graphical menus (GUI's) in which you can place items in certain slots and when clicked, you can adjust your functionality.
In my case, I have created the Menu
foundation class which contains basic methods for the creation of such a menu. Then, the PurchaseMenu
which extends the Menu class is used to trigger functionality in specific locations to simulate a transaction for product that can be clicked from the menu.
In depth, the menu I will include contains "Kit" displays (like game classes) that when one Left-Click's the display the player can buy it, or if it's already bought, the player will just select that kit for use. When one Right-Clicks's the display, the player can level up the kit up to 3.
In both cases a transaction menu must be popped up in order to buy or level up the clicked kit. My design is really straight forward, by passing the clicked kit from the constructor on each PurchaseMenu
class.
The problem on all the above is that the Kit is passed correctly from the constructor, but the kit that is actually being bought or level up is a random one (obviously not, but haven't found any evidence yet) and that usually happens after some tries.
My Design:
InventoryClick
is called when a menu display is clicked (interacted). InventoryConstruct
is called when a menu is being created (opened).PurchaseProduct
is called when a display is purchased successfully. PrePaymentChecks
is necessary checks that need to be ran before the purchase.My questions:
Any form of help is appreciated, I hope I described my problem in detail, if you require any further source code, please post a comment below.
Because of the fact that the question will be more than 30k characters, I uploaded the whole project into a Git repository.
https://github.com/parat26/core
Menu.java: https://github.com/parat26/core/blob/master/src/src/ares/core/menu/Menu.java
PurchaseMenu.java:https://github.com/parat26/core/blob/master/src/src/ares/core/menu/PurchaseMenu.java
BattleOptionsMenu.java: https://github.com/parat26/core/blob/master/src/src/ares/core/menu/type/MenuBattleOptions.java
PurchaseMenuKit.java: https://github.com/parat26/core/blob/master/src/src/ares/core/menu/type/PurchaseMenuKit.java
Try changing PurchaseMenu.object to final and see what the output is. Also, System.out.println()
is your friend.
I do not suggest you use Object for your kit as it may be changing the object when you set object
to sellableKit
. Make an interface called Sellable<T>
so that you can enforce the type (called Strong Typing) with:
private final ItemStack item;
protected final Sellable<? super Kit> kit;
private final GoldCurrency currency;
public PurchaseMenu(String menuName, ItemStack sellableItem, Sellable<? super Kit> sellableKit, GoldCurrency currencyType)
{
super(Material.STONE, menuName, 54);
item = sellableItem;
kit = sellableKit;
currency = currencyType;
DependOnEvents(true);
}
Making those fields final also is good practice since it doesn't appear that you are setting those fields after object creation and lets anyone know immediately those objects will never change. It should also enlighten the situation since a final object cannot be changed.
You should remove the private Kit kit;
field from BuyKitOwnershipMenu
since your just making a copy of the object. Your PurchaseProduct()
method can be changed to
@Override
public void PurchaseProduct(GoldCurrency currency, Client client)
{
client.getManager().setKitOwned(kit, true);
}
Since kit is now protected and in the super class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With