diff --git a/pom.xml b/pom.xml
index 9734812..c63ff9b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,6 +55,10 @@
org.bstats
nl.sbdeveloper.themeparkplus.libs.bstats
+
+ com.samjakob.spigui
+ nl.sbdeveloper.themeparkplus.libs.spigui
+
@@ -172,5 +176,20 @@
worldguardwrapper
1.1.9-SNAPSHOT
+
+ com.samjakob
+ SpiGUI
+ v1.1
+
+
+ org.spigotmc
+ spigot-api
+
+
+ org.bukkit
+ bukkit
+
+
+
diff --git a/src/main/lombok/nl/sbdeveloper/themeparkplus/ThemeParkPlus.java b/src/main/lombok/nl/sbdeveloper/themeparkplus/ThemeParkPlus.java
index fa23474..9ddb15b 100644
--- a/src/main/lombok/nl/sbdeveloper/themeparkplus/ThemeParkPlus.java
+++ b/src/main/lombok/nl/sbdeveloper/themeparkplus/ThemeParkPlus.java
@@ -1,5 +1,6 @@
package nl.sbdeveloper.themeparkplus;
+import com.samjakob.spigui.SpiGUI;
import net.milkbowl.vault.economy.Economy;
import nl.sbdeveloper.themeparkplus.commands.TPPCMD;
import nl.sbdeveloper.themeparkplus.commands.TPPTabComplete;
@@ -32,7 +33,9 @@ public final class ThemeParkPlus extends JavaPlugin {
private static Economy econ = null;
private static String webhookURL;
- private final int configVersion = 2;
+ private static SpiGUI spiGUI;
+
+ private final int configVersion = 3;
@Override
public void onEnable() {
@@ -140,6 +143,7 @@ public final class ThemeParkPlus extends JavaPlugin {
Bukkit.getPluginManager().registerEvents(new DirectionalGateListener(), this);
Bukkit.getPluginManager().registerEvents(new FastpassListeners(), this);
Bukkit.getPluginManager().registerEvents(new SignListeners(), this);
+ Bukkit.getPluginManager().registerEvents(new MalfunctionListener(), this);
Bukkit.getPluginManager().registerEvents(new WaitingTimeListener(), this);
if (getSConfig().getFile().getBoolean("AntiFreerun.Enabled")) {
Bukkit.getPluginManager().registerEvents(new AntiFreerunListener(), this);
@@ -157,6 +161,10 @@ public final class ThemeParkPlus extends JavaPlugin {
}
}
+ Bukkit.getLogger().info("[ThemeParkPlus] Loading GUI helper...");
+ spiGUI = new SpiGUI(this);
+ spiGUI.setEnableAutomaticPagination(false);
+
Bukkit.getLogger().info("[ThemeParkPlus] Loading data...");
try {
data.load();
@@ -205,6 +213,10 @@ public final class ThemeParkPlus extends JavaPlugin {
return webhookURL;
}
+ public static SpiGUI getSpiGUI() {
+ return spiGUI;
+ }
+
private boolean setupEconomy() {
if (getServer().getPluginManager().getPlugin("Vault") == null) {
return false;
diff --git a/src/main/lombok/nl/sbdeveloper/themeparkplus/api/PlusAPI.java b/src/main/lombok/nl/sbdeveloper/themeparkplus/api/PlusAPI.java
index 22f44ed..8a9d029 100644
--- a/src/main/lombok/nl/sbdeveloper/themeparkplus/api/PlusAPI.java
+++ b/src/main/lombok/nl/sbdeveloper/themeparkplus/api/PlusAPI.java
@@ -4,6 +4,7 @@ import de.tr7zw.changeme.nbtapi.NBTItem;
import nl.iobyte.themepark.api.attraction.Attraction;
import nl.sbdeveloper.themeparkplus.ThemeParkPlus;
import nl.sbdeveloper.themeparkplus.api.objects.Gate;
+import nl.sbdeveloper.themeparkplus.api.objects.MalfunctionReport;
import nl.sbdeveloper.themeparkplus.api.objects.WaitingRow;
import nl.sbdeveloper.themeparkplus.util.ConfigUtil;
import nl.sbdeveloper.themeparkplus.util.XMaterial;
@@ -18,8 +19,25 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
public class PlusAPI {
- private static HashMap gates = new HashMap<>();
- private static HashMap rows = new HashMap<>();
+ private static final HashMap gates = new HashMap<>();
+ private static final HashMap rows = new HashMap<>();
+ private static final HashMap reports = new HashMap<>();
+
+ public static void addReport(MalfunctionReport report) {
+ reports.put(report.getRideID(), report);
+ }
+
+ public static void removeReport(String rideID) {
+ reports.remove(rideID);
+ }
+
+ public static MalfunctionReport getReport(String rideID) {
+ return reports.get(rideID);
+ }
+
+ public static boolean isReported(String rideID) {
+ return reports.containsKey(rideID);
+ }
/**
* Add a gate
diff --git a/src/main/lombok/nl/sbdeveloper/themeparkplus/api/objects/MalfunctionReport.java b/src/main/lombok/nl/sbdeveloper/themeparkplus/api/objects/MalfunctionReport.java
index ac67429..3fc8892 100644
--- a/src/main/lombok/nl/sbdeveloper/themeparkplus/api/objects/MalfunctionReport.java
+++ b/src/main/lombok/nl/sbdeveloper/themeparkplus/api/objects/MalfunctionReport.java
@@ -1,18 +1,19 @@
package nl.sbdeveloper.themeparkplus.api.objects;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
+import lombok.*;
import java.time.LocalDateTime;
import java.util.UUID;
-/** @deprecated Please don't use! It's not implemented yet. */
-@Getter @Setter @NoArgsConstructor @AllArgsConstructor
+@Getter @NoArgsConstructor
public class MalfunctionReport {
- private String rideID;
- private UUID reporterUUID;
- private LocalDateTime reportDate;
- private String reason;
+ @Getter private String rideID;
+ @Getter private UUID reporterUUID;
+ @Getter private final LocalDateTime reportDate = LocalDateTime.now();
+ @Getter @Setter private String reason = "Unknown";
+
+ public MalfunctionReport(String rideID, UUID reporterUUID) {
+ this.rideID = rideID;
+ this.reporterUUID = reporterUUID;
+ }
}
diff --git a/src/main/lombok/nl/sbdeveloper/themeparkplus/gui/MalfunctionGUI.java b/src/main/lombok/nl/sbdeveloper/themeparkplus/gui/MalfunctionGUI.java
new file mode 100644
index 0000000..2c3e7c9
--- /dev/null
+++ b/src/main/lombok/nl/sbdeveloper/themeparkplus/gui/MalfunctionGUI.java
@@ -0,0 +1,102 @@
+package nl.sbdeveloper.themeparkplus.gui;
+
+import com.samjakob.spigui.SGMenu;
+import com.samjakob.spigui.buttons.SGButton;
+import com.samjakob.spigui.item.ItemBuilder;
+import nl.iobyte.themepark.api.API;
+import nl.iobyte.themepark.api.attraction.Attraction;
+import nl.iobyte.themepark.api.attraction.component.Status;
+import nl.sbdeveloper.themeparkplus.ThemeParkPlus;
+import nl.sbdeveloper.themeparkplus.api.PlusAPI;
+import nl.sbdeveloper.themeparkplus.api.objects.MalfunctionReport;
+import nl.sbdeveloper.themeparkplus.util.ConfigUtil;
+import nl.sbdeveloper.themeparkplus.util.XMaterial;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.inventory.ItemStack;
+
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class MalfunctionGUI {
+ public static void open(Attraction att, Player p) {
+ SGMenu menu = ThemeParkPlus.getSpiGUI().create(ConfigUtil.makecolored(ThemeParkPlus.getSConfig().getFile().getString("Malfunction.GUI.Title").replace("%ridename%", att.getId())), 1);
+
+ SGButton report = new SGButton(getItem("Report", ConfigUtil.makecolored(att.getName()))).withListener((InventoryClickEvent e) -> {
+ if (!PlusAPI.isReported(att.getId())) {
+ MalfunctionReport malfunctionReport = new MalfunctionReport(att.getId(), p.getUniqueId());
+ PlusAPI.addReport(malfunctionReport);
+ att.setStatus(Status.MALFUNCTION, null); //Player must be null, otherwise we will get a loop in the listener
+
+ //TODO Send message
+ } else {
+ //TODO Already reported
+ }
+ p.closeInventory();
+ });
+ menu.setButton(getSlot("Report"), report);
+
+ SGButton fix = new SGButton(getItem("Fix", PlusAPI.getReport(att.getId()))).withListener((InventoryClickEvent e) -> {
+ if (PlusAPI.isReported(att.getId())) {
+
+ PlusAPI.removeReport(att.getId());
+ att.setStatus(Status.CLOSED, null); //Player must be null, otherwise we will get a loop in the listener
+
+ //TODO Send message
+ } else {
+ //TODO No malfunction
+ }
+ p.closeInventory();
+ });
+ menu.setButton(getSlot("Fix"), fix);
+
+ SGButton cancel = new SGButton(getItem("Cancel")).withListener((InventoryClickEvent e) -> p.closeInventory());
+ menu.setButton(getSlot("Cancel"), cancel);
+
+ p.openInventory(menu.getInventory());
+ }
+
+ private static int getSlot(String type) {
+ return ThemeParkPlus.getSConfig().getFile().getInt("Malfunction.GUI.Buttons." + type + ".Slot");
+ }
+
+ private static ItemStack getItem(String type, Object... data) { //data is a string or a report
+ String material = ThemeParkPlus.getSConfig().getFile().getString("Malfunction.GUI.Buttons." + type + ".Material");
+ String name = ThemeParkPlus.getSConfig().getFile().getString("Malfunction.GUI.Buttons." + type + ".Name");
+ List lores = ThemeParkPlus.getSConfig().getFile().getStringList("Malfunction.GUI.Buttons." + type + ".Lores");
+
+ if (material == null || name == null || lores.isEmpty()) return null; //Something is wrong in the config
+
+ List loresFormatted = new ArrayList<>();
+ switch (type) {
+ case "Report":
+ lores.forEach(lore -> loresFormatted.add(lore.replace("%ridename%", (String) data[0])));
+ break;
+ case "Fix":
+ String ridename = "this ride";
+ String reporter = "-";
+ String date = "-";
+ String reason = "-";
+ if (data[0] != null) {
+ ridename = API.getAttraction(((MalfunctionReport) data[0]).getRideID()).getName();
+ reporter = Bukkit.getOfflinePlayer(((MalfunctionReport) data[0]).getReporterUUID()).getName();
+ date = ((MalfunctionReport) data[0]).getReportDate().format(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss"));
+ reason = ((MalfunctionReport) data[0]).getReason();
+ }
+
+ for (String lore : lores) {
+ loresFormatted.add(lore.replace("%ridename%", ridename).replace("%reporter%", reporter).replace("%date%", date).replace("%reason%", reason));
+ }
+ break;
+ default:
+ break;
+ }
+
+ Optional stack = XMaterial.matchXMaterial(material);
+
+ return stack.map(xMaterial -> new ItemBuilder(xMaterial.parseItem()).name(name).lore(loresFormatted).build()).orElse(null);
+ }
+}
diff --git a/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/FastpassListeners.java b/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/FastpassListeners.java
index 121b53a..f4752a9 100644
--- a/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/FastpassListeners.java
+++ b/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/FastpassListeners.java
@@ -46,7 +46,6 @@ public class FastpassListeners implements Listener {
//Buy a ticket
String attID = sign.getLine(2);
if (!API.isAttraction(attID)) return;
-
Attraction att = API.getAttraction(attID);
double price;
diff --git a/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/MalfunctionListener.java b/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/MalfunctionListener.java
new file mode 100644
index 0000000..c09e865
--- /dev/null
+++ b/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/MalfunctionListener.java
@@ -0,0 +1,34 @@
+package nl.sbdeveloper.themeparkplus.listeners;
+
+import nl.iobyte.themepark.api.API;
+import nl.iobyte.themepark.api.attraction.Attraction;
+import nl.sbdeveloper.themeparkplus.ThemeParkPlus;
+import nl.sbdeveloper.themeparkplus.gui.MalfunctionGUI;
+import nl.sbdeveloper.themeparkplus.util.ConfigUtil;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.block.Sign;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.EquipmentSlot;
+
+public class MalfunctionListener implements Listener {
+ @EventHandler
+ public void onClickSign(PlayerInteractEvent e) {
+ if (e.getClickedBlock() == null || e.getAction() != Action.RIGHT_CLICK_BLOCK || !(e.getClickedBlock().getState() instanceof Sign) || e.getHand() != EquipmentSlot.HAND) return;
+
+ String mrLineOne = ChatColor.stripColor(ConfigUtil.makecolored(ThemeParkPlus.getSConfig().getFile().getString("Malfunction.Sign.Row1")));
+ String mrLineTwo = ChatColor.stripColor(ConfigUtil.makecolored(ThemeParkPlus.getSConfig().getFile().getString("Malfunction.Sign.Row2")));
+
+ Sign sign = (Sign) e.getClickedBlock().getState();
+ if (ChatColor.stripColor(sign.getLine(0)).equalsIgnoreCase(mrLineOne) && ChatColor.stripColor(sign.getLine(1)).equalsIgnoreCase(mrLineTwo)) {
+ String attID = sign.getLine(2);
+ if (!API.isAttraction(attID)) return;
+ Attraction att = API.getAttraction(attID);
+
+ MalfunctionGUI.open(att, e.getPlayer());
+ }
+ }
+}
diff --git a/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/SignListeners.java b/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/SignListeners.java
index 30276ed..41ea2a1 100644
--- a/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/SignListeners.java
+++ b/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/SignListeners.java
@@ -52,6 +52,8 @@ public class SignListeners implements Listener {
String sLineTwo = ConfigUtil.makecolored(ThemeParkPlus.getSConfig().getFile().getString("Fastpass.ScannerSign.Row2"));
String wrLineOne = ConfigUtil.makecolored(ThemeParkPlus.getSConfig().getFile().getString("WaitingRow.Sign.Row1"));
String wrLineTwo = ConfigUtil.makecolored(ThemeParkPlus.getSConfig().getFile().getString("WaitingRow.Sign.Row2"));
+ String mrLineOne = ConfigUtil.makecolored(ThemeParkPlus.getSConfig().getFile().getString("Malfunction.Sign.Row1"));
+ String mrLineTwo = ConfigUtil.makecolored(ThemeParkPlus.getSConfig().getFile().getString("Malfunction.Sign.Row2"));
if (lines[1].equalsIgnoreCase("Machine") && !lines[2].isEmpty() && !lines[3].isEmpty()) {
e.setLine(0, mLineOne);
@@ -78,6 +80,9 @@ public class SignListeners implements Listener {
e.setLine(3, "0 min.");
p.sendMessage(ConfigUtil.getMessage("WaitingRow.SignCreated"));
+ } else if (lines[1].equalsIgnoreCase("Malfunction") && !lines[2].isEmpty()) {
+ e.setLine(0, mrLineOne);
+ e.setLine(1, mrLineTwo);
} else {
p.sendMessage(ConfigUtil.getMessage("General.IncorrectSign"));
}
diff --git a/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/StatusChangeListener.java b/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/StatusChangeListener.java
index 7280ca8..0025ae4 100644
--- a/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/StatusChangeListener.java
+++ b/src/main/lombok/nl/sbdeveloper/themeparkplus/listeners/StatusChangeListener.java
@@ -1,9 +1,13 @@
package nl.sbdeveloper.themeparkplus.listeners;
+import nl.iobyte.themepark.api.attraction.Attraction;
import nl.iobyte.themepark.api.attraction.component.Status;
import nl.iobyte.themepark.api.attraction.manager.StatusManager;
import nl.iobyte.themepark.api.events.attraction.ChangeStatusEvent;
+import nl.iobyte.themepark.api.events.attraction.PreChangeStatusEvent;
import nl.sbdeveloper.themeparkplus.ThemeParkPlus;
+import nl.sbdeveloper.themeparkplus.api.PlusAPI;
+import nl.sbdeveloper.themeparkplus.api.objects.MalfunctionReport;
import nl.sbdeveloper.themeparkplus.util.ConfigUtil;
import nl.sbdeveloper.themeparkplus.util.DiscordWebhook;
import org.bukkit.Bukkit;
@@ -16,9 +20,33 @@ import java.awt.*;
import java.io.IOException;
/**
- * Status change listener for discord webhook
+ * Status change listener for malfunction menu and discord webhook
*/
public class StatusChangeListener implements Listener {
+ @EventHandler
+ public void onStatusChange(PreChangeStatusEvent e) {
+ Attraction att = e.getAttraction();
+
+ if (!PlusAPI.isReported(att.getId()) && e.getAfter() == Status.MALFUNCTION && e.getPlayer() != null) {
+ if (ThemeParkPlus.getSConfig().getFile().getBoolean("Malfunction.AllowCommandReport")) {
+ MalfunctionReport malfunctionReport = new MalfunctionReport(att.getId(), e.getPlayer().getUniqueId());
+ PlusAPI.addReport(malfunctionReport);
+ } else {
+ e.setCancelled(true);
+ e.getPlayer().sendMessage(ConfigUtil.getMessage("Malfunction.NoCommand"));
+ }
+ }
+
+ if (PlusAPI.isReported(att.getId()) && e.getAfter() != Status.MALFUNCTION && e.getPlayer() != null) {
+ if (ThemeParkPlus.getSConfig().getFile().getBoolean("Malfunction.AllowCommandFix")) {
+ PlusAPI.removeReport(att.getId());
+ } else {
+ e.setCancelled(true);
+ e.getPlayer().sendMessage(ConfigUtil.getMessage("Malfunction.NoCommand"));
+ }
+ }
+ }
+
@EventHandler
public void onStatusChange(@NotNull ChangeStatusEvent e) {
if (e.getAfter() != Status.GLOBAL) {
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index a94c745..a87d1e1 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -8,8 +8,41 @@ MessageInConsole: true
WaitingRow:
MinutesPerPlayer: 1.5
Sign:
- Row1: "&8[&6ThemeParkPlus&8]"
- Row2: "&bWaitingRow"
+ Row1: '&8[&6ThemeParkPlus&8]'
+ Row2: '&bWaitingRow'
+Malfunction:
+ AllowCommandReport: true
+ AllowCommandFix: false
+ Sign:
+ Row1: '&8[&6ThemeParkPlus&8]'
+ Row2: '&bMalfunction'
+ GUI:
+ Title: '&3Report Malfunction for %ridename%'
+ Buttons:
+ Report:
+ Slot: 2
+ Material: GREEN_WOOL
+ Name: '&2&lReport Malfunction'
+ Lores:
+ - '&fClick here to report malfunction for %ridename%.'
+ - '&r'
+ - '&cAbuse of this function is not allowed!'
+ Fix:
+ Slot: 4
+ Material: STONE_PICKAXE
+ Name: '&e&lFix Ride'
+ Lores:
+ - '&fClick here to fix %ridename%!'
+ - '&r'
+ - '&fReporter: &7%reporter%'
+ - '&fDate: &7%date%'
+ - '&fReason: &7%reason%'
+ Cancel:
+ Slot: 6
+ Material: RED_WOOL
+ Name: '&4&lCancel Report'
+ Lores:
+ - '&fClick here to cancel.'
Fastpass:
Item:
DisplayName: '&6Fastpass Ticket'
diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml
index 8749371..e346250 100644
--- a/src/main/resources/messages.yml
+++ b/src/main/resources/messages.yml
@@ -38,4 +38,6 @@ WaitingRow:
SignCreated: '&aYou''ve successfully created a waitingrow sign!'
WrongLocation: '&cA waitingrow sign (from the attraction %ridename%) couldn''t be found! It will be deleted.'
RedstoneTimer:
- Started: '&aThe timer successfully started. It will go off in &f%sec1% &asecond(s), and will turn off in &f%sec2% &asecond(s) after that.'
\ No newline at end of file
+ Started: '&aThe timer successfully started. It will go off in &f%sec1% &asecond(s), and will turn off in &f%sec2% &asecond(s) after that.'
+Malfunction:
+ NoCommand: '&cYou can''t report or fix a ride using the command. Please use this Malfunction Sign at the ride.'
\ No newline at end of file