diff --git a/src/main/java/com/songoda/core/SongodaPlugin.java b/src/main/java/com/songoda/core/SongodaPlugin.java index aeed3a5e..931aef68 100644 --- a/src/main/java/com/songoda/core/SongodaPlugin.java +++ b/src/main/java/com/songoda/core/SongodaPlugin.java @@ -86,12 +86,14 @@ public abstract class SongodaPlugin extends JavaPlugin { locale = Locale.loadDefaultLocale(this, "en_US"); // plugin setup onPluginEnable(); + if(emergencyStop) { + console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + return; + } // Start Metrics Metrics.start(this); } catch (Throwable t) { getLogger().log(Level.SEVERE, "Unexpected error while loading " + getDescription().getName() + ": Disabling plugin!", t); - emergencyStop = true; - setEnabled(false); console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); return; } @@ -99,6 +101,11 @@ public abstract class SongodaPlugin extends JavaPlugin { console.sendMessage(ChatColor.GREEN + "============================="); } + protected void emergencyStop() { + emergencyStop = true; + Bukkit.getPluginManager().disablePlugin(this); + } + @Override public final void onDisable() { if (emergencyStop) { diff --git a/src/main/java/com/songoda/core/compatibility/LegacyMaterials.java b/src/main/java/com/songoda/core/compatibility/LegacyMaterials.java index 87283d17..fb4644ea 100644 --- a/src/main/java/com/songoda/core/compatibility/LegacyMaterials.java +++ b/src/main/java/com/songoda/core/compatibility/LegacyMaterials.java @@ -900,7 +900,7 @@ public enum LegacyMaterials { STONE_PRESSURE_PLATE("STONE_PLATE"), STONE_SHOVEL("STONE_SPADE"), STONE_SLAB("STEP", (byte) 0), - STONE_STAIRS(""), + STONE_STAIRS(), STONE_SWORD, STRAY_SPAWN_EGG("MONSTER_EGG", (byte) 6), STRING, @@ -920,7 +920,7 @@ public enum LegacyMaterials { STRUCTURE_VOID, SUGAR, SUGAR_CANE, - SUNFLOWER("LONG_GRASS", (byte) 0), + SUNFLOWER("DOUBLE_PLANT", (byte) 0), SUSPICIOUS_STEW, SWEET_BERRIES, SWEET_BERRY_BUSH, diff --git a/src/main/java/com/songoda/core/compatibility/ParticleHandler.java b/src/main/java/com/songoda/core/compatibility/ParticleHandler.java index 00be073c..2e8f5a32 100644 --- a/src/main/java/com/songoda/core/compatibility/ParticleHandler.java +++ b/src/main/java/com/songoda/core/compatibility/ParticleHandler.java @@ -1,5 +1,6 @@ package com.songoda.core.compatibility; +import java.util.stream.Stream; import org.bukkit.Color; import org.bukkit.Effect; import org.bukkit.Location; @@ -7,7 +8,165 @@ import org.bukkit.Particle; import org.bukkit.block.BlockFace; public class ParticleHandler { - + + public static enum ParticleType { + EXPLOSION_NORMAL(), + EXPLOSION_LARGE, + EXPLOSION_HUGE, + FIREWORKS_SPARK, + WATER_BUBBLE, + WATER_SPLASH, + WATER_WAKE, + SUSPENDED, + SUSPENDED_DEPTH, + CRIT, + CRIT_MAGIC, + SMOKE_NORMAL, + SMOKE_LARGE, + SPELL, + SPELL_INSTANT, + SPELL_MOB, + SPELL_MOB_AMBIENT, + SPELL_WITCH, + DRIP_WATER, + DRIP_LAVA, + VILLAGER_ANGRY, + VILLAGER_HAPPY, + TOWN_AURA, + NOTE, + PORTAL, + ENCHANTMENT_TABLE, + FLAME, + LAVA, + CLOUD, + REDSTONE(), //DustOptions + SNOWBALL, + SNOW_SHOVEL, + SLIME, + HEART, + BARRIER, + ITEM_CRACK(), // ItemStack + BLOCK_CRACK(), // BlockData + BLOCK_DUST(), // BlockData + WATER_DROP, + // 1.9-1.12 included ITEM_TAKE + MOB_APPEARANCE, + DRAGON_BREATH, + END_ROD, + DAMAGE_INDICATOR, + SWEEP_ATTACK, + /// End 1.9 particles /// + FALLING_DUST(ServerVersion.V1_10, "BLOCK_DUST"), // BlockData + /// End 1.10 /// + TOTEM(ServerVersion.V1_11, "VILLAGER_HAPPY"), + SPIT(ServerVersion.V1_11, "REDSTONE"), + /// End 1.11-1.12 /// + SQUID_INK(ServerVersion.V1_13, "CRIT"), + BUBBLE_POP(ServerVersion.V1_13, "CRIT"), + CURRENT_DOWN(ServerVersion.V1_13, "CRIT"), + BUBBLE_COLUMN_UP(ServerVersion.V1_13, "CRIT"), + NAUTILUS(ServerVersion.V1_13, "END_ROD"), + DOLPHIN(ServerVersion.V1_13, "TOWN_AURA"), + /// End 1.13 /// + SNEEZE(ServerVersion.V1_14, "REDSTONE"), + CAMPFIRE_COSY_SMOKE(ServerVersion.V1_14, "SMOKE_NORMAL"), + CAMPFIRE_SIGNAL_SMOKE(ServerVersion.V1_14, "SMOKE_LARGE"), + COMPOSTER(ServerVersion.V1_14, "CRIT"), + FLASH(ServerVersion.V1_14, "EXPLOSION_NORMAL"), // idk + FALLING_LAVA(ServerVersion.V1_14, "DRIP_LAVA"), + LANDING_LAVA(ServerVersion.V1_14, "LAVA"), + FALLING_WATER(ServerVersion.V1_14, "DRIP_WATER"), + /// End 1.14 /// + ; + + final boolean compatibilityMode; + final LegacyParticleEffects.Type compatibleEffect; + final Object particle; + + private ParticleType() { + if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) { + this.compatibilityMode = true; + this.particle = null; + this.compatibleEffect = LegacyParticleEffects.Type.valueOf(name()); + } else { + this.compatibleEffect = null; + // does this particle exist in our version? + Particle check = Stream.of(Particle.values()).filter(p -> p.name().equals(name())).findFirst().orElse(null); + if (check != null) { + this.particle = check; + this.compatibilityMode = false; + } else { + // this shouldn't happen, really + this.particle = Particle.END_ROD; + this.compatibilityMode = true; + } + } + } + + private ParticleType(ServerVersion minVersion, String compatible) { + // Particle class doesn't exist in 1.8 + if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) { + this.compatibilityMode = true; + this.compatibleEffect = LegacyParticleEffects.Type.valueOf(compatible); + this.particle = null; + } else if (ServerVersion.isServerVersionBelow(minVersion)) { + this.compatibilityMode = true; + this.compatibleEffect = null; + this.particle = Particle.valueOf(compatible); + } else { + this.compatibleEffect = null; + // does this particle exist in our version? + Particle check = Stream.of(Particle.values()).filter(p -> p.name().equals(name())).findFirst().orElse(null); + if (check != null) { + this.particle = check; + this.compatibilityMode = false; + } else { + // this shouldn't happen, really + this.particle = Particle.END_ROD; + this.compatibilityMode = true; + } + } + } + } + + public static void spawnParticles(ParticleType type, Location location) { + if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) { + LegacyParticleEffects.createParticle(location, type.compatibleEffect); + } else { + location.getWorld().spawnParticle((Particle) type.particle, location, 0); + } + } + + public static void spawnParticles(ParticleType type, Location location, int count) { + if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) { + LegacyParticleEffects.createParticle(location, type.compatibleEffect); + for (int i = 0; i < count; i++) { + float xx = (float) (1 * (Math.random() - Math.random())); + float yy = (float) (1 * (Math.random() - Math.random())); + float zz = (float) (1 * (Math.random() - Math.random())); + Location at = location.clone().add(xx, yy, zz); + LegacyParticleEffects.createParticle(at, LegacyParticleEffects.Type.REDSTONE); + } + } else { + location.getWorld().spawnParticle((Particle) type.particle, location, count); + } + } + + public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ) { + if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) { + LegacyParticleEffects.createParticle(location, type.compatibleEffect); + for (int i = 0; i < count; i++) { + float xx = (float) (offsetX * (Math.random() - Math.random())); + float yy = (float) (offsetY * (Math.random() - Math.random())); + float zz = (float) (offsetZ * (Math.random() - Math.random())); + Location at = location.clone().add(xx, yy, zz); + LegacyParticleEffects.createParticle(at, LegacyParticleEffects.Type.REDSTONE); + } + } else { + location.getWorld().spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ); + } + } + public static void redstoneParticles(Location location, int red, int green, int blue) { redstoneParticles(location, red, green, blue, 1F, 1, 0); } diff --git a/src/main/java/com/songoda/core/compatibility/ServerVersion.java b/src/main/java/com/songoda/core/compatibility/ServerVersion.java index 83aded63..bb220220 100644 --- a/src/main/java/com/songoda/core/compatibility/ServerVersion.java +++ b/src/main/java/com/songoda/core/compatibility/ServerVersion.java @@ -49,10 +49,18 @@ public enum ServerVersion { return ArrayUtils.contains(versions, serverVersion); } + public static boolean isServerVersionAbove(ServerVersion version) { + return serverVersion.ordinal() > version.ordinal(); + } + public static boolean isServerVersionAtLeast(ServerVersion version) { return serverVersion.ordinal() >= version.ordinal(); } + public static boolean isServerVersionAtOrBelow(ServerVersion version) { + return serverVersion.ordinal() <= version.ordinal(); + } + public static boolean isServerVersionBelow(ServerVersion version) { return serverVersion.ordinal() < version.ordinal(); } diff --git a/src/main/java/com/songoda/core/configuration/ConfigFileConfigurationAdapter.java b/src/main/java/com/songoda/core/configuration/ConfigFileConfigurationAdapter.java index dbcef167..7dbd19e0 100644 --- a/src/main/java/com/songoda/core/configuration/ConfigFileConfigurationAdapter.java +++ b/src/main/java/com/songoda/core/configuration/ConfigFileConfigurationAdapter.java @@ -1,5 +1,8 @@ package com.songoda.core.configuration; +import com.songoda.core.compatibility.LegacyMaterials; +import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -7,6 +10,8 @@ import org.bukkit.configuration.Configuration; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class ConfigFileConfigurationAdapter extends FileConfiguration { @@ -116,4 +121,153 @@ public class ConfigFileConfigurationAdapter extends FileConfiguration { return config.createSection(path, map); } + // Other non-FileConfiguration methods + + @NotNull + public ConfigSection createDefaultSection(@NotNull String path) { + return config.createDefaultSection(path); + } + + @NotNull + public ConfigSection createDefaultSection(@NotNull String path, String... comment) { + return config.createDefaultSection(path, comment); + } + + @NotNull + public ConfigSection createDefaultSection(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, String... comment) { + return config.createDefaultSection(path, commentStyle, comment); + } + + @NotNull + public ConfigSection setComment(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... lines) { + return config.setComment(path, commentStyle, lines); + } + + @NotNull + public ConfigSection setComment(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List lines) { + return config.setComment(path, commentStyle, lines); + } + + @NotNull + public ConfigSection setDefaultComment(@NotNull String path, String... lines) { + return config.setDefaultComment(path, lines); + } + + @NotNull + public ConfigSection setDefaultComment(@NotNull String path, @Nullable List lines) { + return config.setDefaultComment(path, lines); + } + + @NotNull + public ConfigSection setDefaultComment(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, String... lines) { + return config.setDefaultComment(path, commentStyle, lines); + } + + @NotNull + public ConfigSection setDefaultComment(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, @Nullable List lines) { + return config.setDefaultComment(path, commentStyle, lines); + } + + @Nullable + public Comment getComment(@NotNull String path) { + return config.getComment(path); + } + + @Nullable + public String getCommentString(@NotNull String path) { + return config.getCommentString(path); + } + + @NotNull + public List getSections(String path) { + return config.getSections(path); + } + + @NotNull + public ConfigSection set(@NotNull String path, @Nullable Object value, String... comment) { + return config.set(path, value, comment); + } + + @NotNull + public ConfigSection set(@NotNull String path, @Nullable Object value, List comment) { + return config.set(path, value, comment); + } + + @NotNull + public ConfigSection set(@NotNull String path, @Nullable Object value, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... comment) { + return config.set(path, value, commentStyle, comment); + } + + @NotNull + public ConfigSection set(@NotNull String path, @Nullable Object value, @Nullable ConfigFormattingRules.CommentStyle commentStyle, List comment) { + return config.set(path, value, commentStyle, comment); + } + + @NotNull + public ConfigSection setDefault(@NotNull String path, @Nullable Object value) { + return config.setDefault(path, value); + } + + @NotNull + public ConfigSection setDefault(@NotNull String path, @Nullable Object value, String... comment) { + return config.setDefault(path, value, comment); + } + + @NotNull + public ConfigSection setDefault(@NotNull String path, @Nullable Object value, List comment) { + return config.setDefault(path, value, comment); + } + + @NotNull + public ConfigSection setDefault(@NotNull String path, @Nullable Object value, ConfigFormattingRules.CommentStyle commentStyle, String... comment) { + return config.setDefault(path, value, commentStyle, comment); + } + + @NotNull + public ConfigSection setDefault(@NotNull String path, @Nullable Object value, ConfigFormattingRules.CommentStyle commentStyle, List comment) { + return config.setDefault(path, value, commentStyle, comment); + } + + @NotNull + public ConfigSection createSection(@NotNull String path, String... comment) { + return config.createSection(path, comment); + } + + @NotNull + public ConfigSection createSection(@NotNull String path, @Nullable List comment) { + return config.createSection(path, comment); + } + + @NotNull + public ConfigSection createSection(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... comment) { + return config.createSection(path, commentStyle, comment); + } + + @NotNull + public ConfigSection createSection(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List comment) { + return config.createSection(path, commentStyle, comment); + } + + public char getChar(@NotNull String path) { + return config.getChar(path); + } + + public char getChar(@NotNull String path, char def) { + return config.getChar(path, def); + } + + @Nullable + public LegacyMaterials getMaterial(@NotNull String path) { + return config.getMaterial(path); + } + + @Nullable + public LegacyMaterials getMaterial(@NotNull String path, @Nullable LegacyMaterials def) { + return config.getMaterial(path, def); + } + + @NotNull + public ConfigSection getOrCreateConfigurationSection(@NotNull String path) { + return config.getOrCreateConfigurationSection(path); + } } diff --git a/src/main/java/com/songoda/core/configuration/ConfigSection.java b/src/main/java/com/songoda/core/configuration/ConfigSection.java index 3f56b549..84086d86 100644 --- a/src/main/java/com/songoda/core/configuration/ConfigSection.java +++ b/src/main/java/com/songoda/core/configuration/ConfigSection.java @@ -629,6 +629,7 @@ public class ConfigSection extends MemoryConfiguration { return result instanceof ConfigSection ? (ConfigSection) result : null; } + @NotNull public ConfigSection getOrCreateConfigurationSection(@NotNull String path) { Object result = get(path); return result instanceof ConfigSection ? (ConfigSection) result : createSection(path); diff --git a/src/main/java/com/songoda/core/configuration/editor/PluginConfigGui.java b/src/main/java/com/songoda/core/configuration/editor/PluginConfigGui.java index 8256e1c4..bccaac59 100644 --- a/src/main/java/com/songoda/core/configuration/editor/PluginConfigGui.java +++ b/src/main/java/com/songoda/core/configuration/editor/PluginConfigGui.java @@ -60,7 +60,7 @@ public class PluginConfigGui extends SimplePagedGui { try { // can we also grab extra config from this mysterious plugin? Object more = plugin.getClass().getDeclaredMethod("getExtraConfig").invoke(plugin); - if (more instanceof List && !((List) more).isEmpty()) { + if (more != null && more instanceof List && !((List) more).isEmpty()) { try { // if we have the getExtraConfig function, we should also be able to get the file Method method_Config_getFile = ((List) more).get(0).getClass().getDeclaredMethod("getFile"); diff --git a/src/main/java/com/songoda/core/gui/Gui.java b/src/main/java/com/songoda/core/gui/Gui.java index 60e81245..a7a3cdb6 100644 --- a/src/main/java/com/songoda/core/gui/Gui.java +++ b/src/main/java/com/songoda/core/gui/Gui.java @@ -5,6 +5,7 @@ import com.songoda.core.gui.events.GuiClickEvent; import com.songoda.core.gui.events.GuiCloseEvent; import com.songoda.core.gui.events.GuiDropItemEvent; import com.songoda.core.gui.events.GuiOpenEvent; +import com.songoda.core.gui.events.GuiPageEvent; import com.songoda.core.gui.methods.Pagable; import com.songoda.core.gui.methods.Clickable; import com.songoda.core.gui.methods.Droppable; @@ -51,6 +52,7 @@ public class Gui { protected static ItemStack AIR = new ItemStack(Material.AIR); protected boolean open = false; + protected Clickable defaultClicker = null; protected Openable opener = null; protected Closable closer = null; protected Droppable dropper = null; @@ -210,6 +212,11 @@ public class Gui { return this; } + public Gui setDefaultAction(Clickable action) { + defaultClicker = action; + return this; + } + public Gui setDefaultItem(ItemStack item) { blankItem = item; return this; @@ -219,6 +226,21 @@ public class Gui { return blankItem; } + public ItemStack getItem(int cell) { + if (inventory != null && unlockedCells.getOrDefault(cell, false)) { + return inventory.getItem(cell); + } + return cellItems.get(cell); + } + + public ItemStack getItem(int row, int col) { + final int cell = col + row * 9; + if (inventory != null && unlockedCells.getOrDefault(cell, false)) { + return inventory.getItem(cell); + } + return cellItems.get(cell); + } + public Gui setItem(int cell, ItemStack item) { cellItems.put(cell, item); if (open && cell >= 0 && cell < inventory.getSize()) { @@ -277,7 +299,7 @@ public class Gui { public Gui updateItem(int cell, String name, String... lore) { ItemStack item = cellItems.get(cell); if (item != null && item.getType() != Material.AIR) { - setItem(cell, GuiUtils.updateItem(item, title, lore)); + setItem(cell, GuiUtils.updateItem(item, name, lore)); } return this; } @@ -462,7 +484,7 @@ public class Gui { public Gui setNextPage(int row, int col, ItemStack item) { nextPageIndex = col + row * 9; if (page < pages) { - setButton(nextPageIndex, item, ClickType.LEFT, (event) -> this.nextPage()); + setButton(nextPageIndex, item, ClickType.LEFT, (event) -> this.nextPage(event.manager)); } return this; } @@ -470,18 +492,18 @@ public class Gui { public Gui setPrevPage(int row, int col, ItemStack item) { prevPageIndex = col + row * 9; if (page > 1) { - setButton(prevPageIndex, item, ClickType.LEFT, (event) -> this.prevPage()); + setButton(prevPageIndex, item, ClickType.LEFT, (event) -> this.prevPage(event.manager)); } return this; } - public void nextPage() { + public void nextPage(GuiManager manager) { if (page < pages) { int lastPage = page; ++page; // page switch events if (pager != null) { - pager.onPageChange(this, lastPage, page); + pager.onPageChange(new GuiPageEvent(this, manager, lastPage, page)); // page markers updatePageNavigation(); @@ -493,12 +515,12 @@ public class Gui { } } - public void prevPage() { + public void prevPage(GuiManager manager) { if (page > 1) { int lastPage = page; --page; if (pager != null) { - pager.onPageChange(this, lastPage, page); + pager.onPageChange(new GuiPageEvent(this, manager, lastPage, page)); // page markers updatePageNavigation(); @@ -512,13 +534,13 @@ public class Gui { protected void updatePageNavigation() { if (page > 1) { - this.setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage()); + this.setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage(event.manager)); } else { this.setItem(prevPageIndex, null); this.clearActions(prevPageIndex); } if (pages > 1 && page != pages) { - this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage()); + this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage(event.manager)); } else { this.setItem(nextPageIndex, null); this.clearActions(nextPageIndex); @@ -586,6 +608,10 @@ public class Gui { button.onClick(new GuiClickEvent(manager, this, player, event, cell, true)); } else { // no event for this button + if(defaultClicker != null) { + // this is a default action, not a triggered action + defaultClicker.onClick(new GuiClickEvent(manager, this, player, event, cell, true)); + } return false; } return true; diff --git a/src/main/java/com/songoda/core/gui/GuiManager.java b/src/main/java/com/songoda/core/gui/GuiManager.java index e1baa135..9a5dae75 100644 --- a/src/main/java/com/songoda/core/gui/GuiManager.java +++ b/src/main/java/com/songoda/core/gui/GuiManager.java @@ -78,7 +78,7 @@ public class GuiManager { if(openInv != null) { openInv.open = false; } - Inventory inv = gui.generateInventory(this); + Inventory inv = gui.getOrCreateInventory(this); player.openInventory(inv); gui.onOpen(this, player); openInventories.put(player, gui); diff --git a/src/main/java/com/songoda/core/gui/SimplePagedGui.java b/src/main/java/com/songoda/core/gui/SimplePagedGui.java index 4f50be08..8530c6b9 100644 --- a/src/main/java/com/songoda/core/gui/SimplePagedGui.java +++ b/src/main/java/com/songoda/core/gui/SimplePagedGui.java @@ -89,7 +89,7 @@ public class SimplePagedGui extends Gui { } @Override - public void nextPage() { + public void nextPage(GuiManager manager) { if (page < pages) { ++page; showPage(); @@ -97,7 +97,7 @@ public class SimplePagedGui extends Gui { } @Override - public void prevPage() { + public void prevPage(GuiManager manager) { if (page > 1) { --page; showPage(); @@ -120,7 +120,7 @@ public class SimplePagedGui extends Gui { protected void updatePageNavigation() { if (page > 1) { inventory.setItem((rows * 9) - 6, prevPage); - this.setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage()); + this.setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage(event.manager)); } else { inventory.setItem((rows * 9) - 6, footerBackItem != null ? footerBackItem : blankItem); this.setItem(prevPageIndex, null); @@ -128,7 +128,7 @@ public class SimplePagedGui extends Gui { } if (pages > 1 && page != pages) { inventory.setItem((rows * 9) - 4, nextPage); - this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage()); + this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage(event.manager)); } else { inventory.setItem((rows * 9) - 4, footerBackItem != null ? footerBackItem : blankItem); this.setItem(nextPageIndex, null); diff --git a/src/main/java/com/songoda/core/gui/events/GuiPageEvent.java b/src/main/java/com/songoda/core/gui/events/GuiPageEvent.java new file mode 100644 index 00000000..e9cc065a --- /dev/null +++ b/src/main/java/com/songoda/core/gui/events/GuiPageEvent.java @@ -0,0 +1,20 @@ +package com.songoda.core.gui.events; + +import com.songoda.core.gui.Gui; +import com.songoda.core.gui.GuiManager; + +public class GuiPageEvent { + + final Gui gui; + final GuiManager manager; + final int lastPage; + final int page; + + public GuiPageEvent(Gui gui, GuiManager manager, int lastPage, int page) { + this.gui = gui; + this.manager = manager; + this.lastPage = lastPage; + this.page = page; + } + +} diff --git a/src/main/java/com/songoda/core/gui/methods/Pagable.java b/src/main/java/com/songoda/core/gui/methods/Pagable.java index c7f99a62..239ba099 100644 --- a/src/main/java/com/songoda/core/gui/methods/Pagable.java +++ b/src/main/java/com/songoda/core/gui/methods/Pagable.java @@ -1,8 +1,8 @@ package com.songoda.core.gui.methods; -import com.songoda.core.gui.Gui; +import com.songoda.core.gui.events.GuiPageEvent; public interface Pagable { - void onPageChange(Gui gui, int lastPage, int newPage); + void onPageChange(GuiPageEvent event); } diff --git a/src/main/java/com/songoda/core/locale/Message.java b/src/main/java/com/songoda/core/locale/Message.java index fbc79dd5..e30c586f 100644 --- a/src/main/java/com/songoda/core/locale/Message.java +++ b/src/main/java/com/songoda/core/locale/Message.java @@ -1,5 +1,6 @@ package com.songoda.core.locale; +import com.songoda.core.compatibility.ServerVersion; import java.util.regex.Matcher; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; @@ -58,8 +59,12 @@ public class Message { * @param sender command sender to send the message to */ public void sendTitle(CommandSender sender) { - if(sender instanceof Player) { - ((Player) sender).sendTitle("", this.getMessage(), 10, 20, 10); + if (sender instanceof Player) { + if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) { + ((Player) sender).sendTitle("", getMessage(), 10, 30, 10); + } else { + ((Player) sender).sendTitle("", getMessage()); + } } else { sender.sendMessage(this.getMessage()); } diff --git a/src/main/java/com/songoda/core/utils/ItemSerializer.java b/src/main/java/com/songoda/core/utils/ItemSerializer.java new file mode 100644 index 00000000..9cf11e54 --- /dev/null +++ b/src/main/java/com/songoda/core/utils/ItemSerializer.java @@ -0,0 +1,72 @@ +package com.songoda.core.utils; + +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.io.BukkitObjectInputStream; +import org.bukkit.util.io.BukkitObjectOutputStream; +import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * Class based off of https://gist.github.com/graywolf336/8153678 + */ +public class ItemSerializer { + + /** + * A method to serialize an {@link ItemStack} list to Base64 String. + * + * @param items to turn into a Base64 String. + * @return Base64 string of the items. + */ + public static String toBase64(List items) { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); + + // Write the size of the inventory + dataOutput.writeInt(items.size()); + + // Save every element in the list + for (ItemStack item : items) + dataOutput.writeObject(item); + + // Serialize that array + dataOutput.close(); + return Base64Coder.encodeLines(outputStream.toByteArray()); + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + /** + * Gets a list of ItemStacks from Base64 string. + * + * @param data Base64 string to convert to ItemStack list. + * @return ItemStack array created from the Base64 string. + */ + public static List fromBase64(String data) { + try { + ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); + BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); + int length = dataInput.readInt(); + List items = new ArrayList<>(); + + // Read the serialized itemstack list + for (int i = 0; i < length; i++) + items.add((ItemStack) dataInput.readObject()); + + dataInput.close(); + return items; + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + +}