Recent changes and additions (general functionality)
This commit is contained in:
parent
459dbf80ec
commit
97af7663cc
29
lang.yml
29
lang.yml
|
@ -1,18 +1,37 @@
|
|||
# Language file for XAquamarine
|
||||
generic-no-permission: "Sinulla ei ole oikeutta tuohon."
|
||||
command-ticket-usage: "Käytä: &b/%label% [viesti]"
|
||||
generic-not-player: "Tämä komento toimii vain pelaajilla."
|
||||
generic-invalid-number: "Virheellinen numero: &b$n$"
|
||||
generic-ticket-not-found: "Apupyyntöä ei löytynyt."
|
||||
generic-invalid-ticket: "Apupyyntö on virheellinen tai sitä koskevaa maailmaa ei ole ladattu."
|
||||
generic-invalid-player: "Pelaajaa '$player$' ei löytynyt. Oletko varma, että hän on pelannut täällä tuolla nimellä?"
|
||||
generic-no-tickets: "Apupyyntöjä ei löytynyt."
|
||||
generic-previous: "Edelliset"
|
||||
generic-next: "Seuraavat"
|
||||
generic-page: "Sivu "
|
||||
|
||||
gui-click-teleport: "Klikkaa vasemmalla siirtyäksesi"
|
||||
gui-click-solve: "Klikkaa oikealla sulkeaksesi"
|
||||
|
||||
command-ticket-usage: "Käytä: &b/$label$ [viesti]"
|
||||
command-ticket-goto-usage: "Käytä: &b/$label$ goto [id]"
|
||||
command-ticket-goto-teleport: "Woosh! Täällä ollaan."
|
||||
command-ticket-solve-usage: "Käytä: &b/$label$ solve [id] [viesti]"
|
||||
command-ticket-solved: "&b$solver$ &7sulki apupyynnön &b#$n$&7: &f&o$comment$"
|
||||
command-ticket-view-usage: "Käytä: &b/$label$ view [id]"
|
||||
command-ticket-player-usage: "Käytä: &b/$label$ player [pelaaja] [sivu]"
|
||||
|
||||
ticket-deny-nearby: "Et voi luoda uutta apupyyntöä tässä, koska lähellä on tehty jo muita apupyyntöjä."
|
||||
ticket-deny-player: "Et voi luoda uutta apupyyntöä, koska sinulla on jo useita odottavia apupyyntöjä."
|
||||
|
||||
ticket-created: "Avasit uuden apupyynnön. Numero: &b%ticketId%"
|
||||
ticket-created-announcement: "&b%player% &7avasi apupyynnön &b#%ticketId%&7:"
|
||||
ticket-join-announcement: "Palvelimella odottaa &b%ticketCount% apupyyntöä"
|
||||
ticket-created: "Avasit uuden apupyynnön. Numero: &b$ticketId$"
|
||||
ticket-created-announcement: "&b$player$ &7avasi apupyynnön &b#$ticketId$&7:"
|
||||
ticket-join-announcement: "Palvelimella odottaa &b$ticketCount$ apupyyntöä"
|
||||
|
||||
ticket-preview-teleport: "Teleporttaa"
|
||||
ticket-preview-solve: "Muuta ratkaistuksi"
|
||||
|
||||
ticket-hover-title: "&bApupyyntö #%ticketId%"
|
||||
ticket-hover-title: "&bApupyyntö #$ticketId$"
|
||||
ticket-hover-sender: "&7Lähettäjä: &f%s"
|
||||
ticket-hover-timestamp: "&7Aikaleima: &f%s"
|
||||
ticket-hover-location: "&7Sijainti: &f%s"
|
||||
|
|
|
@ -13,9 +13,11 @@ commands:
|
|||
permission: aquamarine.ticket
|
||||
xt:
|
||||
description: Staff features
|
||||
aliases: [aq]
|
||||
permission: aquamarine.staff
|
||||
xti:
|
||||
description: Staff features
|
||||
aliases: [aqi]
|
||||
permission: aquamarine.staff
|
||||
permissions:
|
||||
aquamarine.ticket:
|
||||
|
|
|
@ -90,7 +90,7 @@ public class XText {
|
|||
|
||||
for (String s:words) {
|
||||
|
||||
out.append(s);
|
||||
out.append(s).append(' ');
|
||||
line += s.length();
|
||||
|
||||
if (line >= charsPerLine) {
|
||||
|
|
|
@ -61,13 +61,14 @@ public class XTicketManager implements Listener {
|
|||
throw new RuntimeException("Unable to create new ticket. Check your storage method.");
|
||||
|
||||
String staffAnnounce = plugin.lang("ticket-created-announcement")
|
||||
.replace("player", player.getName())
|
||||
.replace("ticketId", ""+ticket.getId());
|
||||
.replaceAll("\\$player\\$", player.getName())
|
||||
.replaceAll("\\$ticketId\\$", ""+ticket.getId());
|
||||
|
||||
Bukkit.getOnlinePlayers()
|
||||
.stream()
|
||||
.filter(p -> p.hasPermission(AquamarinePermission.STAFF))
|
||||
.forEach(p -> plugin.sendPrefixed(staffAnnounce, p));
|
||||
.peek(p -> plugin.sendPrefixed(staffAnnounce, p))
|
||||
.forEach(p -> p.sendMessage("§f§o" + ticket.getMessage()));
|
||||
|
||||
return ticket;
|
||||
|
||||
|
@ -83,10 +84,10 @@ public class XTicketManager implements Listener {
|
|||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (player.hasPermission(AquamarinePermission.STAFF)) {
|
||||
if (player.hasPermission(AquamarinePermission.STAFF) || player.isOp()) {
|
||||
storage.getWaitingTicketsAsync((List<XTicket> tickets) -> {
|
||||
if (tickets.size() > 0) {
|
||||
plugin.sendPrefixed(plugin.lang("ticket-join-announcement").replace("%ticketCount%", ""+tickets.size()));
|
||||
plugin.sendPrefixed(plugin.lang("ticket-join-announcement").replaceAll("\\$ticketCount\\$", ""+tickets.size()), player);
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1.5f);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package fi.xeno.aquamarine;
|
||||
|
||||
import fi.xeno.aquamarine.command.CommandTicket;
|
||||
import fi.xeno.aquamarine.command.CommandXt;
|
||||
import fi.xeno.aquamarine.command.CommandXti;
|
||||
import fi.xeno.aquamarine.sql.XHikariDatabase;
|
||||
import fi.xeno.aquamarine.storage.XFlatFileTicketDataStorage;
|
||||
import fi.xeno.aquamarine.storage.XMemoryTicketDataStorage;
|
||||
|
@ -8,6 +10,8 @@ import fi.xeno.aquamarine.storage.XSQLTicketDataStorage;
|
|||
import fi.xeno.aquamarine.storage.XTicketDataStorage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -19,6 +23,8 @@ import java.text.SimpleDateFormat;
|
|||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class XTicketsPlugin extends JavaPlugin {
|
||||
|
@ -87,8 +93,14 @@ public class XTicketsPlugin extends JavaPlugin {
|
|||
}
|
||||
|
||||
ticketManager = new XTicketManager(this, dataStorage);
|
||||
Bukkit.getPluginManager().registerEvents(ticketManager, this);
|
||||
|
||||
registerCommand("ticket", new CommandTicket(this, ticketManager));
|
||||
registerCommand("xt", new CommandXt(this, ticketManager));
|
||||
|
||||
CommandXti ticketGuiCommand = new CommandXti(this, ticketManager);
|
||||
Bukkit.getPluginManager().registerEvents(ticketGuiCommand, this);
|
||||
registerCommand("xti", ticketGuiCommand);
|
||||
|
||||
logger.info("Aquamarine has been enabled!");
|
||||
|
||||
|
@ -106,21 +118,31 @@ public class XTicketsPlugin extends JavaPlugin {
|
|||
this.getCommand(label).setTabCompleter(command);
|
||||
}
|
||||
|
||||
public void sendPrefixed(String message, Player... recipients) {
|
||||
public void sendPrefixed(String message, CommandSender... recipients) {
|
||||
sendPrefixed(message, Arrays.asList(recipients));
|
||||
}
|
||||
|
||||
public void sendPrefixed(String message, Iterable<Player> recipients) {
|
||||
public void sendPrefixed(String message, Iterable<CommandSender> recipients) {
|
||||
String out = INFO_PREFIX + message;
|
||||
recipients.forEach(p -> p.sendMessage(out));
|
||||
}
|
||||
|
||||
public String lang(String key){
|
||||
return lang.getString(key, "lang["+key+"]");
|
||||
return ChatColor.translateAlternateColorCodes('&', lang.getString(key, "lang["+key+"]"));
|
||||
}
|
||||
|
||||
public String formatTimestamp(long timestamp) {
|
||||
return dateFormat.format(Date.from(Instant.ofEpochMilli(timestamp)));
|
||||
}
|
||||
|
||||
private static Map<String, NamespacedKey> keyCache = new ConcurrentHashMap<>();
|
||||
public static NamespacedKey key(String n) {
|
||||
if (!keyCache.containsKey(n)) keyCache.put(n, new NamespacedKey(getInstance(), n));
|
||||
return keyCache.get(n);
|
||||
}
|
||||
|
||||
public XTicketManager getTicketManager() {
|
||||
return ticketManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public class CommandTicket implements TabExecutor {
|
|||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage(plugin.lang("command-ticket-usage").replace("%label%", label));
|
||||
sender.sendMessage(plugin.lang("command-ticket-usage").replaceAll("\\$label\\$", label));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ public class CommandTicket implements TabExecutor {
|
|||
|
||||
XTicket ticket = ticketManager.createTicket(player, msgJoiner.toString().trim());
|
||||
|
||||
plugin.sendPrefixed(plugin.lang("ticket-created").replace("%ticketId%", ""+ticket.getId()));
|
||||
plugin.sendPrefixed(plugin.lang("ticket-created").replaceAll("\\$ticketId\\$", ""+ticket.getId()));
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
package fi.xeno.aquamarine.command;
|
||||
|
||||
import fi.xeno.aquamarine.AquamarinePermission;
|
||||
import fi.xeno.aquamarine.XText;
|
||||
import fi.xeno.aquamarine.XTicketManager;
|
||||
import fi.xeno.aquamarine.XTicketsPlugin;
|
||||
import fi.xeno.aquamarine.util.TimestampedValue;
|
||||
import fi.xeno.aquamarine.util.XTicket;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
|
@ -46,19 +51,242 @@ public class CommandXt implements TabExecutor {
|
|||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
|
||||
if (!sender.hasPermission(AquamarinePermission.STAFF)) {
|
||||
sender.sendMessage(plugin.lang("generic-no-permission"));
|
||||
plugin.sendPrefixed(plugin.lang("generic-no-permission"), sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
|
||||
|
||||
|
||||
if (args.length == 0) {
|
||||
|
||||
List<XTicket> tickets = ticketManager.getStorage().getWaitingTickets();
|
||||
|
||||
if (tickets.size() == 0) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-no-tickets"), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
tickets.forEach(xt -> sender.spigot().sendMessage(xt.renderChatPreview(true)));
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
switch (args[0].toLowerCase(Locale.ROOT)) {
|
||||
|
||||
case "help": {
|
||||
plugin.sendPrefixed("§b/" + label + " §7help, view, goto, solve, player, all");
|
||||
break;
|
||||
}
|
||||
|
||||
case "all": {
|
||||
|
||||
int page = 0;
|
||||
if (args.length > 1) {
|
||||
try {
|
||||
page = Integer.parseInt(args[1])-1;
|
||||
} catch (NumberFormatException e) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-invalid-number").replaceAll("\\$n\\$", args[1]), sender);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
List<XTicket> tickets = ticketManager.getStorage().getTickets();
|
||||
|
||||
if (tickets.size() == 0) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-no-tickets"), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
int perPage = 8;
|
||||
int totalPages = (int)Math.ceil((double)tickets.size() / (double)perPage);
|
||||
|
||||
tickets.stream()
|
||||
.skip((long)page*perPage)
|
||||
.limit(perPage)
|
||||
.forEach(xt -> sender.spigot().sendMessage(xt.renderChatPreview(true)));
|
||||
|
||||
ComponentBuilder paginationMenu = new ComponentBuilder();
|
||||
|
||||
if (page > 0)
|
||||
paginationMenu.append(XText.commandButton("§8[§b‹§8] ", "§7" + plugin.lang("generic-previous"), "/" + label + " all " + (page-1)));
|
||||
|
||||
if (page+1 < totalPages)
|
||||
paginationMenu.append(XText.commandButton("§8[§b›§8] ", "§7" + plugin.lang("generic-next"), "/" + label + " all " + (page+1)));
|
||||
|
||||
paginationMenu.append(XText.hoverText(plugin.lang("generic-page") + "§b" + (page+1) + "/" + totalPages, "§r"));
|
||||
sender.spigot().sendMessage(paginationMenu.create());
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case "player":
|
||||
case "from": {
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.sendPrefixed(plugin.lang("command-ticket-player-usage").replaceAll("\\$label\\$", label), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
String playerName = args[1];
|
||||
OfflinePlayer ofp = Bukkit.getOfflinePlayer(playerName);
|
||||
|
||||
if (!ofp.hasPlayedBefore() && !ofp.isOnline()) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-invalid-player").replaceAll("\\$player\\$", playerName), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
int page = 0;
|
||||
if (args.length > 2) {
|
||||
try {
|
||||
page = Integer.parseInt(args[2]);
|
||||
} catch (NumberFormatException e) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-invalid-number").replaceAll("\\$n\\$", args[1]), sender);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
List<XTicket> tickets = ticketManager.getStorage().getTicketsBySender(ofp.getUniqueId());
|
||||
|
||||
if (tickets.size() == 0) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-no-tickets"), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
int perPage = 8;
|
||||
int totalPages = (int)Math.ceil((double)tickets.size() / (double)perPage);
|
||||
|
||||
tickets.stream()
|
||||
.skip((long)page*perPage)
|
||||
.limit(perPage)
|
||||
.forEach(xt -> sender.spigot().sendMessage(xt.renderChatPreview(true)));
|
||||
|
||||
ComponentBuilder paginationMenu = new ComponentBuilder();
|
||||
|
||||
if (page > 0)
|
||||
paginationMenu.append(XText.commandButton("§8[§b‹§8] ", "§7" + plugin.lang("generic-previous"), "/" + label + " player " + ofp.getName() + " " + (page-1)));
|
||||
|
||||
if (page+1 < totalPages)
|
||||
paginationMenu.append(XText.commandButton("§8[§b›§8] ", "§7" + plugin.lang("generic-next"), "/" + label + " player " + ofp.getName() + " " + (page+1)));
|
||||
|
||||
paginationMenu.append(XText.hoverText(plugin.lang("generic-page") + "§b" + (page+1) + "/" + totalPages, "§r"));
|
||||
sender.spigot().sendMessage(paginationMenu.create());
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case "view":
|
||||
case "info":
|
||||
case "show": {
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.sendPrefixed(plugin.lang("command-ticket-view-usage").replaceAll("\\$label\\$", label), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
int ticketId;
|
||||
try {
|
||||
ticketId = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-invalid-number").replaceAll("\\$n\\$", args[1]), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<XTicket> ticketOptional = ticketManager.getStorage().getTicketByNumber(ticketId);
|
||||
if (!ticketOptional.isPresent()) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-ticket-not-found"), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
XTicket ticket = ticketOptional.get();
|
||||
sender.spigot().sendMessage(ticket.renderChatPreview(true, true));
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case "goto": {
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-not-player"), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.sendPrefixed(plugin.lang("command-ticket-goto-usage").replaceAll("\\$label\\$", label), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
int ticketId;
|
||||
try {
|
||||
ticketId = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-invalid-number").replaceAll("\\$n\\$", args[1]), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<XTicket> ticketOptional = ticketManager.getStorage().getTicketByNumber(ticketId);
|
||||
if (!ticketOptional.isPresent()) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-ticket-not-found"), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
XTicket ticket = ticketOptional.get();
|
||||
Player player = (Player)sender;
|
||||
Location location = ticket.getLocation().toLocation();
|
||||
|
||||
if (location == null || !location.isWorldLoaded()) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-invalid-ticket"), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!location.getChunk().isLoaded())
|
||||
location.getChunk().load();
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
player.teleport(location);
|
||||
plugin.sendPrefixed(plugin.lang("command-ticket-goto-teleport"), sender);
|
||||
player.playSound(player.getLocation(), "entity.enderman.teleport", 1f, 1f);
|
||||
player.playSound(player.getLocation(), "entity.endermen.teleport", 1f, 1f);
|
||||
}, 2L);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case "solve": {
|
||||
|
||||
if (args.length < 2) {
|
||||
plugin.sendPrefixed(plugin.lang("command-ticket-solve-usage").replaceAll("\\$label\\$", label), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
StringJoiner commentJoiner = new StringJoiner(" ");
|
||||
Arrays.stream(args).skip(2).forEach(commentJoiner::add);
|
||||
String comment = commentJoiner.toString();
|
||||
|
||||
int ticketId;
|
||||
try {
|
||||
ticketId = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-invalid-number").replaceAll("\\$n\\$", args[1]), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<XTicket> ticketOptional = ticketManager.getStorage().getTicketByNumber(ticketId);
|
||||
if (!ticketOptional.isPresent()) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-ticket-not-found"), sender);
|
||||
return;
|
||||
}
|
||||
|
||||
XTicket ticket = ticketOptional.get();
|
||||
ticketManager.getStorage().solveTicket(ticket, sender, comment);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
149
src/fi/xeno/aquamarine/command/CommandXti.java
Normal file
149
src/fi/xeno/aquamarine/command/CommandXti.java
Normal file
|
@ -0,0 +1,149 @@
|
|||
package fi.xeno.aquamarine.command;
|
||||
|
||||
import fi.xeno.aquamarine.AquamarinePermission;
|
||||
import fi.xeno.aquamarine.XText;
|
||||
import fi.xeno.aquamarine.XTicketManager;
|
||||
import fi.xeno.aquamarine.XTicketsPlugin;
|
||||
import fi.xeno.aquamarine.util.TimestampedValue;
|
||||
import fi.xeno.aquamarine.util.XTicket;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class CommandXti implements TabExecutor, Listener {
|
||||
|
||||
private final XTicketsPlugin plugin;
|
||||
private final XTicketManager ticketManager;
|
||||
|
||||
private final XTicketGui ticketGui;
|
||||
|
||||
public CommandXti(XTicketsPlugin plugin, XTicketManager ticketManager) {
|
||||
|
||||
this.plugin = plugin;
|
||||
this.ticketManager = ticketManager;
|
||||
|
||||
this.ticketGui = new XTicketGui();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
|
||||
if (!sender.hasPermission(AquamarinePermission.STAFF)) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-no-permission"), sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-not-player"), sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player)sender;
|
||||
|
||||
ticketManager.getStorage().getWaitingTicketsAsync(tickets -> {
|
||||
|
||||
if (tickets.size() == 0) {
|
||||
plugin.sendPrefixed(plugin.lang("generic-no-tickets"), player);
|
||||
return;
|
||||
}
|
||||
|
||||
sync(() -> {
|
||||
|
||||
Inventory inv = ticketGui.getInventory();
|
||||
ticketGui.refresh(tickets);
|
||||
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_CHEST_OPEN, 1f, 1f);
|
||||
player.openInventory(inv);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
private void onInventoryClick(InventoryClickEvent e) {
|
||||
|
||||
if (e.getInventory().getHolder() == null || !(e.getInventory().getHolder() instanceof XTicketGui)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.getCurrentItem() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player)e.getWhoClicked();
|
||||
ItemStack item = e.getCurrentItem();
|
||||
|
||||
PersistentDataContainer pd = item.getItemMeta().getPersistentDataContainer();
|
||||
String ticketId = pd.getOrDefault(XTicketsPlugin.key("xTicketId"), PersistentDataType.STRING, "?");
|
||||
|
||||
if (e.getClick().equals(ClickType.LEFT)) {
|
||||
player.performCommand("xt goto " + ticketId);
|
||||
} else if (e.getClick().equals(ClickType.RIGHT)) {
|
||||
player.performCommand("xt solve " + ticketId + " -");
|
||||
}
|
||||
|
||||
player.closeInventory();
|
||||
e.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
private void onInventoryClick(InventoryDragEvent e) {
|
||||
if (e.getInventory().getHolder() != null && e.getInventory().getHolder() instanceof XTicketGui) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void sync(Runnable r) {
|
||||
Bukkit.getScheduler().runTask(plugin, r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static class XTicketGui implements InventoryHolder {
|
||||
|
||||
private final Inventory inv;
|
||||
|
||||
public XTicketGui() {
|
||||
this.inv = Bukkit.createInventory(this, 9*6, "* ✎ *");
|
||||
}
|
||||
|
||||
public synchronized void refresh(List<XTicket> tickets) {
|
||||
inv.clear();
|
||||
tickets.forEach(t -> inv.addItem(t.renderMenuItem()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return inv;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -6,6 +6,7 @@ import fi.xeno.aquamarine.XTicketsPlugin;
|
|||
import fi.xeno.aquamarine.util.XStoredLocation;
|
||||
import fi.xeno.aquamarine.util.XTicket;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -38,7 +39,7 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
|
||||
}
|
||||
|
||||
private void load() throws IOException {
|
||||
private synchronized void load() throws IOException {
|
||||
|
||||
tickets.clear();
|
||||
|
||||
|
@ -71,7 +72,7 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
|
||||
}
|
||||
|
||||
private void save() {
|
||||
private synchronized void save() {
|
||||
|
||||
JsonArray out = new JsonArray();
|
||||
tickets.values()
|
||||
|
@ -82,6 +83,7 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
try {
|
||||
Writer writer = new FileWriter(file);
|
||||
gson.toJson(out, writer);
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().severe("Unable to save ticket JSON data:");
|
||||
e.printStackTrace();
|
||||
|
@ -95,7 +97,7 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
|
||||
|
||||
@Override
|
||||
public XTicket createTicket(Player player, String message) {
|
||||
public synchronized XTicket createTicket(Player player, String message) {
|
||||
|
||||
XTicket ticket = XTicket.asPlayer(getNextTicketId(), player, message);
|
||||
tickets.put(ticket.getId(), ticket);
|
||||
|
@ -107,11 +109,11 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void solveTicket(XTicket ticket, Player solver, String comment) {
|
||||
public synchronized void solveTicket(XTicket ticket, CommandSender solver, String comment) {
|
||||
|
||||
ticket.setSolved(true);
|
||||
|
||||
ticket.setSolvedByUuid(solver.getUniqueId());
|
||||
ticket.setSolvedByUuid(solver instanceof Player ? ((Player)solver).getUniqueId() : new UUID(0,0));
|
||||
ticket.setSolvedByName(solver.getName());
|
||||
|
||||
ticket.setSolveComment(comment);
|
||||
|
@ -120,17 +122,18 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
// this SHOULD be unnecessary, but just to be sure...
|
||||
tickets.put(ticket.getId(), ticket);
|
||||
|
||||
announceSolveTicket(ticket, solver, comment);
|
||||
saveAsync();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<XTicket> getTicketByNumber(int id) {
|
||||
public synchronized Optional<XTicket> getTicketByNumber(int id) {
|
||||
return Optional.ofNullable(tickets.getOrDefault(id, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XTicket> getTickets() {
|
||||
public synchronized List<XTicket> getTickets() {
|
||||
return tickets.values()
|
||||
.stream()
|
||||
.sorted(Comparator.comparingInt(XTicket::getId))
|
||||
|
@ -138,7 +141,7 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<XTicket> getWaitingTickets() {
|
||||
public synchronized List<XTicket> getWaitingTickets() {
|
||||
return tickets.values()
|
||||
.stream()
|
||||
.filter(t -> !t.isSolved())
|
||||
|
@ -147,7 +150,7 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<XTicket> getSolvedTickets() {
|
||||
public synchronized List<XTicket> getSolvedTickets() {
|
||||
return tickets.values()
|
||||
.stream()
|
||||
.filter(XTicket::isSolved)
|
||||
|
@ -156,7 +159,7 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<XTicket> getWaitingNearbyTickets(XStoredLocation location, double radius) {
|
||||
public synchronized List<XTicket> getWaitingNearbyTickets(XStoredLocation location, double radius) {
|
||||
return tickets.values()
|
||||
.stream()
|
||||
.filter(t -> !t.isSolved() && t.getLocation().isInRadius(location, radius))
|
||||
|
@ -165,7 +168,7 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<XTicket> getWaitingTicketsBySender(UUID uuid) {
|
||||
public synchronized List<XTicket> getWaitingTicketsBySender(UUID uuid) {
|
||||
return tickets.values()
|
||||
.stream()
|
||||
.filter(t -> !t.isSolved() && t.getSentByUuid().equals(uuid))
|
||||
|
@ -174,7 +177,7 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<XTicket> getTicketsBySender(UUID uuid) {
|
||||
public synchronized List<XTicket> getTicketsBySender(UUID uuid) {
|
||||
return tickets.values()
|
||||
.stream()
|
||||
.filter(t -> t.getSentByUuid().equals(uuid))
|
||||
|
@ -183,7 +186,7 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<XTicket> getTicketsBySolver(UUID uuid) {
|
||||
public synchronized List<XTicket> getTicketsBySolver(UUID uuid) {
|
||||
return tickets.values()
|
||||
.stream()
|
||||
.filter(t -> t.isSolved() && t.getSolvedByUuid().equals(uuid))
|
||||
|
@ -192,12 +195,12 @@ public class XFlatFileTicketDataStorage extends XTicketDataStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getNextTicketId() {
|
||||
public synchronized int getNextTicketId() {
|
||||
return tickets.keySet().stream().max(Comparator.comparingInt(Integer::intValue)).orElse(0) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
public synchronized void close() {
|
||||
plugin.getLogger().info("Saving ticket storage...");
|
||||
save();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import fi.xeno.aquamarine.XTicketsPlugin;
|
|||
import fi.xeno.aquamarine.util.XStoredLocation;
|
||||
import fi.xeno.aquamarine.util.XTicket;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -33,11 +34,11 @@ public class XMemoryTicketDataStorage extends XTicketDataStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void solveTicket(XTicket ticket, Player solver, String comment) {
|
||||
public void solveTicket(XTicket ticket, CommandSender solver, String comment) {
|
||||
|
||||
ticket.setSolved(true);
|
||||
|
||||
ticket.setSolvedByUuid(solver.getUniqueId());
|
||||
ticket.setSolvedByUuid(solver instanceof Player ? ((Player)solver).getUniqueId() : new UUID(0,0));
|
||||
ticket.setSolvedByName(solver.getName());
|
||||
|
||||
ticket.setSolveComment(comment);
|
||||
|
@ -46,6 +47,8 @@ public class XMemoryTicketDataStorage extends XTicketDataStorage {
|
|||
// this SHOULD be unnecessary, but just to be sure...
|
||||
tickets.put(ticket.getId(), ticket);
|
||||
|
||||
announceSolveTicket(ticket, solver, comment);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,6 +4,7 @@ import fi.xeno.aquamarine.XTicketsPlugin;
|
|||
import fi.xeno.aquamarine.sql.XHikariDatabase;
|
||||
import fi.xeno.aquamarine.util.XStoredLocation;
|
||||
import fi.xeno.aquamarine.util.XTicket;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
@ -118,11 +119,11 @@ public class XSQLTicketDataStorage extends XTicketDataStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void solveTicket(XTicket ticket, Player solver, String comment) {
|
||||
public void solveTicket(XTicket ticket, CommandSender solver, String comment) {
|
||||
|
||||
// these SHOULD be unneeded, but just in case...
|
||||
ticket.setSolved(true);
|
||||
ticket.setSolvedByUuid(solver.getUniqueId());
|
||||
ticket.setSolvedByUuid(solver instanceof Player ? ((Player)solver).getUniqueId() : new UUID(0,0));
|
||||
ticket.setSolvedByName(solver.getName());
|
||||
ticket.setSolveComment(comment);
|
||||
ticket.setTimeSolved(System.currentTimeMillis());
|
||||
|
@ -137,7 +138,7 @@ public class XSQLTicketDataStorage extends XTicketDataStorage {
|
|||
"SET isSolved = 1, solvedByUuid = ?, solvedByName = ?, solveComment = ?, timeSolved = ? " +
|
||||
"WHERE ticketId = ?");
|
||||
|
||||
st.setString(1, solver.getUniqueId().toString());
|
||||
st.setString(1, (solver instanceof Player ? ((Player)solver).getUniqueId() : new UUID(0,0)).toString());
|
||||
st.setString(2, solver.getName());
|
||||
|
||||
st.setString(3, comment);
|
||||
|
@ -146,6 +147,7 @@ public class XSQLTicketDataStorage extends XTicketDataStorage {
|
|||
st.setInt(5, ticket.getId());
|
||||
|
||||
st.executeUpdate();
|
||||
announceSolveTicket(ticket, solver, comment);
|
||||
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package fi.xeno.aquamarine.storage;
|
||||
|
||||
import fi.xeno.aquamarine.AquamarinePermission;
|
||||
import fi.xeno.aquamarine.XTicketsPlugin;
|
||||
import fi.xeno.aquamarine.util.XStoredLocation;
|
||||
import fi.xeno.aquamarine.util.XTicket;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -14,7 +16,7 @@ import java.util.function.Consumer;
|
|||
public abstract class XTicketDataStorage {
|
||||
|
||||
public abstract XTicket createTicket(Player player, String message);
|
||||
public abstract void solveTicket(XTicket ticket, Player solver, String comment);
|
||||
public abstract void solveTicket(XTicket ticket, CommandSender solver, String comment);
|
||||
|
||||
public abstract Optional<XTicket> getTicketByNumber(int id);
|
||||
|
||||
|
@ -42,7 +44,7 @@ public abstract class XTicketDataStorage {
|
|||
});
|
||||
}
|
||||
|
||||
public Optional<XTicket> solveTicket(int ticketId, Player solver, String comment) {
|
||||
public Optional<XTicket> solveTicket(int ticketId, CommandSender solver, String comment) {
|
||||
|
||||
XTicket ticket = getTicketByNumber(ticketId).orElse(null);
|
||||
|
||||
|
@ -55,6 +57,21 @@ public abstract class XTicketDataStorage {
|
|||
|
||||
}
|
||||
|
||||
public void announceSolveTicket(XTicket ticket, CommandSender sender, String comment) {
|
||||
|
||||
String announceText = XTicketsPlugin.getInstance().lang("command-ticket-solved")
|
||||
.replaceAll("\\$solver\\$", sender.getName())
|
||||
.replaceAll("\\$n\\$", ""+ticket.getId())
|
||||
.replaceAll("\\$comment\\$", comment);
|
||||
|
||||
Bukkit.getOnlinePlayers()
|
||||
.stream()
|
||||
.filter(p -> p.hasPermission(AquamarinePermission.STAFF)
|
||||
|| p.getUniqueId().equals(ticket.getSentByUuid()))
|
||||
.forEach(p -> XTicketsPlugin.getInstance().sendPrefixed(announceText, p));
|
||||
|
||||
}
|
||||
|
||||
public void solveTicketAsync(int ticketId, Player solver, String comment, Consumer<Optional<XTicket>> callback) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(XTicketsPlugin.getInstance(), () -> callback.accept(solveTicket(ticketId, solver, comment)));
|
||||
}
|
||||
|
|
|
@ -6,11 +6,20 @@ import fi.xeno.aquamarine.XTicketsPlugin;
|
|||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class XTicket {
|
||||
|
||||
|
@ -125,19 +134,26 @@ public class XTicket {
|
|||
this.timeSolved = timeSolved;
|
||||
}
|
||||
|
||||
|
||||
public BaseComponent[] renderChatPreview(boolean withButtons) {
|
||||
return renderChatPreview(withButtons, false);
|
||||
}
|
||||
|
||||
public BaseComponent[] renderChatPreview(boolean withButtons, boolean withFullText) {
|
||||
|
||||
ComponentBuilder out = new ComponentBuilder();
|
||||
XTicketsPlugin plugin = XTicketsPlugin.getInstance();
|
||||
|
||||
if (withButtons) {
|
||||
out.append(XText.commandButton("§7[§e»§7] ", "§e" + XTicketsPlugin.getInstance().lang("ticket-preview-teleport"), "/xt goto " + this.getId()));
|
||||
out.append(XText.commandButton("§7[§a✔§7] ", "§a" + XTicketsPlugin.getInstance().lang("ticket-preview-solve"), "/xt solve " + this.getId()));
|
||||
out.append(XText.commandButton("§8[§e»§8] ", "§e" + XTicketsPlugin.getInstance().lang("ticket-preview-teleport"), "/xt goto " + this.getId()));
|
||||
out.append(XText.commandSuggestButton("§8[§a✔§8] ", "§a" + XTicketsPlugin.getInstance().lang("ticket-preview-solve"), "/xt solve " + this.getId()));
|
||||
}
|
||||
|
||||
out.append(TextComponent.fromLegacyText("§b#" + this.getId() + " §f" + this.getSentByName() + " §7"));
|
||||
out.append(TextComponent.fromLegacyText((this.isSolved ? "§a" : "§b") + "#" + this.getId() + " §f" + this.getSentByName() + " §7"));
|
||||
|
||||
String previewString = this.message.length() > 40 ? this.message.substring(0, 40).trim() + "..." : this.message;
|
||||
String previewString = this.message.length() > 40 && !withFullText
|
||||
? this.message.substring(0, 40).trim() + "..."
|
||||
: this.message;
|
||||
|
||||
String solvedString = "";
|
||||
if (this.isSolved) {
|
||||
|
@ -148,12 +164,12 @@ public class XTicket {
|
|||
|
||||
}
|
||||
|
||||
String hoverString = plugin.lang("ticket-hover-title").replace("%ticketId%", ""+this.id) + "\n" +
|
||||
String hoverString = plugin.lang("ticket-hover-title").replaceAll("\\$ticketId\\$", ""+this.id) + "\n" +
|
||||
String.format(plugin.lang("ticket-hover-sender"), this.sentByName) + "\n" +
|
||||
String.format(plugin.lang("ticket-hover-timestamp"), plugin.formatTimestamp(this.timestamp)) + "\n" +
|
||||
String.format(plugin.lang("ticket-hover-location"), this.location.toReadable() + "\n" +
|
||||
String.format(plugin.lang("ticket-hover-location"), this.location.toReadable()) + "\n" +
|
||||
solvedString + "\n\n" +
|
||||
"§f§o" + XText.wordWrap(this.message, 40));
|
||||
"§f§o" + XText.wordWrap(this.message, 40);
|
||||
|
||||
out.append(XText.hoverText("§7" + previewString, hoverString));
|
||||
|
||||
|
@ -161,6 +177,38 @@ public class XTicket {
|
|||
|
||||
}
|
||||
|
||||
public ItemStack renderMenuItem() {
|
||||
|
||||
XTicketsPlugin plugin = XTicketsPlugin.getInstance();
|
||||
|
||||
ItemStack item = new ItemStack(Material.PAPER);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
meta.setDisplayName(plugin.lang("ticket-hover-title").replaceAll("\\$ticketId\\$", ""+this.getId()));
|
||||
|
||||
List<String> lore = new ArrayList<>();
|
||||
lore.add(String.format(plugin.lang("ticket-hover-sender"), this.sentByName));
|
||||
lore.add(String.format(plugin.lang("ticket-hover-timestamp"), plugin.formatTimestamp(this.timestamp)));
|
||||
lore.add(String.format(plugin.lang("ticket-hover-location"), this.location.toReadable()));
|
||||
lore.add("§r");
|
||||
lore.addAll(Arrays.stream(XText.wordWrap(this.message, 50).split("\\n"))
|
||||
.map(l -> "§7" + l)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
lore.add("§r");
|
||||
lore.add("§e■□ " + plugin.lang("gui-click-teleport"));
|
||||
lore.add("§a□■ " + plugin.lang("gui-click-solve"));
|
||||
|
||||
meta.setLore(lore);
|
||||
|
||||
PersistentDataContainer pd = meta.getPersistentDataContainer();
|
||||
pd.set(XTicketsPlugin.key("xTicketId"), PersistentDataType.STRING, ""+this.getId());
|
||||
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
|
||||
}
|
||||
|
||||
public JsonObject toJson() {
|
||||
|
||||
JsonObject out = new JsonObject();
|
||||
|
|
Loading…
Reference in New Issue
Block a user