1.20.1: Previous menu title shows when you click a button which animates the title, then you go back to the previous menu before the title reverts
MrCrazys opened this issue · comments
I am using the following code:
package me.mrcrazys.simplemenus.settings;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.mineacademy.fo.Common;
import org.mineacademy.fo.MathUtil;
import org.mineacademy.fo.Valid;
import org.mineacademy.fo.collection.SerializedMap;
import org.mineacademy.fo.menu.Menu;
import org.mineacademy.fo.menu.button.Button;
import org.mineacademy.fo.menu.model.ItemCreator;
import org.mineacademy.fo.model.ConfigSerializable;
import org.mineacademy.fo.remain.CompColor;
import org.mineacademy.fo.remain.CompItemFlag;
import org.mineacademy.fo.remain.CompMaterial;
import org.mineacademy.fo.settings.ConfigItems;
import org.mineacademy.fo.settings.YamlConfig;
import java.util.*;
import java.util.Map.Entry;
@Getter
public class MenuData extends YamlConfig {
private static final ConfigItems<MenuData> MENUS = ConfigItems.fromFile("", "menus.yml", MenuData.class);
private final String name;
private String title;
private List<String> info;
private int size;
private int infoButtonPosition;
private List<ButtonData> buttons;
private MenuData(final String name) {
this.name = name;
this.setPathPrefix(name);
this.loadConfiguration(NO_DEFAULT, "menus.yml");
}
@Override
protected void onLoad() {
this.title = this.getString("Title");
this.info = this.getStringList("Info");
this.size = (int) MathUtil.calculate(this.getString("Size"));
this.infoButtonPosition = this.getInteger("Info_Button_Position", this.size - 9);
this.buttons = this.loadButtons();
}
private List<ButtonData> loadButtons() {
final List<ButtonData> buttons = new ArrayList<>();
for (final Entry<String, Object> entry : this.getMap("Buttons", String.class, Object.class).entrySet()) {
final String buttonName = entry.getKey();
final SerializedMap buttonSettings = SerializedMap.of(entry.getValue());
buttons.add(ButtonData.deserialize(buttonSettings, buttonName));
}
return buttons;
}
public void displayTo(final Player player) {
this.toMenu().displayTo(player);
}
public Menu toMenu() {
return this.toMenu(null);
}
public Menu toMenu(final Menu parent) {
final Map<Integer, Button> buttons = this.getButtons();
return new Menu(parent) {
{
this.setTitle(MenuData.this.title);
this.setSize(MenuData.this.size);
}
@Override
protected List<Button> getButtonsToAutoRegister() {
return new ArrayList<>(buttons.values());
}
@Override
public ItemStack getItemAt(final int slot) {
if (buttons.containsKey(slot))
return buttons.get(slot).getItem();
return NO_ITEM;
}
@Override
protected String[] getInfo() {
return Valid.isNullOrEmpty(MenuData.this.info) ? null : Common.toArray(MenuData.this.info);
}
@Override
protected int getInfoButtonPosition() {
return super.getInfoButtonPosition();
}
};
}
public Map<Integer, Button> getButtons() {
final Map<Integer, Button> buttons = new HashMap<>();
for (final ButtonData data : this.buttons)
buttons.put(data.getSlot(), new Button() {
@Override
public void onClickedInMenu(final Player player, final Menu menu, final ClickType click) {
if (data.getPlayerCommands() != null && !data.getPlayerCommands().isEmpty())
data.getPlayerCommands().forEach(player::chat);
if (data.getTitleAnimation() != null)
menu.animateTitle(data.getTitleAnimation());
if (data.isCopyItem())
player.getInventory().addItem(this.getItem());
if (data.getMenuToOpen() != null) {
final MenuData otherMenu = MenuData.findMenu(data.getMenuToOpen());
if (otherMenu == null)
menu.animateTitle("Invalid menu: " + data.getMenuToOpen());
else
otherMenu.toMenu(menu).displayTo(player);
}
}
@Override
public ItemStack getItem() {
return ItemCreator.of(data.getMaterial(), data.getDisplayName(), data.getLore())
.amount(data.getAmount())
.hideTags(data.isHideTags())
.flags(data.getFlags().toArray(new CompItemFlag[0]))
.modelData(data.getCustomModelData())
.color(data.getColor())
.skullOwner(data.getSkullOwner())
.skullUrl(data.getSkullUrl())
.unbreakable(data.isUnbreakable())
.glow(data.isGlow())
.bookTitle(data.getBookTitle())
.bookAuthor(data.getBookAuthor())
.make();
}
});
return buttons;
}
@Getter
@ToString
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
private static class ButtonData implements ConfigSerializable {
private final String name;
private int slot;
private CompMaterial material;
private String displayName;
private List<String> lore;
private int amount;
private boolean hideTags;
private Set<CompItemFlag> flags;
private int customModelData;
private CompColor color;
private String skullOwner;
private String skullUrl;
private boolean unbreakable;
private boolean glow;
private String bookTitle;
private String bookAuthor;
private List<String> playerCommands;
private String titleAnimation;
private String menuToOpen;
private boolean copyItem;
@Override
public SerializedMap serialize() {
return null;
}
public static ButtonData deserialize(final SerializedMap map, final String buttonName) {
final ButtonData button = new ButtonData(buttonName);
map.setRemoveOnGet(true);
button.slot = map.containsKey("Slot") ? (int) MathUtil.calculate(map.getString("Slot")) : -1;
Valid.checkBoolean(button.slot != -1, "Missing 'Slot' key from button: " + map);
button.material = map.getMaterial("Material");
Valid.checkNotNull(button.material, "Missing 'Material' key from button: " + map);
button.displayName = map.getString("Title");
Valid.checkNotNull(button.displayName, "Missing 'Title' key from button: " + map);
button.lore = map.getStringList("Lore");
Valid.checkNotNull(button.lore, "Missing 'Lore' key from button: " + map);
button.amount = map.getInteger("Amount", 1);
button.hideTags = map.getBoolean("Hide_Tags", false);
button.flags = map.getSet("Flags", CompItemFlag.class);
button.customModelData = map.getInteger("Custom_Model_Data", 0);
button.color = CompColor.fromName(map.containsKey("Color") ? map.getString("Color") : "");
button.skullOwner = map.getString("Skull_Owner");
button.skullUrl = map.getString("Skull_URL");
button.unbreakable = map.getBoolean("Unbreakable", false);
button.glow = map.getBoolean("Glow", false);
button.bookTitle = map.getString("Book_Title");
button.bookAuthor = map.getString("Book_Author");
final SerializedMap click = map.getMap("Click");
click.setRemoveOnGet(true);
button.playerCommands = click.getStringList("Player_Command");
button.titleAnimation = click.getString("Animate");
button.menuToOpen = click.getString("Menu");
button.copyItem = click.getBoolean("Copy_Item", false);
Valid.checkBoolean(click.isEmpty(), "Found unrecognized button click settings: " + click);
Valid.checkBoolean(map.isEmpty(), "Found unrecognized button settings: " + map);
return button;
}
}
public static MenuData findMenu(final String name) {
return MENUS.findItem(name);
}
public static void loadMenus() {
MENUS.loadItems();
}
public static Set<String> getMenuNames() {
return MENUS.getItemNames();
}
}
The menus.yml
files looks like:
Main_Menu:
Title: "Custom Menu"
Size: "9 * 3"
Buttons:
Time:
Slot: "9 * 1 + 3"
Material: CLOCK
Title: "Change Time"
Lore:
- ""
- "Click this button"
- "to change the time"
- "to day in your world."
Click:
Player_Command: "/time set 1000"
Animate: "Time has been set to a day!"
Egg:
Slot: "9 * 1 + 5"
Material: SHEEP_SPAWN_EGG
Title: "Open Egg Menu"
Lore:
- ""
- "Click this button"
- "to open another menu."
Click:
Menu: Test_Menu
Button:
Slot: "9 * 1 + 7"
Material: DIAMOND_SWORD
Title: "Sword"
Unbreakable: true
Lore:
- ""
- "This is a sword!"
Skull:
Slot: "9 * 1 + 1"
Amount: 64
Material: LEATHER_HELMET
Title: "Player Head"
Hide_Tags: true
Lore:
- ""
- "This is a helmet!"
Second_Menu:
Title: "Second Menu"
Size: "9 * 2"
Info:
- "This menu shows example"
- "of getting buttons"
- "as items."
Buttons:
Mob_Egg:
Slot: "4"
Material: ZOMBIE_SPAWN_EGG
Title: "Zombie Spawn Egg"
Lore:
- ""
- "Click to get this"
- "item to your inventory!"
Click:
Copy_Item: true
Animate: "Item copied to inventory!"
Test_Menu:
Title: "Test Menu"
Size: 54
Info:
- "This is a test menu!"
Buttons:
First:
Slot: 8 * 3
Material: BEDROCK
Title: "Test Item"
Lore:
- ""
- "This is a test item."
Click:
Animate: "You clicked the test item!"
When I open Test_Menu
using the button from Main_Menu
, click the Bedrock and then click on the Return button before the title finishes animating, the animated title still shows in the menu I return to, but then when the title reverts, it reverts to the title of the menu which I clicked the button that caused the title to animate.
I know this might be confusing, so please let me know if you need me to elaborate.
Thanks,
MrCrazys
Looks like a logic issue where the animation keeps the old title, and when the animation is finished the title is restored to the old one. You would need to keep the proper title somewhere else outside of the animation and then run a task 1 or two ticks later to manually "fix" the title.