我正在尝试使用HashMap为插槽和按钮创建一个包含我的Pane对象的清单。但是,我收到一个StackOverFlowError,可能(可能是?)因为一些递归,但我完全无法找到位置。相关代码:
ro
BecomeYouTuberPane类扩展窗格
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* Project created by ExpDev
*/
public abstract class Pane implements InventoryHolder {
private Inventory inventory;
private Map<Integer, Button> buttons = new HashMap<>();
/**
* @param rows Amount of rows. Max = 9
*/
public Pane(int rows, String title) {
Objects.requireNonNull(title, "title can not be null!");
if (rows > 6) {
throw new IllegalArgumentException("Rows must be <= 6, got " + rows);
}
this.inventory = Bukkit.createInventory(this, rows * 9, color(title));
}
/**
* @param button The button to add
*/
public void addButton(Button button) {
// Finding next available
buttons.put(buttons.size(), button);
reRender();
}
public void addButton(int place, Button button) {
buttons.put(place, button);
reRender();
}
/**
* @param place The place the button is located
*/
@SuppressWarnings("unused")
public void removeButton(int place) {
buttons.remove(place);
reRender();
}
/**
* Renders the inventory again
*/
@SuppressWarnings("WeakerAccess")
public void reRender() {
inventory.clear();
createControls(inventory);
render(inventory);
}
/**
* @param event The {@link InventoryClickEvent}
*/
@SuppressWarnings("WeakerAccess")
public void onClick(InventoryClickEvent event) {
event.setCancelled(true);
handleClick(event);
}
/**
* Creates the controls
*
* @param inventory The inventory
*/
@SuppressWarnings("WeakerAccess")
protected abstract void createControls(Inventory inventory);
/**
* Get the object's inventory.
*
* @return The inventory.
*/
@Override
public Inventory getInventory() {
return inventory;
}
@SuppressWarnings("WeakerAccess")
protected String color(String input) {
return ChatColor.translateAlternateColorCodes('&', input);
}
/**
* @param player The {@link Player} to open it for
*/
public void open(Player player) {
reRender();
player.openInventory(getInventory());
}
/**
* @param event The click event
*/
void handleClick(InventoryClickEvent event) {
// user clicked in his own inventory. Silently drop it
if (event.getRawSlot() > event.getInventory().getSize()) {
return;
}
// user clicked outside of the inventory
if (event.getSlotType() == InventoryType.SlotType.OUTSIDE) {
return;
}
if (event.getSlot() >= buttons.size()) {
return;
}
Button button = buttons.get(event.getSlot());
button.onClick(event);
}
/**
* @param inventory The inventory to render in
*/
void render(Inventory inventory) {
for (int i : buttons.keySet()) {
Button button = buttons.get(i);
inventory.setItem(i, button.getItemStack());
System.out.println("Putting " + button.getItemStack().getType().toString() + " in slot " +i);
}
}
/**
* @return True if this page is empty
*/
boolean isEmpty() {
return buttons.isEmpty();
}
}
按钮类 import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.ItemStack;
import java.util.Objects; import java.util.function.Consumer;
import me.expdev.youtubebot.Conf;
import me.expdev.youtubebot.YTPlayer;
import me.expdev.youtubebot.utils.ItemStackUtil;
import me.expdev.youtubebot.youtube.YTRequirements;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import java.util.ArrayList;
import java.util.List;
/**
* Project created by ExpDev
*/
public class BecomeYouTuberPane extends Pane {
private YTPlayer player;
public BecomeYouTuberPane(YTPlayer player) {
super(3, "&5YouTuber Rank");
this.player = player;
}
@Override
protected void createControls(Inventory inventory) {
// slot 11 and slot 15
// Lore representing the YTRequirements for the rank
List<String> reqLore = new ArrayList<String>();
reqLore.add(ChatColor.GRAY + "YTRequirements for the " + ChatColor.LIGHT_PURPLE + "YouTube Rank" + ChatColor.GRAY + ":");
// The requirements
YTRequirements requirements = Conf.YTRequirements;
reqLore.add(ChatColor.GRAY + " - You need " + ChatColor.YELLOW + requirements.getSubscriberCount() + "+ " + ChatColor.GRAY + "Subscribers");
reqLore.add(ChatColor.GRAY + " - You need " + ChatColor.YELLOW + requirements.getViewCount() + "+ " + ChatColor.GRAY + "Views");
reqLore.add(ChatColor.GRAY + " - You need " + ChatColor.YELLOW + requirements.getAverageViewCount() + "+ " + ChatColor.GRAY + "Average Views");
reqLore.add(ChatColor.GRAY + " - You need " + ChatColor.YELLOW + requirements.getVideoCount() + "+ " + ChatColor.GRAY + "Videos");
addButton(11, new Button(ItemStackUtil.getItemStack(Material.BOOK,
1,
0,
ChatColor.LIGHT_PURPLE + "YouTube Rank",
reqLore.toArray(new String[0])))
);
// Confirm button
addButton(15, new Button(ItemStackUtil.getItemStack(Material.WOOD_BUTTON,
1,
0,
ChatColor.BOLD.toString() + ChatColor.GREEN + "Continue",
ChatColor.GRAY + "Start becoming a " + ChatColor.YELLOW + "YouTuber"),
e -> {
player.setPreVerifying(true);
player.closePane();
player.msg("&7Type your &9https://www.youtube.com/channel/channelId &7or &9/user/username &7in chat &9(disabled for this process)&7.");
})); // Start verifying
}
}
例外:
/**
* A button
*/
public class Button {
private static int counter;
private final int ID = counter++;
private ItemStack itemStack;
private Consumer<InventoryClickEvent> action;
/**
* @param itemStack The Item
*/
@SuppressWarnings("unused")
public Button(ItemStack itemStack) {
this(itemStack, event -> {});
}
/**
* @param itemStack The Item
* @param action The action
*/
public Button(ItemStack itemStack, Consumer<InventoryClickEvent> action) {
this.itemStack = itemStack;
this.action = action;
}
/**
* @return The icon
*/
@SuppressWarnings("WeakerAccess")
public ItemStack getItemStack() {
return itemStack;
}
/**
* @param action The new action
*/
@SuppressWarnings("unused")
public void setAction(Consumer<InventoryClickEvent> action) {
this.action = action;
}
/**
* @param event The event that triggered it
*/
@SuppressWarnings("WeakerAccess")
public void onClick(InventoryClickEvent event) {
action.accept(event);
}
// We do not want equals collisions. The default hashcode would not fulfil this contract.
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Button)) {
return false;
}
Button button = (Button) o;
return ID == button.ID;
}
@Override
public int hashCode() {
return Objects.hash(ID);
}
}
非常感谢任何帮助!谢谢。
答案 0 :(得分:1)
确实你有一个递归问题。它如下:
reRender
(窗格)createControls
在BecomeYouTuberPane
来电addButton
addButton
调用reRender
,因此循环关闭