diff --git a/src/main/java/com/songoda/ultimatemoderation/UltimateModeration.java b/src/main/java/com/songoda/ultimatemoderation/UltimateModeration.java index b07f3d5..31027ae 100644 --- a/src/main/java/com/songoda/ultimatemoderation/UltimateModeration.java +++ b/src/main/java/com/songoda/ultimatemoderation/UltimateModeration.java @@ -13,6 +13,10 @@ import com.songoda.ultimatemoderation.storage.Storage; import com.songoda.ultimatemoderation.storage.StorageRow; import com.songoda.ultimatemoderation.storage.types.StorageMysql; import com.songoda.ultimatemoderation.storage.types.StorageYaml; +import com.songoda.ultimatemoderation.tickets.Ticket; +import com.songoda.ultimatemoderation.tickets.TicketManager; +import com.songoda.ultimatemoderation.tickets.TicketResponse; +import com.songoda.ultimatemoderation.tickets.TicketStatus; import com.songoda.ultimatemoderation.utils.Methods; import com.songoda.ultimatemoderation.utils.SettingsManager; import com.songoda.ultimatemoderation.utils.gui.AbstractGUI; @@ -28,6 +32,7 @@ public class UltimateModeration extends JavaPlugin { private static UltimateModeration INSTANCE; private References references; + private TicketManager ticketManager; private TemplateManager templateManager; private SettingsManager settingsManager; private CommandManager commandManager; @@ -80,6 +85,7 @@ public class UltimateModeration extends JavaPlugin { this.references = new References(); // Setup Managers + this.ticketManager = new TicketManager(); this.templateManager = new TemplateManager(); this.commandManager = new CommandManager(this); this.punishmentManager = new PunishmentManager(); @@ -88,7 +94,6 @@ public class UltimateModeration extends JavaPlugin { this.checkStorage(); this.loadFromFile(); - // Register Listeners AbstractGUI.initializeListeners(this); Bukkit.getPluginManager().registerEvents(new CommandListener(this), this); @@ -162,6 +167,32 @@ public class UltimateModeration extends JavaPlugin { playerPunishData.addNotes(note); } } + + if (storage.containsGroup("tickets")) { + for (StorageRow row : storage.getRowsByGroup("tickets")) { + + int id = row.get("id").asInt(); + Ticket ticket = new Ticket( + UUID.fromString(row.get("player").asString()), + row.get("subject").asString()); + ticket.setTicketId(id); + ticket.setStatus(TicketStatus.valueOf(row.get("status").asString())); + ticketManager.addTicket(ticket, id); + } + } + + if (storage.containsGroup("ticketresponses")) { + for (StorageRow row : storage.getRowsByGroup("ticketresponses")) { + int id = row.get("ticketid").asInt(); + TicketResponse ticketResponse = new TicketResponse( + UUID.fromString(row.get("author").asString()), + row.get("message").asString(), + row.get("posted").asLong()); + ticketResponse.setTicketId(id); + ticketManager.getTicket(id).addResponse(ticketResponse); + + } + } storage.doSave(); } @@ -201,4 +232,8 @@ public class UltimateModeration extends JavaPlugin { public PunishmentManager getPunishmentManager() { return punishmentManager; } + + public TicketManager getTicketManager() { + return ticketManager; + } } diff --git a/src/main/java/com/songoda/ultimatemoderation/command/CommandManager.java b/src/main/java/com/songoda/ultimatemoderation/command/CommandManager.java index 7d5e233..ea59a5b 100644 --- a/src/main/java/com/songoda/ultimatemoderation/command/CommandManager.java +++ b/src/main/java/com/songoda/ultimatemoderation/command/CommandManager.java @@ -41,6 +41,7 @@ public class CommandManager implements CommandExecutor { instance.getCommand("UnMute").setExecutor(this); instance.getCommand("Warn").setExecutor(this); instance.getCommand("RunTemplate").setExecutor(this); + instance.getCommand("Ticket").setExecutor(this); AbstractCommand commandUltimateModeration = addCommand(new CommandUltimateModeration()); addCommand(new CommandClearChat()); @@ -60,6 +61,7 @@ public class CommandManager implements CommandExecutor { addCommand(new CommandUnMute()); addCommand(new CommandWarn()); addCommand(new CommandRunTemplate()); + addCommand(new CommandTicket()); addCommand(new CommandSettings(commandUltimateModeration)); addCommand(new CommandHelp(commandUltimateModeration)); diff --git a/src/main/java/com/songoda/ultimatemoderation/command/commands/CommandTicket.java b/src/main/java/com/songoda/ultimatemoderation/command/commands/CommandTicket.java new file mode 100644 index 0000000..1cbb826 --- /dev/null +++ b/src/main/java/com/songoda/ultimatemoderation/command/commands/CommandTicket.java @@ -0,0 +1,51 @@ +package com.songoda.ultimatemoderation.command.commands; + +import com.songoda.ultimatemoderation.UltimateModeration; +import com.songoda.ultimatemoderation.command.AbstractCommand; +import com.songoda.ultimatemoderation.gui.GUITicketManager; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class CommandTicket extends AbstractCommand { + + public CommandTicket() { + super(true, false, "Ticket"); + } + + @Override + protected ReturnType runCommand(UltimateModeration instance, CommandSender sender, String... args) { + Player senderP = ((Player) sender); + + GUITicketManager.createNew(senderP, senderP); + return ReturnType.SUCCESS; + } + + @Override + protected List onTab(UltimateModeration instance, CommandSender sender, String... args) { + return null; + } + + @Override + public String getPermissionNode() { + return "um.ticket"; + } + + @Override + public String getSyntax() { + return "/ticket"; + } + + @Override + public String getDescription() { + return "Opens the ticket interface."; + } + +} diff --git a/src/main/java/com/songoda/ultimatemoderation/gui/GUINotesManager.java b/src/main/java/com/songoda/ultimatemoderation/gui/GUINotesManager.java index 64cf264..aa743d0 100644 --- a/src/main/java/com/songoda/ultimatemoderation/gui/GUINotesManager.java +++ b/src/main/java/com/songoda/ultimatemoderation/gui/GUINotesManager.java @@ -41,7 +41,7 @@ public class GUINotesManager extends AbstractGUI { createButton(8, Material.OAK_DOOR, plugin.getLocale().getMessage("gui.general.back")); - createButton(6, Material.REDSTONE, plugin.getLocale().getMessage("gui.moderate.create")); + createButton(6, Material.REDSTONE, plugin.getLocale().getMessage("gui.notes.create")); for (int i = 0; i < 9; i++) createButton(9 + i, Material.GRAY_STAINED_GLASS_PANE, "&1"); @@ -75,9 +75,9 @@ public class GUINotesManager extends AbstractGUI { SimpleDateFormat format = new SimpleDateFormat("MM-dd-yyyy"); - lore.add(plugin.getLocale().getMessage("gui.moderate.createdby", Bukkit.getOfflinePlayer(note.getAuthor()).getName())); - lore.add(plugin.getLocale().getMessage("gui.moderate.createdon", format.format(new Date(note.getCreationDate())))); - lore.add(plugin.getLocale().getMessage("gui.moderate.remove")); + lore.add(plugin.getLocale().getMessage("gui.notes.createdby", Bukkit.getOfflinePlayer(note.getAuthor()).getName())); + lore.add(plugin.getLocale().getMessage("gui.notes.createdon", format.format(new Date(note.getCreationDate())))); + lore.add(plugin.getLocale().getMessage("gui.notes.remove")); createButton(18 + i, Material.MAP, name, lore); @@ -94,15 +94,18 @@ public class GUINotesManager extends AbstractGUI { @Override protected void registerClickables() { registerClickable(8, ((player1, inventory1, cursor, slot, type) -> - new GUIPlayers(plugin, player))); + new GUIPlayer(plugin, toModerate, player1))); registerClickable(6, ((player1, inventory1, cursor, slot, type) -> { - player.sendMessage(plugin.getLocale().getMessage("gui.moderate.type")); - new AbstractChatConfirm(player, event -> { + player.sendMessage(plugin.getLocale().getMessage("gui.notes.type")); + AbstractChatConfirm abstractChatConfirm = new AbstractChatConfirm(player, event -> { plugin.getPunishmentManager().getPlayer(toModerate).addNotes(new PunishmentNote(event.getMessage(), player.getUniqueId(), toModerate.getUniqueId(), System.currentTimeMillis())); constructGUI(); }); + + abstractChatConfirm.setOnClose(() -> + init(inventory.getTitle(), inventory.getSize())); })); } diff --git a/src/main/java/com/songoda/ultimatemoderation/gui/GUIPlayer.java b/src/main/java/com/songoda/ultimatemoderation/gui/GUIPlayer.java index b64eb87..5b7296e 100644 --- a/src/main/java/com/songoda/ultimatemoderation/gui/GUIPlayer.java +++ b/src/main/java/com/songoda/ultimatemoderation/gui/GUIPlayer.java @@ -19,7 +19,7 @@ public class GUIPlayer extends AbstractGUI { this.plugin = plugin; this.toModerate = toModerate; - init(plugin.getLocale().getMessage("gui.player.title", toModerate.getName()), 45); + init(plugin.getLocale().getMessage("gui.player.title", toModerate.getName()), 54); } @Override @@ -34,32 +34,31 @@ public class GUIPlayer extends AbstractGUI { createButton(8, Material.OAK_DOOR, plugin.getLocale().getMessage("gui.general.back")); createButton(28, Material.ANVIL, plugin.getLocale().getMessage("gui.player.punish")); - createButton(30, Material.DIAMOND_CHESTPLATE, plugin.getLocale().getMessage("gui.player.moderate")); + createButton(30, Material.CHEST, plugin.getLocale().getMessage("gui.player.tickets")); createButton(32, Material.DIAMOND_SWORD, plugin.getLocale().getMessage("gui.player.punishments")); createButton(34, Material.MAP, plugin.getLocale().getMessage("gui.player.notes")); + createButton(40, Material.DIAMOND_CHESTPLATE, plugin.getLocale().getMessage("gui.player.moderate")); } @Override protected void registerClickables() { - registerClickable(8, ((player1, inventory1, cursor, slot, type) -> { - new GUIPlayers(plugin, player1); - })); + registerClickable(8, ((player1, inventory1, cursor, slot, type) -> + new GUIPlayers(plugin, player1))); - registerClickable(28, ((player1, inventory1, cursor, slot, type) -> { - new GUIPunish(plugin, toModerate, null, player1); - })); + registerClickable(28, ((player1, inventory1, cursor, slot, type) -> + new GUIPunish(plugin, toModerate, null, player1))); - registerClickable(30, ((player1, inventory1, cursor, slot, type) -> { - new GUIModerate(plugin, toModerate, player1); - })); + registerClickable(30, ((player1, inventory1, cursor, slot, type) -> + new GUITicketManager(plugin, toModerate, player1))); - registerClickable(32, ((player1, inventory1, cursor, slot, type) -> { - new GUIPunishments(plugin, toModerate, player1); - })); + registerClickable(32, ((player1, inventory1, cursor, slot, type) -> + new GUIPunishments(plugin, toModerate, player1))); - registerClickable(34, ((player1, inventory1, cursor, slot, type) -> { - new GUINotesManager(plugin, toModerate, player1); - })); + registerClickable(34, ((player1, inventory1, cursor, slot, type) -> + new GUINotesManager(plugin, toModerate, player1))); + + registerClickable(40, ((player1, inventory1, cursor, slot, type) -> + new GUIModerate(plugin, toModerate, player1))); } @Override diff --git a/src/main/java/com/songoda/ultimatemoderation/gui/GUIPlayers.java b/src/main/java/com/songoda/ultimatemoderation/gui/GUIPlayers.java index 1cf5d47..4fe0ba1 100644 --- a/src/main/java/com/songoda/ultimatemoderation/gui/GUIPlayers.java +++ b/src/main/java/com/songoda/ultimatemoderation/gui/GUIPlayers.java @@ -72,6 +72,7 @@ public class GUIPlayers extends AbstractGUI { createButton(48, Material.ARROW, plugin.getLocale().getMessage("gui.general.next")); + createButton(51, Material.CHEST, "&7Tickets"); createButton(52, Material.MAP, plugin.getLocale().getMessage("gui.players.button.templatemanager")); } @@ -81,8 +82,11 @@ public class GUIPlayers extends AbstractGUI { @Override protected void registerClickables() { - registerClickable(52, ((player1, inventory1, cursor, slot, type) -> - new GUITemplateManager(plugin, player))); + registerClickable(51, (player1, inventory1, cursor, slot, type) -> + new GUITicketManager(plugin, null, player)); + + registerClickable(52, (player1, inventory1, cursor, slot, type) -> + new GUITemplateManager(plugin, player)); } @Override diff --git a/src/main/java/com/songoda/ultimatemoderation/gui/GUITemplateManager.java b/src/main/java/com/songoda/ultimatemoderation/gui/GUITemplateManager.java index 1c9448f..fc02cb7 100644 --- a/src/main/java/com/songoda/ultimatemoderation/gui/GUITemplateManager.java +++ b/src/main/java/com/songoda/ultimatemoderation/gui/GUITemplateManager.java @@ -59,7 +59,6 @@ public class GUITemplateManager extends AbstractGUI { } })); } - } @Override diff --git a/src/main/java/com/songoda/ultimatemoderation/gui/GUITicket.java b/src/main/java/com/songoda/ultimatemoderation/gui/GUITicket.java new file mode 100644 index 0000000..0c04c8b --- /dev/null +++ b/src/main/java/com/songoda/ultimatemoderation/gui/GUITicket.java @@ -0,0 +1,123 @@ +package com.songoda.ultimatemoderation.gui; + +import com.songoda.ultimatemoderation.UltimateModeration; +import com.songoda.ultimatemoderation.tickets.Ticket; +import com.songoda.ultimatemoderation.tickets.TicketResponse; +import com.songoda.ultimatemoderation.tickets.TicketStatus; +import com.songoda.ultimatemoderation.utils.AbstractChatConfirm; +import com.songoda.ultimatemoderation.utils.gui.AbstractAnvilGUI; +import com.songoda.ultimatemoderation.utils.gui.AbstractGUI; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class GUITicket extends AbstractGUI { + + private final UltimateModeration plugin; + + private final Ticket ticket; + + private final OfflinePlayer toModerate; + + public GUITicket(UltimateModeration plugin, Ticket ticket, OfflinePlayer toModerate, Player player) { + super(player); + this.ticket = ticket; + this.plugin = plugin; + this.toModerate = toModerate; + + init(plugin.getLocale().getMessage("gui.ticket.title", ticket.getTicketId()), 54); + } + + @Override + protected void constructGUI() { + inventory.clear(); + resetClickables(); + registerClickables(); + + createButton(1, Material.ARROW, plugin.getLocale().getMessage("gui.general.previous")); + + createButton(3, Material.ARROW, plugin.getLocale().getMessage("gui.general.next")); + + createButton(8, Material.OAK_DOOR, plugin.getLocale().getMessage("gui.general.back")); + + if (player.hasPermission("um.ticket.openclose")) + createButton(5, Material.REDSTONE, "&6" + ticket.getStatus().getStatus()); + + createButton(6, Material.REDSTONE, plugin.getLocale().getMessage("gui.ticket.respond")); + + for (int i = 0; i < 9; i++) + createButton(9 + i, Material.GRAY_STAINED_GLASS_PANE, "&1"); + + List responses = ticket.getResponses(); + + for (int i = 0; i < responses.size(); i++) { + TicketResponse ticketResponse = responses.get(i); + + String subjectStr = ticketResponse.getMessage(); + + ArrayList lore = new ArrayList<>(); + int lastIndex = 0; + for (int n = 0; n < subjectStr.length(); n++) { + if (n - lastIndex < 20) + continue; + + if (subjectStr.charAt(n) == ' ') { + lore.add("&6" +subjectStr.substring(lastIndex, n).trim()); + lastIndex = n; + } + } + + if (lastIndex - subjectStr.length() < 20) + lore.add("&6" + subjectStr.substring(lastIndex, subjectStr.length()).trim()); + + String name = lore.get(0); + lore.remove(0); + + lore.add(""); + + SimpleDateFormat format = new SimpleDateFormat("MM-dd-yyyy"); + + + lore.add(plugin.getLocale().getMessage("gui.ticket.postedby", Bukkit.getOfflinePlayer(ticketResponse.getAuthor()).getName() )); + lore.add(plugin.getLocale().getMessage("gui.ticket.createdon", format.format(new Date(ticketResponse.getPostedDate())))); + + createButton(18 + i, Material.MAP, name, lore); + } + } + + @Override + protected void registerClickables() { + if (player.hasPermission("um.ticket.openclose")) { + registerClickable(8, ((player1, inventory1, cursor, slot, type) -> + new GUITicketManager(plugin, toModerate, player))); + } + + registerClickable(5, ((player1, inventory1, cursor, slot, type) -> { + ticket.setStatus(ticket.getStatus() == TicketStatus.OPEN ? TicketStatus.CLOSED : TicketStatus.OPEN); + constructGUI(); + })); + + registerClickable(6, ((player1, inventory1, cursor, slot, type) -> { + player.sendMessage(plugin.getLocale().getMessage("gui.ticket.what")); + AbstractChatConfirm abstractChatConfirm = new AbstractChatConfirm(player, event2 -> { + ticket.addResponse(new TicketResponse(player, event2.getMessage(), System.currentTimeMillis())); + constructGUI(); + }); + + abstractChatConfirm.setOnClose(() -> + init(inventory.getTitle(), inventory.getSize())); + })); + } + + @Override + protected void registerOnCloses() { + } +} diff --git a/src/main/java/com/songoda/ultimatemoderation/gui/GUITicketManager.java b/src/main/java/com/songoda/ultimatemoderation/gui/GUITicketManager.java new file mode 100644 index 0000000..c212f06 --- /dev/null +++ b/src/main/java/com/songoda/ultimatemoderation/gui/GUITicketManager.java @@ -0,0 +1,156 @@ +package com.songoda.ultimatemoderation.gui; + +import com.songoda.ultimatemoderation.UltimateModeration; +import com.songoda.ultimatemoderation.punish.PunishmentNote; +import com.songoda.ultimatemoderation.tickets.Ticket; +import com.songoda.ultimatemoderation.tickets.TicketResponse; +import com.songoda.ultimatemoderation.tickets.TicketStatus; +import com.songoda.ultimatemoderation.utils.AbstractChatConfirm; +import com.songoda.ultimatemoderation.utils.Methods; +import com.songoda.ultimatemoderation.utils.gui.AbstractAnvilGUI; +import com.songoda.ultimatemoderation.utils.gui.AbstractGUI; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class GUITicketManager extends AbstractGUI { + + private final UltimateModeration plugin; + + private final OfflinePlayer toModerate; + + private TicketStatus status = TicketStatus.OPEN; + + public GUITicketManager(UltimateModeration plugin, OfflinePlayer toModerate, Player player) { + super(player); + this.plugin = plugin; + this.toModerate = toModerate; + + init(plugin.getLocale().getMessage(toModerate != null ? "gui.tickets.titlesingle" : "gui.tickets.title", player.getName()), 54); + } + + @Override + protected void constructGUI() { + inventory.clear(); + resetClickables(); + registerClickables(); + + createButton(1, Material.ARROW, plugin.getLocale().getMessage("gui.general.previous")); + + createButton(3 ,Material.DIAMOND_SWORD, Methods.formatText("&6" + status.getStatus())); + + createButton(5, Material.ARROW, plugin.getLocale().getMessage("gui.general.next")); + + if (toModerate != null) + createButton(7, Material.REDSTONE, plugin.getLocale().getMessage("gui.tickets.create")); + + if (player.hasPermission("um.ticket")) + createButton(8, Material.OAK_DOOR, plugin.getLocale().getMessage("gui.general.back")); + + for (int i = 0; i < 9; i++) + createButton(9 + i, Material.GRAY_STAINED_GLASS_PANE, "&1"); + + List tickets = toModerate != null ? plugin.getTicketManager().getTicketsAbout(toModerate, status) : plugin.getTicketManager().getTickets(status); + + for (int i = 0; i < tickets.size(); i++) { + Ticket ticket = tickets.get(i); + + String subjectStr = ticket.getSubject(); + + ArrayList lore = new ArrayList<>(); + int lastIndex = 0; + for (int n = 0; n < subjectStr.length(); n++) { + if (n - lastIndex < 20) + continue; + + if (subjectStr.charAt(n) == ' ') { + lore.add("&6" +subjectStr.substring(lastIndex, n).trim()); + lastIndex = n; + } + } + + if (lastIndex - subjectStr.length() < 20) + lore.add("&6" + subjectStr.substring(lastIndex, subjectStr.length()).trim() + " &7- " + ticket.getTicketId()); + + String name = lore.get(0); + lore.remove(0); + + lore.add(""); + + SimpleDateFormat format = new SimpleDateFormat("MM-dd-yyyy"); + + lore.add(plugin.getLocale().getMessage("gui.ticket.status", ticket.getStatus().getStatus())); + + if (toModerate != null) + lore.add(plugin.getLocale().getMessage("gui.tickets.player", Bukkit.getOfflinePlayer(ticket.getVictim()).getName())); + lore.add(plugin.getLocale().getMessage("gui.ticket.createdon", format.format(new Date(ticket.getCreationDate())))); + lore.add(plugin.getLocale().getMessage("gui.tickets.click")); + + createButton(18 + i, Material.MAP, name, lore); + + registerClickable(18 + i, ((player1, inventory1, cursor, slot, type) -> + new GUITicket(plugin, ticket, toModerate, player))); + } + + } + + @Override + protected void registerClickables() { + if (player.hasPermission("um.ticket")) { + registerClickable(8, ((player1, inventory1, cursor, slot, type) -> { + if (toModerate == null) + new GUIPlayers(plugin, player); + else + new GUIPlayer(plugin, toModerate, player1); + })); + } + + registerClickable(3, ((player1, inventory1, cursor, slot, type) -> { + this.status = status == TicketStatus.OPEN ? TicketStatus.CLOSED : TicketStatus.OPEN; + constructGUI(); + })); + + if (toModerate != null) { + registerClickable(7, ((player1, inventory1, cursor, slot, type) -> + createNew(player, toModerate))); + } + } + + public static void createNew(Player player, OfflinePlayer toModerate) { + UltimateModeration plugin = UltimateModeration.getInstance(); + + AbstractAnvilGUI gui = new AbstractAnvilGUI(player, event -> { + Ticket ticket = new Ticket(toModerate, event.getName()); + + player.sendMessage(plugin.getLocale().getMessage("gui.tickets.what")); + AbstractChatConfirm abstractChatConfirm = new AbstractChatConfirm(player, event2 -> { + plugin.getTicketManager().addTicket(ticket); + + ticket.addResponse(new TicketResponse(player, event2.getMessage(), System.currentTimeMillis())); + }); + + abstractChatConfirm.setOnClose(() -> + new GUITicket(plugin, ticket, toModerate, player)); + }); + + ItemStack item = new ItemStack(Material.PAPER); + ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(plugin.getLocale().getMessage("gui.tickets.subject")); + item.setItemMeta(meta); + + gui.setSlot(AbstractAnvilGUI.AnvilSlot.INPUT_LEFT, item); + gui.open(); + } + + @Override + protected void registerOnCloses() { + } +} diff --git a/src/main/java/com/songoda/ultimatemoderation/storage/Storage.java b/src/main/java/com/songoda/ultimatemoderation/storage/Storage.java index 12c53aa..8176129 100644 --- a/src/main/java/com/songoda/ultimatemoderation/storage/Storage.java +++ b/src/main/java/com/songoda/ultimatemoderation/storage/Storage.java @@ -5,9 +5,13 @@ import com.songoda.ultimatemoderation.punish.AppliedPunishment; import com.songoda.ultimatemoderation.punish.PunishmentNote; import com.songoda.ultimatemoderation.punish.player.PlayerPunishData; import com.songoda.ultimatemoderation.punish.template.Template; +import com.songoda.ultimatemoderation.tickets.Ticket; +import com.songoda.ultimatemoderation.tickets.TicketResponse; +import com.songoda.ultimatemoderation.tickets.TicketStatus; import com.songoda.ultimatemoderation.utils.ConfigWrapper; import java.util.List; +import java.util.UUID; public abstract class Storage { @@ -61,6 +65,20 @@ public abstract class Storage { new StorageItem("creation", note.getCreationDate())); } } + + for (Ticket ticket : instance.getTicketManager().getTickets()) { + prepareSaveItem("tickets", new StorageItem("id", ticket.getTicketId()), + new StorageItem("player", ticket.getVictim().toString()), + new StorageItem("subject", ticket.getSubject()), + new StorageItem("status", ticket.getStatus().toString())); + + for (TicketResponse ticketResponse : ticket.getResponses()) { + prepareSaveItem("ticketresponses", new StorageItem("posted", ticketResponse.getPostedDate()), + new StorageItem("ticketid", ticket.getTicketId()), + new StorageItem("author", ticketResponse.getAuthor().toString()), + new StorageItem("message", ticketResponse.getMessage())); + } + } } public abstract void doSave(); diff --git a/src/main/java/com/songoda/ultimatemoderation/storage/types/StorageYaml.java b/src/main/java/com/songoda/ultimatemoderation/storage/types/StorageYaml.java index 785aa96..876fda3 100644 --- a/src/main/java/com/songoda/ultimatemoderation/storage/types/StorageYaml.java +++ b/src/main/java/com/songoda/ultimatemoderation/storage/types/StorageYaml.java @@ -58,7 +58,7 @@ public class StorageYaml extends Storage { public void prepareSaveItem(String group, StorageItem... items) { for (StorageItem item : items) { if (item == null || item.asObject() == null) continue; - toSave.put("data." + group + "." + items[0].asString() + "." + item.getKey(), item.asObject()); + toSave.put("data." + group + "." + items[0].asObject()+ "." + item.getKey(), item.asObject()); } } diff --git a/src/main/java/com/songoda/ultimatemoderation/tickets/Ticket.java b/src/main/java/com/songoda/ultimatemoderation/tickets/Ticket.java new file mode 100644 index 0000000..d8b5b4f --- /dev/null +++ b/src/main/java/com/songoda/ultimatemoderation/tickets/Ticket.java @@ -0,0 +1,83 @@ +package com.songoda.ultimatemoderation.tickets; + +import org.bukkit.OfflinePlayer; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class Ticket { + + private int ticketId; + + private TicketStatus status = TicketStatus.OPEN; + + private final List tickets = new ArrayList<>(); + private final UUID victim; + private final String subject; + + public Ticket(OfflinePlayer victim, String subject) { + this.victim = victim.getUniqueId(); + this.subject = subject; + } + + public Ticket(UUID victim, String subject) { + this.victim = victim; + this.subject = subject; + } + + public Ticket(OfflinePlayer victim, String subject, TicketResponse response) { + this.victim = victim.getUniqueId(); + this.subject = subject; + this.tickets.add(response); + } + + public Ticket(UUID victim, String subject, TicketResponse response) { + this.victim = victim; + this.subject = subject; + this.tickets.add(response); + } + + public int getTicketId() { + return ticketId; + } + + public void setTicketId(int ticketId) { + this.ticketId = ticketId; + } + + public List getResponses() { + return new ArrayList<>(tickets); + } + + public TicketResponse addResponse(TicketResponse response) { + response.setTicketId(ticketId); + tickets.add(response); + return response; + } + + public TicketResponse removeResponse(TicketResponse response) { + tickets.remove(response); + return response; + } + + public UUID getVictim() { + return victim; + } + + public String getSubject() { + return subject; + } + + public long getCreationDate() { + return tickets.get(0).getPostedDate(); + } + + public TicketStatus getStatus() { + return status; + } + + public void setStatus(TicketStatus status) { + this.status = status; + } +} diff --git a/src/main/java/com/songoda/ultimatemoderation/tickets/TicketManager.java b/src/main/java/com/songoda/ultimatemoderation/tickets/TicketManager.java new file mode 100644 index 0000000..e4fa546 --- /dev/null +++ b/src/main/java/com/songoda/ultimatemoderation/tickets/TicketManager.java @@ -0,0 +1,43 @@ +package com.songoda.ultimatemoderation.tickets; + +import org.bukkit.OfflinePlayer; + +import java.util.*; +import java.util.stream.Collectors; + +public class TicketManager { + + private final TreeMap registeredTickets = new TreeMap<>(); + + public Ticket addTicket(Ticket ticket) { + int id = registeredTickets.isEmpty() ? 1 : registeredTickets.lastEntry().getValue().getTicketId() + 1; + ticket.setTicketId(id); + return addTicket(ticket, id); + } + + public Ticket addTicket(Ticket ticket, int id) { + registeredTickets.put(id, ticket); + return ticket; + } + + public Ticket getTicket(int id) { + return registeredTickets.get(id); + } + + public List getTickets() { + return new ArrayList<>(registeredTickets.values()); + } + + public List getTickets(TicketStatus status) { + return registeredTickets.values().stream().filter(ticket -> ticket.getStatus() == status).collect(Collectors.toList()); + } + + public List getTicketsAbout(OfflinePlayer player, TicketStatus status) { + return getTicketsAbout(player.getUniqueId(), status); + } + + public List getTicketsAbout(UUID player, TicketStatus status) { + return registeredTickets.values().stream() + .filter(ticket -> ticket.getVictim().equals(player) && ticket.getStatus() == status).collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/songoda/ultimatemoderation/tickets/TicketResponse.java b/src/main/java/com/songoda/ultimatemoderation/tickets/TicketResponse.java new file mode 100644 index 0000000..379f3c0 --- /dev/null +++ b/src/main/java/com/songoda/ultimatemoderation/tickets/TicketResponse.java @@ -0,0 +1,46 @@ +package com.songoda.ultimatemoderation.tickets; + +import org.bukkit.OfflinePlayer; + +import java.util.UUID; + +public class TicketResponse { + + private int ticketId; + + private final UUID author; + private final String message; + private final long posted; + + public TicketResponse(OfflinePlayer author, String message, long posted) { + this.author = author.getUniqueId(); + this.message = message; + this.posted = posted; + } + + public TicketResponse(UUID author, String message, long posted) { + this.author = author; + this.message = message; + this.posted = posted; + } + + public int getTicketId() { + return ticketId; + } + + public void setTicketId(int ticketId) { + this.ticketId = ticketId; + } + + public UUID getAuthor() { + return author; + } + + public String getMessage() { + return message; + } + + public long getPostedDate() { + return posted; + } +} diff --git a/src/main/java/com/songoda/ultimatemoderation/tickets/TicketStatus.java b/src/main/java/com/songoda/ultimatemoderation/tickets/TicketStatus.java new file mode 100644 index 0000000..6a71b28 --- /dev/null +++ b/src/main/java/com/songoda/ultimatemoderation/tickets/TicketStatus.java @@ -0,0 +1,17 @@ +package com.songoda.ultimatemoderation.tickets; + +public enum TicketStatus { + + OPEN("Open"), + CLOSED("Closed"); + + private String status; + + TicketStatus(String status) { + this.status = status; + } + + public String getStatus() { + return status; + } +} diff --git a/src/main/java/com/songoda/ultimatemoderation/utils/AbstractChatConfirm.java b/src/main/java/com/songoda/ultimatemoderation/utils/AbstractChatConfirm.java index f4eff59..ad80b38 100644 --- a/src/main/java/com/songoda/ultimatemoderation/utils/AbstractChatConfirm.java +++ b/src/main/java/com/songoda/ultimatemoderation/utils/AbstractChatConfirm.java @@ -4,10 +4,10 @@ import com.songoda.ultimatemoderation.UltimateModeration; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.inventory.Inventory; import org.bukkit.plugin.java.JavaPlugin; import java.util.ArrayList; @@ -18,26 +18,24 @@ public class AbstractChatConfirm implements Listener { private static final List registered = new ArrayList<>(); - private Inventory inventory; - private final Player player; private final ChatConfirmHandler handler; + private OnClose onClose = null; + public AbstractChatConfirm(Player player, ChatConfirmHandler hander) { this.player = player; this.handler = hander; - this.inventory = player.getOpenInventory() == null ? null : player.getOpenInventory().getTopInventory(); player.closeInventory(); initializeListeners(UltimateModeration.getInstance()); registered.add(player.getUniqueId()); } - private static boolean listenersInitialized = false; + private Listener listener; public void initializeListeners(JavaPlugin plugin) { - if (listenersInitialized) return; - Bukkit.getPluginManager().registerEvents(new Listener() { + this.listener = new Listener() { @EventHandler public void onChat(AsyncPlayerChatEvent event) { Player player = event.getPlayer(); @@ -50,15 +48,15 @@ public class AbstractChatConfirm implements Listener { handler.onChat(chatConfirmEvent); - if (inventory != null) player.openInventory(inventory); + if (onClose != null) { + onClose.onClose(); + } + HandlerList.unregisterAll(listener); } + }; - @EventHandler - public void onPlayerQuit(PlayerQuitEvent event) { - AbstractChatConfirm.unregister(event.getPlayer()); - } - }, plugin); - listenersInitialized = true; + + Bukkit.getPluginManager().registerEvents(listener, UltimateModeration.getInstance()); } public static boolean isRegistered(Player player) { @@ -73,6 +71,14 @@ public class AbstractChatConfirm implements Listener { void onChat(ChatConfirmEvent event); } + public void setOnClose(OnClose onClose) { + this.onClose = onClose; + } + + public interface OnClose { + void onClose(); + } + public class ChatConfirmEvent { private final Player player; diff --git a/src/main/resources/en_US.lang b/src/main/resources/en_US.lang index 08eae5b..7ea2a9a 100644 --- a/src/main/resources/en_US.lang +++ b/src/main/resources/en_US.lang @@ -81,8 +81,6 @@ gui.templatemanager.create = "&6&lCreate Template" gui.templatemanager.leftclick = "&7Left-Click to edit." gui.templatemanager.rightclick = "&7Right-Click to destroy." -gui.notes.title = "&8%toModerate% > Notes" - gui.punishments.title = "&8%toModerate% > Punish" gui.punishments.reason = "&6Reason" gui.punishments.duration = "&6Initial Duration" @@ -129,10 +127,29 @@ gui.player.punish = "&6&lPunish" gui.player.moderate = "&b&lModerate" gui.player.punishments = "&c&lPunishments" gui.player.notes = "&a&lNotes" +gui.player.tickets = "&7&lTickets" gui.moderate.title = "&8%toModerate% > Moderate" -gui.moderate.create = "&6Create Note" -gui.moderate.remove = "&cClick to remove" -gui.moderate.type = "Type in your note." -gui.moderate.createdon = "&7Created on &6%time%&7." -gui.moderate.createdby = "&7Created by &6%player%&7." \ No newline at end of file + +gui.notes.title = "&8%tonotes% > Notes" +gui.notes.create = "&6Create Note" +gui.notes.remove = "&cClick to remove" +gui.notes.type = "Type in your note." +gui.notes.createdon = "&7Created on &6%time%&7." +gui.notes.createdby = "&7Created by &6%player%&7." + + +gui.tickets.title = "&8Tickets" +gui.tickets.titlesingle = "&8%toModerate% > Tickets" +gui.tickets.create = "&6Create a ticket" +gui.tickets.click = "&6Click to Manage." +gui.tickets.player = "&7Player &6%player%&7." +gui.tickets.what = "&6What would you like to say in your first ticket post?" +gui.tickets.subject = "Ticket Subject" + +gui.ticket.title = "&8Tickets > %id%"; +gui.ticket.createdon = "&7Created on &6%time%&7." +gui.ticket.respond = "&6Respond" +gui.ticket.status = "&7Status &6%status%&7." +gui.ticket.postedby = "&7Posted by &6%player%&7." +gui.ticket.what = "&6What would you like to say?" \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 951c9ac..30d3c96 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -83,4 +83,8 @@ commands: RunTemplate: description: RunTemplate defaullt: false - usage: /runtemplate \ No newline at end of file + usage: /runtemplate + Ticket: + description: Ticket + defaullt: false + usage: /ticket \ No newline at end of file