diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3df27d1f..4246e5dc 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,7 +4,7 @@ stages:
variables:
name: "SongodaCore"
path: "/builds/$CI_PROJECT_PATH"
- version: "2.0.7"
+ version: "2.0.10"
build:
stage: build
diff --git a/pom.xml b/pom.xml
index dfd6f126..2ffacd29 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,6 +3,7 @@
SongodaCore
4.0.0
maven-version-number
+ jar
clean install
SongodaCore-${project.version}
diff --git a/src/main/java/com/songoda/core/SongodaCore.java b/src/main/java/com/songoda/core/SongodaCore.java
index 2101161e..713bb1ee 100644
--- a/src/main/java/com/songoda/core/SongodaCore.java
+++ b/src/main/java/com/songoda/core/SongodaCore.java
@@ -46,7 +46,7 @@ public class SongodaCore {
* Whenever we make a major change to the core GUI, updater,
* or other function used by the core, increment this number
*/
- private final static int coreRevision = 3;
+ private final static int coreRevision = 4;
private final static int updaterVersion = 1;
private final static Set registeredPlugins = new HashSet<>();
diff --git a/src/main/java/com/songoda/core/compatibility/LegacyMaterials.java b/src/main/java/com/songoda/core/compatibility/LegacyMaterials.java
index 24951086..39940d1e 100644
--- a/src/main/java/com/songoda/core/compatibility/LegacyMaterials.java
+++ b/src/main/java/com/songoda/core/compatibility/LegacyMaterials.java
@@ -1022,15 +1022,17 @@ public enum LegacyMaterials {
private static final Map lookupMap = new HashMap();
static {
- for (LegacyMaterials m : values()) {
- lookupMap.put(m.name(), m);
- lookupMap.put(m.material + ":" + (m.data == null ? "" : m.data), m);
- }
- for (LegacyMaterials m : values()) {
- if (!lookupMap.containsKey(m.legacy)) {
- lookupMap.put(m.legacy, m);
- }
- }
+ for (LegacyMaterials m : values()) {
+ lookupMap.put(m.name(), m);
+ if (!m.usesCompatibility()) {
+ lookupMap.put(m.material + ":" + (m.data == null ? "" : m.data), m);
+ }
+ }
+ for (LegacyMaterials m : values()) {
+ if (!m.usesCompatibility() && !lookupMap.containsKey(m.legacy)) {
+ lookupMap.put(m.legacy, m);
+ }
+ }
}
LegacyMaterials() {
@@ -1902,6 +1904,7 @@ public enum LegacyMaterials {
case DRAGON_WALL_HEAD:
case END_GATEWAY:
case END_PORTAL:
+ case FARMLAND:
case FIRE: // used to be able to in older versions
case FIRE_CORAL_WALL_FAN:
case FROSTED_ICE:
diff --git a/src/main/java/com/songoda/core/core/LocaleModule.java b/src/main/java/com/songoda/core/core/LocaleModule.java
index f2bb20a9..8d8a5908 100644
--- a/src/main/java/com/songoda/core/core/LocaleModule.java
+++ b/src/main/java/com/songoda/core/core/LocaleModule.java
@@ -1,6 +1,5 @@
package com.songoda.core.core;
-import com.songoda.core.core.PluginInfoModule;
import com.songoda.core.locale.Locale;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
@@ -35,8 +34,24 @@ public class LocaleModule implements PluginInfoModule {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
urlConnection.setRequestProperty("Accept", "*/*");
+ urlConnection.setInstanceFollowRedirects(true);
urlConnection.setConnectTimeout(5000);
+ // do we need to follow a redirect?
+ int status = urlConnection.getResponseCode();
+ if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM || status == HttpURLConnection.HTTP_SEE_OTHER) {
+ // get redirect url from "location" header field
+ String newUrl = urlConnection.getHeaderField("Location");
+ // get the cookie if needed
+ String cookies = urlConnection.getHeaderField("Set-Cookie");
+ // open the new connnection again
+ urlConnection = (HttpURLConnection) new URL(newUrl).openConnection();
+ urlConnection.setRequestProperty("Cookie", cookies);
+ urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
+ urlConnection.setRequestProperty("Accept", "*/*");
+ urlConnection.setConnectTimeout(5000);
+ }
+
Locale.saveLocale(plugin.getJavaPlugin(), urlConnection.getInputStream(), fileName);
urlConnection.disconnect();
diff --git a/src/main/java/com/songoda/core/gui/Gui.java b/src/main/java/com/songoda/core/gui/Gui.java
index 9fc91b8c..2304d017 100644
--- a/src/main/java/com/songoda/core/gui/Gui.java
+++ b/src/main/java/com/songoda/core/gui/Gui.java
@@ -18,7 +18,6 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
@@ -40,7 +39,7 @@ public class Gui {
protected Inventory inventory;
protected String title;
protected GuiType inventoryType = GuiType.STANDARD;
- protected int rows, page, pages;
+ protected int rows, page = 1, pages = 1;
protected boolean acceptsItems = false;
protected boolean allowDropItems = true;
protected boolean allowClose = true;
@@ -48,11 +47,12 @@ public class Gui {
protected final Map cellItems = new HashMap<>();
protected final Map> conditionalButtons = new HashMap<>();
protected ItemStack blankItem = GuiUtils.getBorderGlassItem();
- protected int nextPageIndex, prevPageIndex;
+ protected int nextPageIndex = -1, prevPageIndex = -1;
protected ItemStack nextPage, prevPage;
protected Gui parent = null;
protected static ItemStack AIR = new ItemStack(Material.AIR);
+ protected GuiManager guiManager;
protected boolean open = false;
protected Clickable defaultClicker = null;
protected Openable opener = null;
@@ -205,7 +205,21 @@ public class Gui {
@NotNull
public Gui setTitle(String title) {
- this.title = title;
+ if (title == null) title = "";
+ if (!title.equals(this.title)) {
+ this.title = title;
+ if (inventory != null) {
+ // update active inventory
+ List toUpdate = getPlayers();
+ boolean isAllowClose = allowClose;
+ exit();
+ Inventory oldInv = inventory;
+ createInventory();
+ inventory.setContents(oldInv.getContents());
+ toUpdate.forEach(player -> player.openInventory(inventory));
+ allowClose = isAllowClose;
+ }
+ }
return this;
}
@@ -547,7 +561,7 @@ public class Gui {
public Gui setNextPage(int cell, @NotNull ItemStack item) {
nextPageIndex = cell;
if (page < pages) {
- setButton(nextPageIndex, nextPage = item, ClickType.LEFT, (event) -> this.nextPage(event.manager));
+ setButton(nextPageIndex, nextPage = item, ClickType.LEFT, (event) -> this.nextPage());
}
return this;
}
@@ -556,7 +570,7 @@ public class Gui {
public Gui setNextPage(int row, int col, @NotNull ItemStack item) {
nextPageIndex = col + row * 9;
if (page < pages) {
- setButton(nextPageIndex, nextPage = item, ClickType.LEFT, (event) -> this.nextPage(event.manager));
+ setButton(nextPageIndex, nextPage = item, ClickType.LEFT, (event) -> this.nextPage());
}
return this;
}
@@ -565,7 +579,7 @@ public class Gui {
public Gui setPrevPage(int cell, @NotNull ItemStack item) {
prevPageIndex = cell;
if (page > 1) {
- setButton(prevPageIndex, prevPage = item, ClickType.LEFT, (event) -> this.prevPage(event.manager));
+ setButton(prevPageIndex, prevPage = item, ClickType.LEFT, (event) -> this.prevPage());
}
return this;
}
@@ -574,18 +588,38 @@ public class Gui {
public Gui setPrevPage(int row, int col, @NotNull ItemStack item) {
prevPageIndex = col + row * 9;
if (page > 1) {
- setButton(prevPageIndex, prevPage = item, ClickType.LEFT, (event) -> this.prevPage(event.manager));
+ setButton(prevPageIndex, prevPage = item, ClickType.LEFT, (event) -> this.prevPage());
}
return this;
}
- public void nextPage(@NotNull GuiManager manager) {
+ public void setPage(int page) {
+ int lastPage = page;
+ this.page = Math.max(1, Math.min(pages, page));
+ if(pager != null && this.page != lastPage) {
+ pager.onPageChange(new GuiPageEvent(this, guiManager, lastPage, page));
+ // page markers
+ updatePageNavigation();
+ }
+ }
+
+ public void changePage(int direction) {
+ int lastPage = page;
+ this.page = Math.max(1, Math.min(pages, page + direction));
+ if(pager != null && this.page != lastPage) {
+ pager.onPageChange(new GuiPageEvent(this, guiManager, lastPage, page));
+ // page markers
+ updatePageNavigation();
+ }
+ }
+
+ public void nextPage() {
if (page < pages) {
int lastPage = page;
++page;
// page switch events
if (pager != null) {
- pager.onPageChange(new GuiPageEvent(this, manager, lastPage, page));
+ pager.onPageChange(new GuiPageEvent(this, guiManager, lastPage, page));
// page markers
updatePageNavigation();
@@ -597,12 +631,12 @@ public class Gui {
}
}
- public void prevPage(@NotNull GuiManager manager) {
+ public void prevPage() {
if (page > 1) {
int lastPage = page;
--page;
if (pager != null) {
- pager.onPageChange(new GuiPageEvent(this, manager, lastPage, page));
+ pager.onPageChange(new GuiPageEvent(this, guiManager, lastPage, page));
// page markers
updatePageNavigation();
@@ -615,17 +649,21 @@ public class Gui {
}
protected void updatePageNavigation() {
- if (page > 1) {
- this.setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage(event.manager));
- } else {
- this.setItem(prevPageIndex, null);
- this.clearActions(prevPageIndex);
+ if(prevPage != null) {
+ if (page > 1) {
+ this.setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage());
+ } else {
+ this.setItem(prevPageIndex, null);
+ this.clearActions(prevPageIndex);
+ }
}
- if (pages > 1 && page != pages) {
- this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage(event.manager));
- } else {
- this.setItem(nextPageIndex, null);
- this.clearActions(nextPageIndex);
+ if(nextPage != null) {
+ if (pages > 1 && page != pages) {
+ this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage());
+ } else {
+ this.setItem(nextPageIndex, null);
+ this.clearActions(nextPageIndex);
+ }
}
}
@@ -636,19 +674,10 @@ public class Gui {
@NotNull
protected Inventory generateInventory(@NotNull GuiManager manager) {
+ this.guiManager = manager;
final int cells = rows * 9;
- InventoryType t = inventoryType == null ? InventoryType.CHEST : inventoryType.type;
- switch (t) {
- case DISPENSER:
- case HOPPER:
- inventory = Bukkit.getServer().createInventory(new GuiHolder(manager, this), t,
- title == null ? "" : trimTitle(ChatColor.translateAlternateColorCodes('&', title)));
- break;
- default:
- inventory = Bukkit.getServer().createInventory(new GuiHolder(manager, this), cells,
- title == null ? "" : trimTitle(ChatColor.translateAlternateColorCodes('&', title)));
- }
+ createInventory();
for (int i = 0; i < cells; ++i) {
final ItemStack item = cellItems.get(i);
inventory.setItem(i, item != null ? item : (unlockedCells.getOrDefault(i, false) ? AIR : blankItem));
@@ -657,6 +686,20 @@ public class Gui {
return inventory;
}
+ protected void createInventory() {
+ final InventoryType t = inventoryType == null ? InventoryType.CHEST : inventoryType.type;
+ switch (t) {
+ case DISPENSER:
+ case HOPPER:
+ inventory = Bukkit.getServer().createInventory(new GuiHolder(guiManager, this), t,
+ title == null ? "" : trimTitle(title));
+ break;
+ default:
+ inventory = Bukkit.getServer().createInventory(new GuiHolder(guiManager, this), rows * 9,
+ title == null ? "" : trimTitle(title));
+ }
+ }
+
@Nullable
public Gui getParent() {
return parent;
@@ -674,7 +717,9 @@ public class Gui {
}
protected static String trimTitle(String title) {
- if (title != null && title.length() > 32) {
+ if(title == null) {
+ return "";
+ } else if (title != null && title.length() > 32) {
return title.substring(0, 31);
}
return title;
@@ -709,6 +754,7 @@ public class Gui {
public void onOpen(@NotNull GuiManager manager, @NotNull Player player) {
open = true;
+ guiManager = manager;
if (opener != null) {
opener.onOpen(new GuiOpenEvent(manager, this, player));
}
@@ -719,11 +765,12 @@ public class Gui {
manager.showGUI(player, this);
return;
}
+ boolean showParent = open && parent != null;
if (open && closer != null) {
- open = inventory.getViewers().isEmpty();
+ open = !inventory.getViewers().isEmpty();
closer.onClose(new GuiCloseEvent(manager, this, player));
}
- if (parent != null) {
+ if (showParent) {
manager.showGUI(player, parent);
}
}
diff --git a/src/main/java/com/songoda/core/gui/GuiManager.java b/src/main/java/com/songoda/core/gui/GuiManager.java
index 426b3a6f..d68d2836 100644
--- a/src/main/java/com/songoda/core/gui/GuiManager.java
+++ b/src/main/java/com/songoda/core/gui/GuiManager.java
@@ -36,6 +36,7 @@ public class GuiManager {
final UUID uuid = UUID.randomUUID(); // manager tracking to fix weird bugs from lazy programming
final GuiListener listener = new GuiListener(this);
final Map openInventories = new HashMap();
+ private final Object lock = new Object();
private boolean initialized = false;
private boolean shutdown = false;
@@ -77,14 +78,20 @@ public class GuiManager {
} else if (!initialized) {
init();
}
- Gui openInv = openInventories.get(player);
- if(openInv != null) {
- openInv.open = false;
- }
- Inventory inv = gui.getOrCreateInventory(this);
- player.openInventory(inv);
- gui.onOpen(this, player);
- openInventories.put(player, gui);
+ Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
+ Gui openInv = openInventories.get(player);
+ if (openInv != null) {
+ openInv.open = false;
+ }
+ Inventory inv = gui.getOrCreateInventory(this);
+ Bukkit.getScheduler().runTask(plugin, () -> {
+ player.openInventory(inv);
+ gui.onOpen(this, player);
+ synchronized(lock) {
+ openInventories.put(player, gui);
+ }
+ });
+ });
}
public void showPopup(Player player, String message) {
@@ -115,11 +122,13 @@ public class GuiManager {
* Close all active GUIs
*/
public void closeAll() {
- openInventories.entrySet().stream()
- .filter(e -> e.getKey().getOpenInventory().getTopInventory().getHolder() instanceof GuiHolder)
- .collect(Collectors.toList()) // to prevent concurrency exceptions
- .forEach(e -> e.getKey().closeInventory());
- openInventories.clear();
+ synchronized(lock) {
+ openInventories.entrySet().stream()
+ .filter(e -> e.getKey().getOpenInventory().getTopInventory().getHolder() instanceof GuiHolder)
+ .collect(Collectors.toList()) // to prevent concurrency exceptions
+ .forEach(e -> e.getKey().closeInventory());
+ openInventories.clear();
+ }
}
protected static class GuiListener implements Listener {
diff --git a/src/main/java/com/songoda/core/gui/GuiUtils.java b/src/main/java/com/songoda/core/gui/GuiUtils.java
index 3b1e6dbe..c445fec2 100644
--- a/src/main/java/com/songoda/core/gui/GuiUtils.java
+++ b/src/main/java/com/songoda/core/gui/GuiUtils.java
@@ -103,6 +103,22 @@ public class GuiUtils {
return item;
}
+ public static ItemStack createButtonItem(LegacyMaterials mat, int amount, String title, String... lore) {
+ ItemStack item = mat.getItem();
+ item.setAmount(amount);
+ ItemMeta meta = item.getItemMeta();
+ if (meta != null) {
+ meta.setDisplayName(title);
+ if (lore != null) {
+ meta.setLore(getSafeLore(lore));
+ } else {
+ meta.setLore(Collections.EMPTY_LIST);
+ }
+ item.setItemMeta(meta);
+ }
+ return item;
+ }
+
public static ItemStack createButtonItem(ItemStack from, String title, String... lore) {
ItemStack item = from.clone();
ItemMeta meta = item.getItemMeta();
@@ -133,6 +149,22 @@ public class GuiUtils {
return item;
}
+ public static ItemStack createButtonItem(LegacyMaterials mat, int amount, String title, List lore) {
+ ItemStack item = mat.getItem();
+ item.setAmount(amount);
+ ItemMeta meta = item.getItemMeta();
+ if (meta != null) {
+ meta.setDisplayName(title);
+ if (lore != null) {
+ meta.setLore(getSafeLore(lore));
+ } else {
+ meta.setLore(Collections.EMPTY_LIST);
+ }
+ }
+ item.setItemMeta(meta);
+ return item;
+ }
+
public static ItemStack createButtonItem(ItemStack from, String title, List lore) {
ItemStack item = from.clone();
ItemMeta meta = item.getItemMeta();
diff --git a/src/main/java/com/songoda/core/gui/SimplePagedGui.java b/src/main/java/com/songoda/core/gui/SimplePagedGui.java
index f966db89..c636a8c6 100644
--- a/src/main/java/com/songoda/core/gui/SimplePagedGui.java
+++ b/src/main/java/com/songoda/core/gui/SimplePagedGui.java
@@ -80,7 +80,7 @@ public class SimplePagedGui extends Gui {
}
@Override
- public void nextPage(GuiManager manager) {
+ public void nextPage() {
if (page < pages) {
++page;
showPage();
@@ -88,7 +88,7 @@ public class SimplePagedGui extends Gui {
}
@Override
- public void prevPage(GuiManager manager) {
+ public void prevPage() {
if (page > 1) {
--page;
showPage();
@@ -111,7 +111,7 @@ public class SimplePagedGui extends Gui {
protected void updatePageNavigation() {
if (page > 1) {
inventory.setItem(inventory.getSize() - prevPageIndex, prevPage);
- this.setButton(-prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage(event.manager));
+ this.setButton(-prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage());
} else {
inventory.setItem(inventory.getSize() - prevPageIndex, footerBackItem != null ? footerBackItem : blankItem);
this.setItem(-prevPageIndex, null);
@@ -119,7 +119,7 @@ public class SimplePagedGui extends Gui {
}
if (pages > 1 && page != pages) {
inventory.setItem(inventory.getSize() - nextPageIndex, nextPage);
- this.setButton(-nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage(event.manager));
+ this.setButton(-nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage());
} else {
inventory.setItem(inventory.getSize() - nextPageIndex, footerBackItem != null ? footerBackItem : blankItem);
this.setItem(-nextPageIndex, null);
@@ -129,6 +129,7 @@ public class SimplePagedGui extends Gui {
@Override
protected Inventory generateInventory(GuiManager manager) {
+ this.guiManager = manager;
// calculate pages here
rowsPerPage = useHeader ? 4 : 5;
maxCellSlot = (this.cellItems.isEmpty() ? 0 : this.cellItems.keySet().stream().max(Integer::compare).get()) + 1;
@@ -137,16 +138,21 @@ public class SimplePagedGui extends Gui {
this.setRows(maxRows + (useHeader ? 1 : 0));
// create inventory view
- final int cells = rows * 9;
- inventory = Bukkit.getServer().createInventory(new GuiHolder(manager, this), cells,
- title == null ? "" : trimTitle(ChatColor.translateAlternateColorCodes('&', title)));
+ createInventory();
// populate and return the display inventory
- page = 1;
+ page = Math.min(page, pages);
update();
return inventory;
}
+ @Override
+ protected void createInventory() {
+ final int cells = rows * 9;
+ inventory = Bukkit.getServer().createInventory(new GuiHolder(guiManager, this), cells,
+ title == null ? "" : trimTitle(title));
+ }
+
@Override
public void update() {
if (inventory == null) {
@@ -164,8 +170,7 @@ public class SimplePagedGui extends Gui {
if (Math.min(54, (maxRows + (useHeader ? 1 : 0)) * 9) != inventory.getSize()) {
toUpdate = getPlayers();
this.setRows(maxRows + (useHeader ? 1 : 0));
- inventory = Bukkit.getServer().createInventory(inventory.getHolder(), rows * 9,
- title == null ? "" : trimTitle(ChatColor.translateAlternateColorCodes('&', title)));
+ createInventory();
}
// populate header
@@ -189,7 +194,7 @@ public class SimplePagedGui extends Gui {
if(toUpdate != null) {
// whoopsie!
exit();
- toUpdate.forEach(player -> ((GuiHolder) inventory.getHolder()).manager.showGUI(player, this));
+ toUpdate.forEach(player -> guiManager.showGUI(player, this));
}
}
diff --git a/src/main/java/com/songoda/core/hooks/PluginHook.java b/src/main/java/com/songoda/core/hooks/PluginHook.java
index f131d57f..7042fb1b 100644
--- a/src/main/java/com/songoda/core/hooks/PluginHook.java
+++ b/src/main/java/com/songoda/core/hooks/PluginHook.java
@@ -64,6 +64,22 @@ public final class PluginHook {
}
}
+ /**
+ * Add a hook handler for us to use later.
+ * NOTE: The class passed MUST extend Hook.
+ * Permissible constructors are empty () or (org.bukkit.plugin.Plugin)
+ * Each plugin defined must use a different handler class.
+ *
+ * @param
+ * @param type Generic hook type for this plugin
+ * @param pluginName Plugin name
+ * @param handler Specific class that will handle this plugin, if enabled.
+ * @return instance of the PluginHook that was added
+ */
+ public static PluginHook addHook(T type, String pluginName, Class handler) {
+ return new PluginHook(type, pluginName, handler);
+ }
+
protected static Map loadHooks(Class type, Plugin plugin) {
Map loaded = new LinkedHashMap<>();
PluginManager pluginManager = Bukkit.getPluginManager();