diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/core/Gui.java b/src/main/java/fr/moribus/imageonmap/guiproko/core/Gui.java index 75f71cd..8864073 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/core/Gui.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/core/Gui.java @@ -21,6 +21,7 @@ package fr.moribus.imageonmap.guiproko.core; import fr.moribus.imageonmap.PluginLogger; import java.lang.reflect.Constructor; import java.util.HashMap; +import org.bukkit.Bukkit; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.Listener; @@ -33,6 +34,10 @@ abstract public class Gui */ private Player player; + /** + * The parent of this GUI (if any). + */ + private Gui parent; /** * If the inventory is currently open. @@ -40,14 +45,11 @@ abstract public class Gui private boolean open = false; /** - * Closes this inventory. + * If the GUI is immune to close events. + * Useful to filter out excessive InventoryCloseEvents Bukkit sends ... */ - public void close() - { - setClosed(); - } + private boolean immune = false; - /* ===== Public API ===== */ /** @@ -59,6 +61,27 @@ abstract public class Gui onAfterUpdate(); } + /** + * Closes this inventory. + */ + public void close() + { + close(false); + } + + /** + * Closes this inventory. + * (Dirty hack edition) + * @param immune if true, the parent of this GUI will be set immune when opened + */ + protected void close(boolean immune) + { + onClose(); + + if(parent != null) + Gui.open(player, parent).setImmune(immune); + } + /* ===== Protected API ===== */ /** @@ -74,7 +97,7 @@ abstract public class Gui protected void onAfterUpdate() {} - protected final void setClosed() + protected void onClose() { if(open == false) return; open = false; @@ -94,9 +117,31 @@ abstract public class Gui /** @return If the GUI is currently open or not. */ public final boolean isOpen() { return open; } + /** @return The parent of this GUI. */ + public final Gui getParent() { return parent; } + + private void setParent(Gui parent) + { + if(parent == this) + throw new IllegalArgumentException("A GUI cannot be its own parent."); + this.parent = parent; + } + /** @return The player this Gui instance is associated to. */ protected final Player getPlayer() { return player; } + protected boolean checkImmune() + { + if(!immune) return false; + immune = false; + return true; + } + + private void setImmune(boolean immune) + { + this.immune = immune; + } + /* ===== Static API ===== */ /** @@ -159,6 +204,31 @@ abstract public class Gui } } + /** + * Opens a GUI for a player. + * @param A GUI type. + * @param owner The player the GUI will be shown to. + * @param gui The GUI. + * @param parent The parent of the newly created GUI. Can be null. + * @return The opened GUI. + */ + static public final T open(final Player owner, final T gui, final Gui parent) + { + Gui openGui = openGuis.get(owner); + if(openGui != null) openGui.onClose(); + if(parent != null) ((Gui)gui).setParent(parent); + + Bukkit.getScheduler().runTaskLater(plugin, new Runnable() { + @Override + public void run() + { + ((Gui)gui).open(owner);/* JAVA GENERICS Y U NO WORK */ + } + }, 0); + + return gui; + } + /** * Opens a GUI for a player. * @param A GUI type. @@ -168,10 +238,7 @@ abstract public class Gui */ static public final T open(Player owner, T gui) { - close(owner); - ((Gui)gui).open(owner);/* JAVA GENERICS Y U NO WORK */ - - return gui; + return open(owner, gui, null); } /** @@ -193,6 +260,7 @@ abstract public class Gui static public final T getOpenGui(HumanEntity entity, Class guiClass) { Gui openGui = getOpenGui(entity); + if(openGui == null) return null; if(!guiClass.isAssignableFrom(openGui.getClass())) return null; return (T) openGui; } diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/core/InventoryGui.java b/src/main/java/fr/moribus/imageonmap/guiproko/core/InventoryGui.java index b42285a..27e4d47 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/core/InventoryGui.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/core/InventoryGui.java @@ -112,8 +112,13 @@ abstract public class InventoryGui extends Gui @Override public void close() { + if(!isOpen()) return; + + //If close() is called manually, not from InventoryCloseEvent + if(getPlayer().getOpenInventory().equals(inventory)) + getPlayer().closeInventory(); + super.close(); - getPlayer().closeInventory(); } /** @@ -236,11 +241,16 @@ abstract public class InventoryGui extends Gui @EventHandler public void onInventoryClose(InventoryCloseEvent event) { - Gui openGui = getOpenGui(event.getPlayer()); + InventoryGui openGui = getOpenGui(event.getPlayer(), InventoryGui.class); if(openGui == null) return; - if(!openGui.isOpen()); - openGui.setClosed(); + if(!event.getInventory().equals(openGui.inventory)) return; + + if(openGui.isOpen()) + { + if(openGui.checkImmune()) return; + openGui.close(); + } } } diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/core/PromptGui.java b/src/main/java/fr/moribus/imageonmap/guiproko/core/PromptGui.java index cb13875..f821388 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/core/PromptGui.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/core/PromptGui.java @@ -23,8 +23,6 @@ import fr.moribus.imageonmap.PluginLogger; import fr.moribus.imageonmap.ReflectionUtils; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.logging.Level; -import java.util.logging.Logger; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -46,10 +44,8 @@ public class PromptGui extends Gui /* ===== Reflection to Sign API ===== */ static private Field fieldSign = null;//CraftSign.sign - static private Field fieldIsEditable = null;//TileEntitySign.isEditable static private Method methodGetHandle = null;//CraftPlayer.getHandle() static private Method methodOpenSign = null;//EntityHuman.openSign() - static private Field fieldSignEditor = null;//TileEntitySign.k{EntityHuman} static private Class classTileEntitySign = null;//CraftBlock.class static public boolean isAvailable() @@ -60,12 +56,12 @@ public class PromptGui extends Gui static public void prompt(Player owner, Callback callback) { - prompt(owner, callback, ""); + prompt(owner, callback, "", null); } - static public void prompt(Player owner, Callback callback, String contents) + static public void prompt(Player owner, Callback callback, String contents, Gui parent) { - Gui.open(owner, new PromptGui(callback, contents)); + Gui.open(owner, new PromptGui(callback, contents), parent); } static private void init() @@ -81,10 +77,8 @@ public class PromptGui extends Gui fieldSign = ReflectionUtils.getField(CraftSign, "sign"); - fieldIsEditable = ReflectionUtils.getField(classTileEntitySign, "isEditable"); methodGetHandle = CraftPlayer.getDeclaredMethod("getHandle"); methodOpenSign = EntityHuman.getDeclaredMethod("openSign", classTileEntitySign); - fieldSignEditor = ReflectionUtils.getField(classTileEntitySign, EntityHuman); } catch (Exception ex) { @@ -144,17 +138,17 @@ public class PromptGui extends Gui } @Override - public void close() + protected void onClose() { Block block = getPlayer().getWorld().getBlockAt(signLocation); block.setType(Material.AIR); - super.close(); + super.onClose(); } private void validate(String[] lines) { callback.call(getSignContents(lines)); - this.close(); + this.close(true);//Bukkit sends extra InventoryCloseEvents when closing a sign GUI... } static private String getSignContents(String[] lines) diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/list/ConfirmDeleteMapGui.java b/src/main/java/fr/moribus/imageonmap/guiproko/list/ConfirmDeleteMapGui.java index 54545dc..5a13d46 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/list/ConfirmDeleteMapGui.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/list/ConfirmDeleteMapGui.java @@ -69,12 +69,6 @@ public class ConfirmDeleteMapGui extends ActionGui */ private final ImageMap mapToDelete; - /** - * The previously-viewed page of the list GUI. - * Used to be able to bring the user back to the same page. - */ - private final int currentPage; - /** * A source of randomness. * @@ -86,12 +80,10 @@ public class ConfirmDeleteMapGui extends ActionGui /** * * @param mapToDelete The map being deleted. - * @param currentPage The previously-viewed page of the list GUI. */ - public ConfirmDeleteMapGui(ImageMap mapToDelete, int currentPage) + public ConfirmDeleteMapGui(ImageMap mapToDelete) { this.mapToDelete = mapToDelete; - this.currentPage = currentPage; } @Override @@ -165,7 +157,7 @@ public class ConfirmDeleteMapGui extends ActionGui @GuiAction protected void action_cancel() { - Gui.open(getPlayer(), new MapDetailGui(mapToDelete)).setCurrentPageX(currentPage); + close(); } @GuiAction @@ -184,6 +176,6 @@ public class ConfirmDeleteMapGui extends ActionGui getPlayer().sendMessage(ChatColor.RED + ex.getMessage()); } - Gui.open(getPlayer(), new MapListGui(/* currentPage */)); + close(); } } diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/list/MapDetailGui.java b/src/main/java/fr/moribus/imageonmap/guiproko/list/MapDetailGui.java index e11d4a7..0f75faa 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/list/MapDetailGui.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/list/MapDetailGui.java @@ -84,13 +84,13 @@ public class MapDetailGui extends ExplorerGui map.rename(newName); getPlayer().sendMessage(ChatColor.GRAY + "Map successfuly renamed."); } - }, map.getName()); + }, map.getName(), this); } @GuiAction private void delete() { - Gui.open(getPlayer(), new ConfirmDeleteMapGui(map, getCurrentPageX())); + Gui.open(getPlayer(), new ConfirmDeleteMapGui(map), this); } @Override diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/list/MapListGui.java b/src/main/java/fr/moribus/imageonmap/guiproko/list/MapListGui.java index 6f768c8..19f7e6b 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/list/MapListGui.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/list/MapListGui.java @@ -69,7 +69,7 @@ public class MapListGui extends ExplorerGui @Override protected void onRightClick(ImageMap map) { - Gui.open(getPlayer(), new MapDetailGui(map)); + Gui.open(getPlayer(), new MapDetailGui(map), this); } @Override