Update from Git Manager GUI
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
package me.viper.teamplugin.manager;
|
||||
|
||||
import me.viper.teamplugin.Main;
|
||||
import me.viper.teamplugin.util.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Manages team-rank applications stored in data.yml under "Applications".
|
||||
*
|
||||
* Entry format per rank list: "playerName|isoTimestamp|reason"
|
||||
*/
|
||||
public class ApplicationManager {
|
||||
|
||||
// ── Submit ────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Submits an application for {@code applicant} to join {@code rank}.
|
||||
* Returns false if the player has already applied to any rank.
|
||||
*/
|
||||
public static boolean apply(Player applicant, String rank, String reason) {
|
||||
// Duplicate check across all ranks
|
||||
if (findApplication(applicant.getName()) != null) {
|
||||
applicant.sendMessage(Utils.color(LangManager.get("apply_already")));
|
||||
return false;
|
||||
}
|
||||
|
||||
FileConfiguration data = DataManager.getData();
|
||||
String key = "Applications." + rank;
|
||||
List<String> list = new ArrayList<>(data.getStringList(key));
|
||||
list.add(applicant.getName() + "|" + Utils.formatIsoNow() + "|" + (reason.isEmpty() ? "-" : reason));
|
||||
data.set(key, list);
|
||||
DataManager.save();
|
||||
|
||||
applicant.sendMessage(Utils.color(
|
||||
Utils.replace(LangManager.get("apply_sent"), "%rank%", rank)));
|
||||
|
||||
// Notify online admins
|
||||
if (Main.getInstance().getConfig().getBoolean("apply.notify_admins", true)) {
|
||||
String displayRank = Main.getInstance().getConfig()
|
||||
.getString("rank-settings." + rank + ".display", rank);
|
||||
String notify = Utils.color(Utils.replace(
|
||||
LangManager.get("apply_admin_notify"),
|
||||
"%player%", applicant.getName(),
|
||||
"%rank%", displayRank));
|
||||
for (Player admin : Bukkit.getOnlinePlayers()) {
|
||||
if (admin.hasPermission("teamplugin.admin")) admin.sendMessage(notify);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ── Query ─────────────────────────────────────────────────────────
|
||||
|
||||
/** Returns parsed applications for a single rank: each entry is [name, iso, reason]. */
|
||||
public static List<String[]> getApplications(String rank) {
|
||||
return DataManager.getData().getStringList("Applications." + rank)
|
||||
.stream()
|
||||
.map(s -> s.split("\\|", 3))
|
||||
.filter(a -> a.length == 3)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/** Returns all applications across all ranks: each entry is [rank, name, iso, reason]. */
|
||||
public static List<String[]> getAllApplications() {
|
||||
List<String[]> all = new ArrayList<>();
|
||||
for (String rank : Main.getInstance().getConfig().getStringList("ranks")) {
|
||||
for (String[] app : getApplications(rank)) {
|
||||
all.add(new String[]{rank, app[0], app[1], app[2]});
|
||||
}
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
/** Returns all player names that have a pending application. */
|
||||
public static List<String> getApplicantNames() {
|
||||
return getAllApplications().stream()
|
||||
.map(a -> a[1])
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/** Returns the rank a player has applied for, or null if not found. */
|
||||
public static String findApplication(String playerName) {
|
||||
for (String rank : Main.getInstance().getConfig().getStringList("ranks")) {
|
||||
boolean found = DataManager.getData()
|
||||
.getStringList("Applications." + rank)
|
||||
.stream()
|
||||
.anyMatch(e -> e.split("\\|", 3)[0].equalsIgnoreCase(playerName));
|
||||
if (found) return rank;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ── Remove ────────────────────────────────────────────────────────
|
||||
|
||||
/** Removes the application for playerName from all ranks. Returns true if one was found. */
|
||||
public static boolean removeApplication(String playerName) {
|
||||
FileConfiguration data = DataManager.getData();
|
||||
boolean removed = false;
|
||||
for (String rank : Main.getInstance().getConfig().getStringList("ranks")) {
|
||||
String key = "Applications." + rank;
|
||||
List<String> list = data.getStringList(key);
|
||||
boolean changed = list.removeIf(
|
||||
e -> e.split("\\|", 3)[0].equalsIgnoreCase(playerName));
|
||||
if (changed) {
|
||||
data.set(key, list.isEmpty() ? null : list);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
if (removed) DataManager.save();
|
||||
return removed;
|
||||
}
|
||||
}
|
||||
85
src/main/java/me/viper/teamplugin/manager/AuditLog.java
Normal file
85
src/main/java/me/viper/teamplugin/manager/AuditLog.java
Normal file
@@ -0,0 +1,85 @@
|
||||
package me.viper.teamplugin.manager;
|
||||
|
||||
import me.viper.teamplugin.Main;
|
||||
import me.viper.teamplugin.util.Utils;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Writes and reads audit entries in log.yml.
|
||||
*
|
||||
* Entry format:
|
||||
* 2026-03-08T12:00:00Z | ADD | by:AdminName | Steve → Owner
|
||||
*
|
||||
* Supported action strings (use the constants below for consistency):
|
||||
* ADD, REMOVE, MOVE, APPLY_ACCEPT, APPLY_DENY
|
||||
*/
|
||||
public class AuditLog {
|
||||
|
||||
public static final String ADD = "ADD";
|
||||
public static final String REMOVE = "REMOVE";
|
||||
public static final String MOVE = "MOVE";
|
||||
public static final String APPLY_ACCEPT = "APPLY_ACCEPT";
|
||||
public static final String APPLY_DENY = "APPLY_DENY";
|
||||
|
||||
private static File file;
|
||||
private static FileConfiguration cfg;
|
||||
|
||||
// ── File management ───────────────────────────────────────────────
|
||||
|
||||
private static void ensureLoaded() {
|
||||
if (cfg != null) return;
|
||||
file = new File(Main.getInstance().getDataFolder(), "log.yml");
|
||||
try { if (!file.exists()) file.createNewFile(); }
|
||||
catch (IOException e) { e.printStackTrace(); }
|
||||
cfg = YamlConfiguration.loadConfiguration(file);
|
||||
}
|
||||
|
||||
private static void save() {
|
||||
try { if (cfg != null && file != null) cfg.save(file); }
|
||||
catch (IOException e) { e.printStackTrace(); }
|
||||
}
|
||||
|
||||
public static void reload() { cfg = null; }
|
||||
|
||||
// ── API ───────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Appends an audit entry.
|
||||
*
|
||||
* @param action one of the constants above, e.g. AuditLog.ADD
|
||||
* @param performedBy name of the command sender (player or "CONSOLE")
|
||||
* @param detail human-readable summary, e.g. "Steve → Owner"
|
||||
*/
|
||||
public static void log(String action, String performedBy, String detail) {
|
||||
ensureLoaded();
|
||||
String entry = Utils.formatIsoNow()
|
||||
+ " | " + action
|
||||
+ " | by:" + performedBy
|
||||
+ " | " + detail;
|
||||
|
||||
List<String> entries = new ArrayList<>(cfg.getStringList("entries"));
|
||||
entries.add(entry);
|
||||
|
||||
int max = Main.getInstance().getConfig().getInt("audit.keep", 500);
|
||||
if (entries.size() > max) entries = entries.subList(entries.size() - max, entries.size());
|
||||
|
||||
cfg.set("entries", entries);
|
||||
save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last {@code limit} entries, most recent last.
|
||||
*/
|
||||
public static List<String> getEntries(int limit) {
|
||||
ensureLoaded();
|
||||
List<String> all = cfg.getStringList("entries");
|
||||
int from = Math.max(0, all.size() - limit);
|
||||
return new ArrayList<>(all.subList(from, all.size()));
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,34 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class LangManager {
|
||||
private static File file;
|
||||
|
||||
private static File file;
|
||||
private static FileConfiguration cfg;
|
||||
private static String loadedLanguage;
|
||||
|
||||
// ── Setup ─────────────────────────────────────────────────────────
|
||||
|
||||
public static void setup() {
|
||||
file = new File(Main.getInstance().getDataFolder(), "lang.yml");
|
||||
if (!file.exists()) {
|
||||
Main.getInstance().saveResource("lang.yml", false);
|
||||
}
|
||||
cfg = YamlConfiguration.loadConfiguration(file);
|
||||
String lang = Main.getInstance().getConfig().getString("language", "de").toLowerCase();
|
||||
String fileName = "lang_" + lang + ".yml";
|
||||
|
||||
// Both lang files are saved by Main.java on startup.
|
||||
// Here we just load the correct one.
|
||||
File target = new File(Main.getInstance().getDataFolder(), fileName);
|
||||
file = target;
|
||||
cfg = YamlConfiguration.loadConfiguration(file);
|
||||
loadedLanguage = lang;
|
||||
|
||||
Main.getInstance().getLogger().info(
|
||||
"[LangManager] Loaded language: " + lang + " (" + fileName + ")");
|
||||
}
|
||||
|
||||
// ── Getters ───────────────────────────────────────────────────────
|
||||
|
||||
public static String get(String path) {
|
||||
if (cfg == null) setup();
|
||||
return cfg.getString(path, "Missing:" + path).replace("%prefix%", cfg.getString("prefix", ""));
|
||||
String raw = cfg.getString(path, "Missing:" + path);
|
||||
return raw.replace("%prefix%", cfg.getString("prefix", ""));
|
||||
}
|
||||
|
||||
public static List<String> getList(String path) {
|
||||
@@ -30,11 +44,23 @@ public class LangManager {
|
||||
return cfg.getStringList(path);
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
try {
|
||||
if (cfg != null && file != null) cfg.save(file);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
/** Returns the currently active language code ("de" or "en"). */
|
||||
public static String getLanguage() {
|
||||
return loadedLanguage != null ? loadedLanguage : "de";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured subcommand name for a given key, e.g.
|
||||
* getCmd("cmd_add") → "hinzufügen" (DE) or "add" (EN).
|
||||
*/
|
||||
public static String getCmd(String key) {
|
||||
return get(key);
|
||||
}
|
||||
|
||||
// ── Save ──────────────────────────────────────────────────────────
|
||||
|
||||
public static void save() {
|
||||
try { if (cfg != null && file != null) cfg.save(file); }
|
||||
catch (IOException e) { e.printStackTrace(); }
|
||||
}
|
||||
}
|
||||
144
src/main/java/me/viper/teamplugin/manager/MailboxManager.java
Normal file
144
src/main/java/me/viper/teamplugin/manager/MailboxManager.java
Normal file
@@ -0,0 +1,144 @@
|
||||
package me.viper.teamplugin.manager;
|
||||
|
||||
import me.viper.teamplugin.Main;
|
||||
import me.viper.teamplugin.util.Utils;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Manages mailbox.yml – per-player inbox and message history.
|
||||
*
|
||||
* Entry format (pipe-separated, limit 5 so text may contain '|'):
|
||||
* id|fromName|isoTimestamp|readBool|messageText
|
||||
*
|
||||
* Sections in mailbox.yml:
|
||||
* Mailbox.<playerName> – current inbox messages
|
||||
* History.<playerName> – all sent/received messages (last mail.history_max)
|
||||
*/
|
||||
public class MailboxManager {
|
||||
|
||||
private static File file;
|
||||
private static FileConfiguration cfg;
|
||||
|
||||
// ── File management ───────────────────────────────────────────────
|
||||
|
||||
private static void ensureLoaded() {
|
||||
if (cfg != null) return;
|
||||
file = new File(Main.getInstance().getDataFolder(), "mailbox.yml");
|
||||
try { if (!file.exists()) file.createNewFile(); }
|
||||
catch (IOException e) { e.printStackTrace(); }
|
||||
cfg = YamlConfiguration.loadConfiguration(file);
|
||||
}
|
||||
|
||||
private static void save() {
|
||||
try { if (cfg != null && file != null) cfg.save(file); }
|
||||
catch (IOException e) { e.printStackTrace(); }
|
||||
}
|
||||
|
||||
public static void reload() { cfg = null; }
|
||||
|
||||
// ── Store ─────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Stores a new message in the recipient's inbox and updates history for
|
||||
* both parties. Returns the generated message ID.
|
||||
*/
|
||||
public static String store(String recipient, String fromName, String text) {
|
||||
ensureLoaded();
|
||||
String id = String.valueOf(System.currentTimeMillis());
|
||||
String iso = Utils.formatIsoNow();
|
||||
String entry = id + "|" + fromName + "|" + iso + "|false|" + text;
|
||||
|
||||
// Recipient inbox
|
||||
List<String> inbox = cfg.getStringList("Mailbox." + recipient);
|
||||
inbox.add(entry);
|
||||
cfg.set("Mailbox." + recipient, inbox);
|
||||
|
||||
// History: recipient sees received message as unread
|
||||
addToHistory(recipient, entry);
|
||||
// History: sender sees their own message as already read (true)
|
||||
addToHistory(fromName, id + "|" + fromName + "|" + iso + "|true|" + text);
|
||||
|
||||
save();
|
||||
return id;
|
||||
}
|
||||
|
||||
// ── Read ──────────────────────────────────────────────────────────
|
||||
|
||||
/** Returns parsed message arrays for a player's inbox, newest first. */
|
||||
public static List<String[]> getParsedMessages(String player) {
|
||||
ensureLoaded();
|
||||
List<String[]> result = cfg.getStringList("Mailbox." + player).stream()
|
||||
.map(s -> s.split("\\|", 5))
|
||||
.filter(a -> a.length == 5)
|
||||
.collect(Collectors.toList());
|
||||
// Newest first (highest id = highest timestamp)
|
||||
result.sort((a, b) -> Long.compare(
|
||||
parseLong(b[0]), parseLong(a[0])));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int getUnreadCount(String player) {
|
||||
ensureLoaded();
|
||||
return (int) getParsedMessages(player).stream()
|
||||
.filter(a -> "false".equals(a[3]))
|
||||
.count();
|
||||
}
|
||||
|
||||
// ── Mutations ─────────────────────────────────────────────────────
|
||||
|
||||
public static void markRead(String player, String msgId) {
|
||||
ensureLoaded();
|
||||
List<String> updated = cfg.getStringList("Mailbox." + player).stream()
|
||||
.map(s -> {
|
||||
String[] p = s.split("\\|", 5);
|
||||
return (p.length == 5 && p[0].equals(msgId))
|
||||
? p[0] + "|" + p[1] + "|" + p[2] + "|true|" + p[4]
|
||||
: s;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
cfg.set("Mailbox." + player, updated);
|
||||
save();
|
||||
}
|
||||
|
||||
public static void delete(String player, String msgId) {
|
||||
ensureLoaded();
|
||||
List<String> remaining = cfg.getStringList("Mailbox." + player).stream()
|
||||
.filter(s -> !s.startsWith(msgId + "|"))
|
||||
.collect(Collectors.toList());
|
||||
cfg.set("Mailbox." + player, remaining.isEmpty() ? null : remaining);
|
||||
save();
|
||||
}
|
||||
|
||||
// ── History ───────────────────────────────────────────────────────
|
||||
|
||||
private static void addToHistory(String player, String entry) {
|
||||
int max = Main.getInstance().getConfig().getInt("mail.history_max", 50);
|
||||
List<String> hist = new ArrayList<>(cfg.getStringList("History." + player));
|
||||
hist.add(entry);
|
||||
if (hist.size() > max) hist = hist.subList(hist.size() - max, hist.size());
|
||||
cfg.set("History." + player, hist);
|
||||
}
|
||||
|
||||
public static List<String[]> getHistory(String player) {
|
||||
ensureLoaded();
|
||||
List<String[]> result = cfg.getStringList("History." + player).stream()
|
||||
.map(s -> s.split("\\|", 5))
|
||||
.filter(a -> a.length == 5)
|
||||
.collect(Collectors.toList());
|
||||
result.sort((a, b) -> Long.compare(parseLong(b[0]), parseLong(a[0])));
|
||||
return result;
|
||||
}
|
||||
|
||||
// ── Helper ────────────────────────────────────────────────────────
|
||||
|
||||
private static long parseLong(String s) {
|
||||
try { return Long.parseLong(s); } catch (NumberFormatException e) { return 0L; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package me.viper.teamplugin.manager;
|
||||
|
||||
import me.viper.teamplugin.util.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MessageManager {
|
||||
|
||||
private static final Map<UUID, String> PENDING_INPUT = new HashMap<>();
|
||||
private static final Map<UUID, String> PENDING_REPLY = new HashMap<>();
|
||||
|
||||
public static void startInput(Player sender, String targetName) {
|
||||
PENDING_INPUT.put(sender.getUniqueId(), targetName);
|
||||
sender.sendMessage(Utils.color(
|
||||
Utils.replace(LangManager.get("msg_enter_message"), "%player%", targetName)));
|
||||
sender.sendMessage(Utils.color(LangManager.get("msg_cancel_hint")));
|
||||
}
|
||||
|
||||
public static void startReply(Player sender, String targetName) {
|
||||
PENDING_REPLY.put(sender.getUniqueId(), targetName);
|
||||
sender.sendMessage(Utils.color(
|
||||
Utils.replace(LangManager.get("msg_reply_prompt"), "%player%", targetName)));
|
||||
sender.sendMessage(Utils.color(LangManager.get("msg_cancel_hint")));
|
||||
}
|
||||
|
||||
public static boolean isAwaitingInput(UUID uuid) {
|
||||
return PENDING_INPUT.containsKey(uuid) || PENDING_REPLY.containsKey(uuid);
|
||||
}
|
||||
|
||||
public static boolean handleInput(Player sender, String text) {
|
||||
String target = PENDING_INPUT.remove(sender.getUniqueId());
|
||||
if (target == null) target = PENDING_REPLY.remove(sender.getUniqueId());
|
||||
if (target == null) return false;
|
||||
|
||||
if (text.equalsIgnoreCase(LangManager.get("msg_cancel_word"))) {
|
||||
sender.sendMessage(Utils.color(LangManager.get("msg_cancelled")));
|
||||
return true;
|
||||
}
|
||||
deliver(sender, target, text);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void cancelInput(UUID uuid) {
|
||||
PENDING_INPUT.remove(uuid);
|
||||
PENDING_REPLY.remove(uuid);
|
||||
}
|
||||
|
||||
private static void deliver(Player sender, String targetName, String text) {
|
||||
MailboxManager.store(targetName, sender.getName(), text);
|
||||
|
||||
Player target = Bukkit.getPlayerExact(targetName);
|
||||
if (target != null && target.isOnline()) {
|
||||
String formatted = Utils.color(Utils.replace(
|
||||
LangManager.get("msg_format"),
|
||||
"%sender%", sender.getName(),
|
||||
"%message%", text));
|
||||
target.sendMessage(formatted);
|
||||
sender.sendMessage(Utils.color(
|
||||
Utils.replace(LangManager.get("msg_sent_online"), "%player%", targetName)));
|
||||
} else {
|
||||
sender.sendMessage(Utils.color(
|
||||
Utils.replace(LangManager.get("msg_sent_offline"), "%player%", targetName)));
|
||||
}
|
||||
}
|
||||
|
||||
public static void deliverPending(Player player) {
|
||||
int unread = MailboxManager.getUnreadCount(player.getName());
|
||||
if (unread == 0) return;
|
||||
Bukkit.getScheduler().runTaskLater(
|
||||
me.viper.teamplugin.Main.getInstance(), () -> {
|
||||
player.sendMessage(Utils.color(Utils.replace(
|
||||
LangManager.get("msg_offline_header"),
|
||||
"%count%", String.valueOf(unread))));
|
||||
player.sendMessage(Utils.color(LangManager.get("msg_mailbox_hint")));
|
||||
}, 20L);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user