Upload folder via GUI - src
This commit is contained in:
@@ -92,10 +92,15 @@ public class IngameShopSpigot extends JavaPlugin implements Listener {
|
||||
private Map<Integer, OrderData> orderCache = new HashMap<>();
|
||||
private Map<UUID, Integer> activeOrderIds = new ConcurrentHashMap<>();
|
||||
|
||||
private FlyManager flyManager;
|
||||
private FlyCodeManager flyCodeManager;
|
||||
private RankManager rankManager;
|
||||
private FlyAboManager flyAboManager;
|
||||
private FlyManager flyManager;
|
||||
private FlyCodeManager flyCodeManager;
|
||||
private RankManager rankManager;
|
||||
private FlyAboManager flyAboManager;
|
||||
private PlotSlotManager plotSlotManager;
|
||||
|
||||
// Plot-Slot Konfiguration
|
||||
private String plotServer = "citybuild";
|
||||
private Map<String, Integer> plotRankDefaults = new HashMap<>();
|
||||
|
||||
private static final String GUI_FLYCODES = ChatColor.GOLD + "✈ Deine Fly-Gutscheine";
|
||||
private final Map<UUID, Integer> flyCodesPage = new HashMap<>();
|
||||
@@ -140,6 +145,22 @@ public class IngameShopSpigot extends JavaPlugin implements Listener {
|
||||
sellPriceOffset = getConfig().getDouble("sell.price-offset", 0.0);
|
||||
flyAboMaxDailySec = getConfig().getInt("fly-abo.max-daily-hours", 6) * 3600;
|
||||
|
||||
// Plot-Slot Konfiguration laden
|
||||
plotServer = getConfig().getString("plot-slots.server", "citybuild").toLowerCase();
|
||||
plotRankDefaults.clear();
|
||||
org.bukkit.configuration.ConfigurationSection rankSec =
|
||||
getConfig().getConfigurationSection("plot-slots.rank-defaults");
|
||||
if (rankSec != null) {
|
||||
for (String key : rankSec.getKeys(false))
|
||||
plotRankDefaults.put(key.toLowerCase(), rankSec.getInt(key, 2));
|
||||
} else {
|
||||
// Viper Network Defaults
|
||||
plotRankDefaults.put("member", 2);
|
||||
plotRankDefaults.put("vip", 3);
|
||||
plotRankDefaults.put("scout", 4);
|
||||
plotRankDefaults.put("primo", 5);
|
||||
}
|
||||
|
||||
if (apiKey.isEmpty()) {
|
||||
getLogger().warning("⚠️ Kein api-key in config.yml gesetzt!");
|
||||
}
|
||||
@@ -156,6 +177,8 @@ public class IngameShopSpigot extends JavaPlugin implements Listener {
|
||||
rankManager.startExpiryChecker();
|
||||
flyAboManager = new FlyAboManager(this, flyCodeManager);
|
||||
flyAboManager.startDailyResetChecker();
|
||||
plotSlotManager = new PlotSlotManager(this, flyCodeManager);
|
||||
plotSlotManager.startBillingChecker();
|
||||
|
||||
int intervalSeconds = getConfig().getInt("check-interval", 10);
|
||||
long pollInterval = intervalSeconds * 20L;
|
||||
@@ -171,6 +194,11 @@ public class IngameShopSpigot extends JavaPlugin implements Listener {
|
||||
getCommand("flyabo").setExecutor(new FlyAboCommand());
|
||||
getCommand("flyabocancel").setExecutor(new FlyAboCancelCommand());
|
||||
getCommand("flyabogive").setExecutor(new FlyAboGiveCommand());
|
||||
getCommand("plotslots").setExecutor(new PlotSlotsCommand());
|
||||
getCommand("plotabo").setExecutor(new PlotAboCommand());
|
||||
getCommand("plotabocancel").setExecutor(new PlotAboCancelCommand());
|
||||
getCommand("plotabogive").setExecutor(new PlotAboGiveCommand());
|
||||
getCommand("plotslotsgive").setExecutor(new PlotSlotsGiveCommand());
|
||||
getCommand("sell").setExecutor(new SellCommand());
|
||||
getCommand("wpis").setExecutor(new ReloadCommand());
|
||||
|
||||
@@ -358,6 +386,13 @@ public class IngameShopSpigot extends JavaPlugin implements Listener {
|
||||
@Override public void run() { flyAboManager.onPlayerJoin(p); }
|
||||
}.runTaskAsynchronously(this);
|
||||
|
||||
// Plot-Slot Limit anwenden (nur auf Plot-Server)
|
||||
if (targetServer.equalsIgnoreCase(plotServer)) {
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() { plotSlotManager.onPlayerJoin(p); }
|
||||
}.runTaskAsynchronously(this);
|
||||
}
|
||||
|
||||
// Ausstehende Fly-Codes anzeigen
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
@@ -928,6 +963,25 @@ public class IngameShopSpigot extends JavaPlugin implements Listener {
|
||||
flyAboManager.grantAbo(player, label, monthlyPrice);
|
||||
anyCode = true;
|
||||
|
||||
} else if ("plot_slots".equals(type)) {
|
||||
// Einmalige Plot-Slot Erweiterung (permanent)
|
||||
int slots = cmdObj.has("slots")
|
||||
? cmdObj.get("slots").getAsInt() : 1;
|
||||
String label = cmdObj.has("label")
|
||||
? cmdObj.get("label").getAsString() : slots + " Extra-Plot-Slot(s)";
|
||||
plotSlotManager.grantExtraSlots(player, slots, label);
|
||||
anyCode = true;
|
||||
|
||||
} else if ("plot_abo".equals(type)) {
|
||||
// Monatliches Plot-Abo
|
||||
int slots = cmdObj.has("slots")
|
||||
? cmdObj.get("slots").getAsInt() : 1;
|
||||
String label = cmdObj.has("label")
|
||||
? cmdObj.get("label").getAsString() : "Plot-Abo +" + slots;
|
||||
int monthlyPrice = (int) data.price;
|
||||
plotSlotManager.grantAbo(player, slots, label, monthlyPrice);
|
||||
anyCode = true;
|
||||
|
||||
} else if ("generic".equals(type) && cmdObj.has("cmd")) {
|
||||
String cmd = cmdObj.get("cmd").getAsString()
|
||||
.replace("{player}", player.getName());
|
||||
@@ -1453,6 +1507,208 @@ public class IngameShopSpigot extends JavaPlugin implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// PLOT-SLOT COMMANDS
|
||||
// ===========================================================
|
||||
|
||||
/** /plotslots – Gesamtstatus: Basis + extra + Abo */
|
||||
private class PlotSlotsCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command,
|
||||
String label, String[] args) {
|
||||
if (!(sender instanceof Player)) { sender.sendMessage("Nur für Spieler."); return true; }
|
||||
Player p = (Player) sender;
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
int base = plotSlotManager.getRankBase(p);
|
||||
int extra = plotSlotManager.getExtraSlots(p.getName());
|
||||
int abo = plotSlotManager.getAboSlots(p.getName());
|
||||
int total = base + extra + abo;
|
||||
Bukkit.getScheduler().runTask(IngameShopSpigot.this, () -> {
|
||||
p.sendMessage(ChatColor.GOLD + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
p.sendMessage(ChatColor.YELLOW + "📦 Deine Plot-Slots:");
|
||||
p.sendMessage(ChatColor.GOLD + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
p.sendMessage(ChatColor.AQUA + " Rang-Basis: " + ChatColor.WHITE + base);
|
||||
p.sendMessage(ChatColor.AQUA + " Einmalig: " + ChatColor.WHITE + extra);
|
||||
p.sendMessage(ChatColor.AQUA + " Abo: " + ChatColor.WHITE + abo);
|
||||
p.sendMessage(ChatColor.AQUA + " Gesamt: " + ChatColor.GREEN + total);
|
||||
p.sendMessage(ChatColor.GRAY + " Mehr Slots: " + ChatColor.AQUA + "viper-network.de");
|
||||
p.sendMessage(ChatColor.GOLD + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
});
|
||||
}
|
||||
}.runTaskAsynchronously(IngameShopSpigot.this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/** /plotabo – Abo-Status anzeigen */
|
||||
private class PlotAboCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command,
|
||||
String label, String[] args) {
|
||||
if (!(sender instanceof Player)) { sender.sendMessage("Nur für Spieler."); return true; }
|
||||
Player p = (Player) sender;
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
PlotSlotManager.PlotAboEntry abo = plotSlotManager.getActiveAbo(p.getName());
|
||||
Bukkit.getScheduler().runTask(IngameShopSpigot.this, () -> {
|
||||
p.sendMessage(ChatColor.GOLD + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
p.sendMessage(ChatColor.YELLOW + "📦 Dein Plot-Abo:");
|
||||
p.sendMessage(ChatColor.GOLD + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
if (abo == null) {
|
||||
p.sendMessage(ChatColor.GRAY + " Kein aktives Plot-Abo.");
|
||||
p.sendMessage(ChatColor.GRAY + " Im Shop erhältlich: " + ChatColor.AQUA + "viper-network.de");
|
||||
} else {
|
||||
p.sendMessage(ChatColor.AQUA + " Paket: " + ChatColor.WHITE + abo.label);
|
||||
p.sendMessage(ChatColor.AQUA + " Slots: " + ChatColor.WHITE + "+" + abo.aboSlots);
|
||||
p.sendMessage(ChatColor.AQUA + " Preis: " + ChatColor.WHITE + abo.monthlyPrice + " " + currency + " / Monat");
|
||||
if (abo.cancelled) {
|
||||
String reason = "payment_failed".equals(abo.cancellationReason)
|
||||
? " (Zahlung fehlgeschlagen)" : " (durch dich)";
|
||||
p.sendMessage(ChatColor.RED + " Status: ⚠ Gekündigt" + reason);
|
||||
p.sendMessage(ChatColor.AQUA + " Aktiv bis: " + ChatColor.YELLOW + abo.periodEnd);
|
||||
} else {
|
||||
p.sendMessage(ChatColor.AQUA + " Status: " + ChatColor.GREEN + "✔ Aktiv");
|
||||
p.sendMessage(ChatColor.AQUA + " Aktiv bis: " + ChatColor.YELLOW + abo.periodEnd);
|
||||
p.sendMessage(ChatColor.AQUA + " Nächste Abbuchung: " + ChatColor.WHITE + abo.nextBillingDate);
|
||||
p.sendMessage(ChatColor.GRAY + " Kündigen: " + ChatColor.WHITE + "/plotabocancel");
|
||||
}
|
||||
}
|
||||
p.sendMessage(ChatColor.GOLD + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
||||
});
|
||||
}
|
||||
}.runTaskAsynchronously(IngameShopSpigot.this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/** /plotabocancel [confirm] – Abo zum Monatsende kündigen */
|
||||
private class PlotAboCancelCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command,
|
||||
String label, String[] args) {
|
||||
if (!(sender instanceof Player)) { sender.sendMessage("Nur für Spieler."); return true; }
|
||||
Player p = (Player) sender;
|
||||
if (args.length == 0 || !args[0].equalsIgnoreCase("confirm")) {
|
||||
p.sendMessage(ChatColor.YELLOW + "⚠ Möchtest du dein Plot-Abo wirklich kündigen?");
|
||||
p.sendMessage(ChatColor.GRAY + " Die Abo-Slots bleiben bis Monatsende erhalten.");
|
||||
p.sendMessage(ChatColor.GRAY + " Plots mit überzähligen Slots werden eingefroren.");
|
||||
p.sendMessage(ChatColor.WHITE + " Bestätigen: " + ChatColor.RED + "/plotabocancel confirm");
|
||||
return true;
|
||||
}
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
boolean ok = plotSlotManager.cancelAbo(p.getName());
|
||||
Bukkit.getScheduler().runTask(IngameShopSpigot.this, () -> {
|
||||
if (ok) {
|
||||
p.sendMessage(ChatColor.YELLOW + "📦 Plot-Abo zur Kündigung vorgemerkt.");
|
||||
p.sendMessage(ChatColor.GRAY + " Deine Abo-Slots bleiben bis Ende des Monats aktiv.");
|
||||
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1.0F, 0.8F);
|
||||
} else {
|
||||
p.sendMessage(ChatColor.RED + "✗ Kein aktives Plot-Abo gefunden.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}.runTaskAsynchronously(IngameShopSpigot.this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/** /plotabogive <Spieler> <Slots> <Monatspreis> [Label] – Admin */
|
||||
private class PlotAboGiveCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command,
|
||||
String label, String[] args) {
|
||||
if (!sender.hasPermission("ingameshop.plotabogive")) {
|
||||
sender.sendMessage(ChatColor.RED + "✗ Keine Berechtigung.");
|
||||
return true;
|
||||
}
|
||||
if (args.length < 3) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "Verwendung: /plotabogive <Spieler> <Slots> <Monatspreis> [Label]");
|
||||
return true;
|
||||
}
|
||||
String targetName = args[0];
|
||||
int slots, price;
|
||||
try { slots = Integer.parseInt(args[1]); price = Integer.parseInt(args[2]); }
|
||||
catch (NumberFormatException e) {
|
||||
sender.sendMessage(ChatColor.RED + "✗ Slots und Preis müssen Zahlen sein.");
|
||||
return true;
|
||||
}
|
||||
String aboLabel = args.length >= 4
|
||||
? String.join(" ", Arrays.copyOfRange(args, 3, args.length))
|
||||
: "Plot-Abo +" + slots;
|
||||
Player target = Bukkit.getPlayer(targetName);
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
plotSlotManager.grantAboByName(targetName, slots, aboLabel, price);
|
||||
Bukkit.getScheduler().runTask(IngameShopSpigot.this, () -> {
|
||||
sender.sendMessage(ChatColor.GREEN + "✔ Plot-Abo (+" + slots + " Slots) an "
|
||||
+ ChatColor.YELLOW + targetName + ChatColor.GREEN + " vergeben.");
|
||||
if (target != null && target.isOnline()) {
|
||||
target.sendMessage("");
|
||||
target.sendMessage(ChatColor.GOLD + "📦 ════════════════════════════");
|
||||
target.sendMessage(ChatColor.YELLOW + " Plot-Abo aktiviert!");
|
||||
target.sendMessage(ChatColor.GRAY + " Paket: " + ChatColor.WHITE + aboLabel);
|
||||
target.sendMessage(ChatColor.GRAY + " Slots: " + ChatColor.WHITE + "+" + slots);
|
||||
target.sendMessage(ChatColor.GRAY + " Monatspreis: " + ChatColor.WHITE + price + " " + currency);
|
||||
target.sendMessage(ChatColor.GRAY + " Status: /plotabo");
|
||||
target.sendMessage(ChatColor.GOLD + " ════════════════════════════");
|
||||
target.playSound(target.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0F, 1.2F);
|
||||
}
|
||||
});
|
||||
}
|
||||
}.runTaskAsynchronously(IngameShopSpigot.this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/** /plotslotsgive <Spieler> <Slots> [Label] – Admin gibt permanente Slots */
|
||||
private class PlotSlotsGiveCommand implements CommandExecutor {
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command,
|
||||
String label, String[] args) {
|
||||
if (!sender.hasPermission("ingameshop.plotslotsgive")) {
|
||||
sender.sendMessage(ChatColor.RED + "✗ Keine Berechtigung.");
|
||||
return true;
|
||||
}
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "Verwendung: /plotslotsgive <Spieler> <Slots> [Label]");
|
||||
return true;
|
||||
}
|
||||
String targetName = args[0];
|
||||
int slots;
|
||||
try { slots = Integer.parseInt(args[1]); }
|
||||
catch (NumberFormatException e) {
|
||||
sender.sendMessage(ChatColor.RED + "✗ Slots muss eine Zahl sein.");
|
||||
return true;
|
||||
}
|
||||
String slotLabel = args.length >= 3
|
||||
? String.join(" ", Arrays.copyOfRange(args, 2, args.length))
|
||||
: "+" + slots + " Plot-Slots";
|
||||
Player target = Bukkit.getPlayer(targetName);
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
plotSlotManager.grantExtraSlotsByName(targetName, slots, slotLabel);
|
||||
Bukkit.getScheduler().runTask(IngameShopSpigot.this, () -> {
|
||||
sender.sendMessage(ChatColor.GREEN + "✔ " + slots + " permanente Plot-Slots an "
|
||||
+ ChatColor.YELLOW + targetName + ChatColor.GREEN + " vergeben.");
|
||||
if (target != null && target.isOnline()) {
|
||||
target.sendMessage("");
|
||||
target.sendMessage(ChatColor.GOLD + "📦 ════════════════════════════");
|
||||
target.sendMessage(ChatColor.YELLOW + " Plot-Slots erweitert!");
|
||||
target.sendMessage(ChatColor.GRAY + " Paket: " + ChatColor.WHITE + slotLabel);
|
||||
target.sendMessage(ChatColor.GRAY + " Dauerhaft: +" + slots + " Slots");
|
||||
target.sendMessage(ChatColor.GRAY + " Status: /plotslots");
|
||||
target.sendMessage(ChatColor.GOLD + " ════════════════════════════");
|
||||
target.playSound(target.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0F, 1.0F);
|
||||
}
|
||||
});
|
||||
}
|
||||
}.runTaskAsynchronously(IngameShopSpigot.this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// HTTP HILFSMETHODEN
|
||||
// ===========================================================
|
||||
@@ -2362,7 +2618,7 @@ public class IngameShopSpigot extends JavaPlugin implements Listener {
|
||||
|
||||
FlyAboManager.AboEntry getActiveAbo(String playerName) {
|
||||
String sql =
|
||||
"SELECT label, monthly_price, cancelled, cancellation_reason,"
|
||||
"SELECT player_name, label, monthly_price, cancelled, cancellation_reason,"
|
||||
+ " DATE_FORMAT(next_billing_date, '%d.%m.%Y') AS billing_fmt,"
|
||||
+ " DATE_FORMAT(period_end, '%d.%m.%Y') AS period_fmt"
|
||||
+ " FROM wis_fly_abos"
|
||||
@@ -2426,6 +2682,235 @@ public class IngameShopSpigot extends JavaPlugin implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Plot-Slot CRUD ────────────────────────────────────────────────
|
||||
|
||||
void createPlotSlotTables() {
|
||||
String sqlExtra =
|
||||
"CREATE TABLE IF NOT EXISTS wis_plot_extra_slots ("
|
||||
+ " id INT AUTO_INCREMENT PRIMARY KEY,"
|
||||
+ " player_name VARCHAR(64) NOT NULL COLLATE utf8mb4_general_ci,"
|
||||
+ " extra_slots INT NOT NULL DEFAULT 0,"
|
||||
+ " last_perm INT NOT NULL DEFAULT 0,"
|
||||
+ " granted_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,"
|
||||
+ " UNIQUE KEY uq_player (player_name)"
|
||||
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
String sqlAbo =
|
||||
"CREATE TABLE IF NOT EXISTS wis_plot_abos ("
|
||||
+ " id INT AUTO_INCREMENT PRIMARY KEY,"
|
||||
+ " player_name VARCHAR(64) NOT NULL COLLATE utf8mb4_general_ci,"
|
||||
+ " label VARCHAR(128) NOT NULL,"
|
||||
+ " abo_slots INT NOT NULL DEFAULT 1,"
|
||||
+ " monthly_price INT NOT NULL DEFAULT 0,"
|
||||
+ " cancelled TINYINT(1) NOT NULL DEFAULT 0,"
|
||||
+ " cancellation_reason VARCHAR(32) DEFAULT NULL,"
|
||||
+ " next_billing_date DATE NOT NULL,"
|
||||
+ " period_end DATE NOT NULL,"
|
||||
+ " granted_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,"
|
||||
+ " UNIQUE KEY uq_player (player_name)"
|
||||
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
stmt.execute(sqlExtra);
|
||||
stmt.execute(sqlAbo);
|
||||
// Migration: last_perm Spalte ergänzen falls Tabelle schon existiert
|
||||
try { stmt.execute("ALTER TABLE wis_plot_extra_slots ADD COLUMN IF NOT EXISTS last_perm INT NOT NULL DEFAULT 0 AFTER extra_slots"); }
|
||||
catch (SQLException ignored) {}
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Plot-Slot-Tabellen Erstellung fehlgeschlagen", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Letzten Permission-Wert lesen/schreiben (für sauberes Entfernen)
|
||||
int getLastPerm(String playerName) {
|
||||
String sql = "SELECT last_perm FROM wis_plot_extra_slots WHERE player_name = ?";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) return rs.getInt("last_perm");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "getLastPerm SQL Fehler", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void saveLastPerm(String playerName, int perm) {
|
||||
String sql =
|
||||
"INSERT INTO wis_plot_extra_slots (player_name, extra_slots, last_perm)"
|
||||
+ " VALUES (?, 0, ?)"
|
||||
+ " ON DUPLICATE KEY UPDATE last_perm = ?";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
ps.setInt(2, perm);
|
||||
ps.setInt(3, perm);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "saveLastPerm SQL Fehler", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Extra-Slots (permanent)
|
||||
void addExtraSlots(String playerName, int slots) {
|
||||
String sql =
|
||||
"INSERT INTO wis_plot_extra_slots (player_name, extra_slots)"
|
||||
+ " VALUES (?, ?)"
|
||||
+ " ON DUPLICATE KEY UPDATE extra_slots = extra_slots + ?";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
ps.setInt(2, slots);
|
||||
ps.setInt(3, slots);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "addExtraSlots SQL Fehler", e);
|
||||
}
|
||||
}
|
||||
|
||||
int getExtraSlots(String playerName) {
|
||||
String sql = "SELECT extra_slots FROM wis_plot_extra_slots WHERE player_name = ?";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) return rs.getInt("extra_slots");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "getExtraSlots SQL Fehler", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Plot-Abo
|
||||
void savePlotAbo(String playerName, int slots, String label, int monthlyPrice) {
|
||||
String sql =
|
||||
"INSERT INTO wis_plot_abos"
|
||||
+ " (player_name, label, abo_slots, monthly_price, cancelled, cancellation_reason,"
|
||||
+ " next_billing_date, period_end)"
|
||||
+ " VALUES (?, ?, ?, ?, 0, NULL,"
|
||||
+ " DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01'),"
|
||||
+ " LAST_DAY(CURDATE()))"
|
||||
+ " ON DUPLICATE KEY UPDATE"
|
||||
+ " label = ?, abo_slots = ?, monthly_price = ?,"
|
||||
+ " cancelled = 0, cancellation_reason = NULL,"
|
||||
+ " next_billing_date = DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01'),"
|
||||
+ " period_end = LAST_DAY(CURDATE()), granted_at = NOW()";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName); ps.setString(2, label);
|
||||
ps.setInt(3, slots); ps.setInt(4, monthlyPrice);
|
||||
ps.setString(5, label); ps.setInt(6, slots);
|
||||
ps.setInt(7, monthlyPrice);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "savePlotAbo SQL Fehler", e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean cancelPlotAbo(String playerName) {
|
||||
String sql =
|
||||
"UPDATE wis_plot_abos SET cancelled = 1, cancellation_reason = 'user',"
|
||||
+ " period_end = LAST_DAY(CURDATE())"
|
||||
+ " WHERE player_name = ? AND period_end >= CURDATE() AND cancelled = 0";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
return ps.executeUpdate() == 1;
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "cancelPlotAbo SQL Fehler", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void cancelPlotAboPaymentFailed(String playerName) {
|
||||
String sql =
|
||||
"UPDATE wis_plot_abos SET cancelled = 1, cancellation_reason = 'payment_failed',"
|
||||
+ " period_end = LAST_DAY(CURDATE())"
|
||||
+ " WHERE player_name = ? AND cancelled = 0";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "cancelPlotAboPaymentFailed SQL Fehler", e);
|
||||
}
|
||||
}
|
||||
|
||||
void renewPlotAbo(String playerName) {
|
||||
String sql =
|
||||
"UPDATE wis_plot_abos"
|
||||
+ " SET next_billing_date = DATE_FORMAT(DATE_ADD(next_billing_date, INTERVAL 1 MONTH), '%Y-%m-01'),"
|
||||
+ " period_end = LAST_DAY(next_billing_date)"
|
||||
+ " WHERE player_name = ? AND cancelled = 0";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "renewPlotAbo SQL Fehler", e);
|
||||
}
|
||||
}
|
||||
|
||||
int getPlotAboSlots(String playerName) {
|
||||
String sql =
|
||||
"SELECT abo_slots FROM wis_plot_abos"
|
||||
+ " WHERE player_name = ? AND period_end >= CURDATE() AND cancelled = 0";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) return rs.getInt("abo_slots");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "getPlotAboSlots SQL Fehler", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PlotSlotManager.PlotAboEntry getActivePlotAbo(String playerName) {
|
||||
String sql =
|
||||
"SELECT label, abo_slots, monthly_price, cancelled, cancellation_reason,"
|
||||
+ " DATE_FORMAT(next_billing_date, '%d.%m.%Y') AS billing_fmt,"
|
||||
+ " DATE_FORMAT(period_end, '%d.%m.%Y') AS period_fmt"
|
||||
+ " FROM wis_plot_abos"
|
||||
+ " WHERE player_name = ? AND period_end >= CURDATE()";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next())
|
||||
return new PlotSlotManager.PlotAboEntry(
|
||||
playerName,
|
||||
rs.getString("label"),
|
||||
rs.getInt("abo_slots"),
|
||||
rs.getInt("monthly_price"),
|
||||
rs.getInt("cancelled") == 1,
|
||||
rs.getString("cancellation_reason"),
|
||||
rs.getString("billing_fmt"),
|
||||
rs.getString("period_fmt"));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "getActivePlotAbo SQL Fehler", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<PlotSlotManager.PlotAboEntry> getDuePlotBillings() {
|
||||
List<PlotSlotManager.PlotAboEntry> list = new ArrayList<>();
|
||||
String sql =
|
||||
"SELECT player_name, label, abo_slots, monthly_price,"
|
||||
+ " DATE_FORMAT(next_billing_date, '%d.%m.%Y') AS billing_fmt,"
|
||||
+ " DATE_FORMAT(period_end, '%d.%m.%Y') AS period_fmt"
|
||||
+ " FROM wis_plot_abos"
|
||||
+ " WHERE next_billing_date <= CURDATE() AND cancelled = 0";
|
||||
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next())
|
||||
list.add(new PlotSlotManager.PlotAboEntry(
|
||||
rs.getString("player_name"),
|
||||
rs.getString("label"),
|
||||
rs.getInt("abo_slots"),
|
||||
rs.getInt("monthly_price"),
|
||||
false, null,
|
||||
rs.getString("billing_fmt"),
|
||||
rs.getString("period_fmt")));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "getDuePlotBillings SQL Fehler", e);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// ── Fly-Code CRUD ────────────────────────────────────────────────
|
||||
|
||||
String generateCode(String playerName, int durationSec, String label) {
|
||||
@@ -3298,6 +3783,256 @@ public class IngameShopSpigot extends JavaPlugin implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// PLOT SLOT MANAGER
|
||||
// ===========================================================
|
||||
|
||||
private class PlotSlotManager {
|
||||
|
||||
private final IngameShopSpigot plugin;
|
||||
private final FlyCodeManager db;
|
||||
|
||||
PlotSlotManager(IngameShopSpigot plugin, FlyCodeManager db) {
|
||||
this.plugin = plugin;
|
||||
this.db = db;
|
||||
db.createPlotSlotTables();
|
||||
}
|
||||
|
||||
// ── Rang-Basis aus Config ──────────────────────────────────────
|
||||
|
||||
int getRankBase(Player player) {
|
||||
int highest = plotRankDefaults.getOrDefault("member", 2);
|
||||
for (Map.Entry<String, Integer> entry : plotRankDefaults.entrySet()) {
|
||||
if (player.hasPermission("group." + entry.getKey())) {
|
||||
if (entry.getValue() > highest) highest = entry.getValue();
|
||||
}
|
||||
}
|
||||
return highest;
|
||||
}
|
||||
|
||||
int getRankBaseByName(String playerName) {
|
||||
Player online = Bukkit.getPlayer(playerName);
|
||||
if (online != null) return getRankBase(online);
|
||||
return plotRankDefaults.getOrDefault("member", 2);
|
||||
}
|
||||
|
||||
// ── Gesamtlimit berechnen und LuckPerms setzen ─────────────────
|
||||
|
||||
void applyLimit(String playerName) {
|
||||
int extra = db.getExtraSlots(playerName);
|
||||
int abo = db.getPlotAboSlots(playerName);
|
||||
int base = getRankBaseByName(playerName);
|
||||
int total = base + extra + abo;
|
||||
int last = db.getLastPerm(playerName);
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
// Nur die tatsächlich gesetzte alte Permission entfernen
|
||||
if (last > 0 && last != total) {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
|
||||
"lp user " + playerName + " permission unset plots.plot." + last);
|
||||
}
|
||||
// Neue Permission setzen
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
|
||||
"lp user " + playerName + " permission set plots.plot." + total + " true");
|
||||
});
|
||||
// last_perm async speichern
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() { db.saveLastPerm(playerName, total); }
|
||||
}.runTaskAsynchronously(plugin);
|
||||
if (debug) plugin.getLogger().info("[PlotSlots] " + playerName
|
||||
+ " → Basis=" + base + " Extra=" + extra + " Abo=" + abo
|
||||
+ " Gesamt=" + total + " (vorher: " + last + ") → plots.plot." + total);
|
||||
}
|
||||
|
||||
// ── Einmalige Extra-Slots ─────────────────────────────────────
|
||||
|
||||
void grantExtraSlots(Player player, int slots, String label) {
|
||||
db.addExtraSlots(player.getName(), slots);
|
||||
applyLimit(player.getName());
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
int total = getRankBase(player)
|
||||
+ db.getExtraSlots(player.getName())
|
||||
+ db.getPlotAboSlots(player.getName());
|
||||
player.sendMessage("");
|
||||
player.sendMessage(ChatColor.GOLD + "📦 ════════════════════════════");
|
||||
player.sendMessage(ChatColor.YELLOW + " Plot-Slots erweitert!");
|
||||
player.sendMessage(ChatColor.GRAY + " Paket: " + ChatColor.WHITE + label);
|
||||
player.sendMessage(ChatColor.GRAY + " Neu: " + ChatColor.WHITE + "+" + slots + " permanente Slots");
|
||||
player.sendMessage(ChatColor.GRAY + " Gesamt: " + ChatColor.GREEN + total + " Plot-Slots");
|
||||
player.sendMessage(ChatColor.GOLD + " ════════════════════════════");
|
||||
player.sendMessage("");
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0F, 1.0F);
|
||||
});
|
||||
}
|
||||
|
||||
int getExtraSlots(String playerName) { return db.getExtraSlots(playerName); }
|
||||
|
||||
void grantExtraSlotsByName(String playerName, int slots, String label) {
|
||||
db.addExtraSlots(playerName, slots);
|
||||
applyLimit(playerName);
|
||||
}
|
||||
|
||||
// ── Monatliches Abo ───────────────────────────────────────────
|
||||
|
||||
void grantAbo(Player player, int slots, String label, int monthlyPrice) {
|
||||
db.savePlotAbo(player.getName(), slots, label, monthlyPrice);
|
||||
applyLimit(player.getName());
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
player.sendMessage("");
|
||||
player.sendMessage(ChatColor.GOLD + "📦 ════════════════════════════");
|
||||
player.sendMessage(ChatColor.YELLOW + " Plot-Abo aktiviert!");
|
||||
player.sendMessage(ChatColor.GRAY + " Paket: " + ChatColor.WHITE + label);
|
||||
player.sendMessage(ChatColor.GRAY + " Slots: " + ChatColor.WHITE + "+" + slots);
|
||||
player.sendMessage(ChatColor.GRAY + " Monatspreis: " + ChatColor.WHITE + monthlyPrice + " " + currency);
|
||||
player.sendMessage(ChatColor.GRAY + " Nächste Abbuchung: " + ChatColor.YELLOW + "1. des Folgemonats");
|
||||
player.sendMessage(ChatColor.GRAY + " Status: /plotabo");
|
||||
player.sendMessage(ChatColor.GOLD + " ════════════════════════════");
|
||||
player.sendMessage("");
|
||||
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0F, 1.2F);
|
||||
});
|
||||
}
|
||||
|
||||
void grantAboByName(String playerName, int slots, String label, int monthlyPrice) {
|
||||
db.savePlotAbo(playerName, slots, label, monthlyPrice);
|
||||
applyLimit(playerName);
|
||||
}
|
||||
|
||||
boolean cancelAbo(String playerName) {
|
||||
boolean ok = db.cancelPlotAbo(playerName);
|
||||
if (ok) applyLimit(playerName);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int getAboSlots(String playerName) { return db.getPlotAboSlots(playerName); }
|
||||
|
||||
PlotAboEntry getActiveAbo(String playerName) { return db.getActivePlotAbo(playerName); }
|
||||
|
||||
// ── Einfrieren überzähliger Plots ─────────────────────────────
|
||||
|
||||
void freezeExcessPlots(String playerName, int newLimit) {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
if (Bukkit.getPluginManager().getPlugin("PlotSquared") == null) return;
|
||||
Player online = Bukkit.getPlayer(playerName);
|
||||
if (online != null) {
|
||||
online.sendMessage("");
|
||||
online.sendMessage(ChatColor.RED + "📦 ════════════════════════════");
|
||||
online.sendMessage(ChatColor.RED + " Plot-Abo abgelaufen!");
|
||||
online.sendMessage(ChatColor.GRAY + " Limit reduziert auf: "
|
||||
+ ChatColor.WHITE + newLimit);
|
||||
online.sendMessage(ChatColor.YELLOW + " Überzählige Plots sind eingefroren.");
|
||||
online.sendMessage(ChatColor.GRAY + " Abo erneuern: " + ChatColor.AQUA + "viper-network.de");
|
||||
online.sendMessage(ChatColor.RED + " ════════════════════════════");
|
||||
online.sendMessage("");
|
||||
online.playSound(online.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1.0F, 0.5F);
|
||||
}
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
|
||||
"lp user " + playerName + " meta set frozen_excess_plots true");
|
||||
});
|
||||
}
|
||||
|
||||
void unfreezeExcessPlots(String playerName) {
|
||||
Bukkit.getScheduler().runTask(plugin, () ->
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
|
||||
"lp user " + playerName + " meta unset frozen_excess_plots"));
|
||||
}
|
||||
|
||||
// ── Monatlicher Billing-Check ─────────────────────────────────
|
||||
|
||||
void startBillingChecker() {
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
if (java.time.LocalDate.now().getDayOfMonth() != 1) return;
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
List<PlotAboEntry> due = db.getDuePlotBillings();
|
||||
if (due.isEmpty()) return;
|
||||
plugin.getLogger().info("[PlotSlots] Billing: " + due.size() + " Abo(s).");
|
||||
for (PlotAboEntry entry : due) {
|
||||
final String pName = entry.playerName;
|
||||
final int price = entry.monthlyPrice;
|
||||
final int slots = entry.aboSlots;
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
@SuppressWarnings("deprecation")
|
||||
org.bukkit.OfflinePlayer op = Bukkit.getOfflinePlayer(pName);
|
||||
if (op == null || !op.hasPlayedBefore()) return;
|
||||
if ((price == 0) || econ.getBalance(op) >= price) {
|
||||
if (price > 0) {
|
||||
econ.withdrawPlayer(op, price);
|
||||
if (!incomeReceiver.isEmpty()) {
|
||||
@SuppressWarnings("deprecation")
|
||||
org.bukkit.OfflinePlayer recv = Bukkit.getOfflinePlayer(incomeReceiver);
|
||||
if (recv != null && recv.hasPlayedBefore())
|
||||
econ.depositPlayer(recv, price);
|
||||
}
|
||||
}
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
db.renewPlotAbo(pName);
|
||||
}
|
||||
}.runTaskAsynchronously(plugin);
|
||||
unfreezeExcessPlots(pName);
|
||||
applyLimit(pName);
|
||||
Player online = Bukkit.getPlayer(pName);
|
||||
if (online != null) {
|
||||
online.sendMessage(ChatColor.GOLD + "📦 Plot-Abo verlängert! +"
|
||||
+ slots + " Slots | " + price + " " + currency + " abgebucht.");
|
||||
online.playSound(online.getLocation(),
|
||||
Sound.ENTITY_PLAYER_LEVELUP, 1.0F, 1.0F);
|
||||
}
|
||||
} else {
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
db.cancelPlotAboPaymentFailed(pName);
|
||||
}
|
||||
}.runTaskAsynchronously(plugin);
|
||||
new BukkitRunnable() {
|
||||
@Override public void run() {
|
||||
int newLimit = getRankBaseByName(pName) + db.getExtraSlots(pName);
|
||||
freezeExcessPlots(pName, newLimit);
|
||||
// applyLimit kümmert sich um die Permission
|
||||
applyLimit(pName);
|
||||
}
|
||||
}.runTaskAsynchronously(plugin);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}.runTaskAsynchronously(plugin);
|
||||
}
|
||||
}.runTaskTimer(plugin, 20L * 60 * 5, 20L * 60 * 60 * 24);
|
||||
}
|
||||
|
||||
// ── PlayerJoin ────────────────────────────────────────────────
|
||||
|
||||
void onPlayerJoin(Player player) {
|
||||
applyLimit(player.getName());
|
||||
if (player.hasPermission("meta.frozen_excess_plots.true")) {
|
||||
player.sendMessage(ChatColor.RED + "📦 Einige deiner Plots sind eingefroren!");
|
||||
player.sendMessage(ChatColor.GRAY + " Grund: Plot-Abo abgelaufen.");
|
||||
player.sendMessage(ChatColor.WHITE + " Erneuern: " + ChatColor.AQUA + "viper-network.de");
|
||||
}
|
||||
}
|
||||
|
||||
// ── Data class ────────────────────────────────────────────────
|
||||
|
||||
static class PlotAboEntry {
|
||||
final String playerName, label, cancellationReason, nextBillingDate, periodEnd;
|
||||
final int aboSlots, monthlyPrice;
|
||||
final boolean cancelled;
|
||||
PlotAboEntry(String playerName, String label, int aboSlots, int monthlyPrice,
|
||||
boolean cancelled, String cancellationReason,
|
||||
String nextBillingDate, String periodEnd) {
|
||||
this.playerName = playerName;
|
||||
this.label = label;
|
||||
this.aboSlots = aboSlots;
|
||||
this.monthlyPrice = monthlyPrice;
|
||||
this.cancelled = cancelled;
|
||||
this.cancellationReason = cancellationReason;
|
||||
this.nextBillingDate = nextBillingDate;
|
||||
this.periodEnd = periodEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
// SELL MANAGER
|
||||
// ===========================================================
|
||||
|
||||
@@ -29,7 +29,7 @@ fly-redeem-disabled: false
|
||||
# Leer lassen ("") wenn niemand die Einnahmen erhalten soll
|
||||
income-receiver: ""
|
||||
|
||||
# MySQL-Verbindung (für Fly-Code-System und Rang-Sessions)
|
||||
# MySQL-Verbindung (für Fly-Code-System, Rang-Sessions, Fly-Abo und Plot-Slots)
|
||||
mysql:
|
||||
host: "localhost"
|
||||
port: "3306"
|
||||
@@ -43,20 +43,32 @@ mysql:
|
||||
sell:
|
||||
# Ankauf auf diesem Server aktivieren
|
||||
enabled: true
|
||||
|
||||
# Preiskorrektur relativ zum WP-Ankaufspreis (in Prozent)
|
||||
# Beispiele:
|
||||
# 0.0 → exakt den WP-Ankaufspreis zahlen
|
||||
# -10.0 → 10 % weniger als der WP-Ankaufspreis
|
||||
# +5.0 → 5 % mehr als der WP-Ankaufspreis
|
||||
# Hinweis: Den Basis-Ankaufspreis konfigurierst du im WP-Admin
|
||||
# unter Items → <Item bearbeiten> → "Ankauf aktivieren"
|
||||
price-offset: -10.0
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────
|
||||
# Fly-Abo Einstellungen
|
||||
# ──────────────────────────────────────────────
|
||||
fly-abo:
|
||||
# Maximale Fly-Zeit pro Tag in Stunden
|
||||
# Standard: 6 (= 6 Stunden = 21.600 Sekunden)
|
||||
max-daily-hours: 6
|
||||
# Maximale Fly-Zeit pro Tag in Stunden (Standard: 6)
|
||||
max-daily-hours: 6
|
||||
|
||||
# ──────────────────────────────────────────────
|
||||
# Plot-Slot Einstellungen (nur Citybuild)
|
||||
# ──────────────────────────────────────────────
|
||||
plot-slots:
|
||||
# Auf welchem Server greift das Plot-Slot-System?
|
||||
# Muss mit server-name des Citybuild-Servers übereinstimmen
|
||||
server: "citybuild"
|
||||
# Standard-Plot-Slots pro LuckPerms-Gruppe
|
||||
# LuckPerms Meta "plotlimit" wird automatisch gesetzt und von
|
||||
# PlotSquared über die Option "max-plots-per-player: -1" + Meta gelesen
|
||||
rank-defaults:
|
||||
member: 2
|
||||
vip: 3
|
||||
scout: 4
|
||||
primo: 5
|
||||
@@ -1,5 +1,5 @@
|
||||
name: IngameShopSpigot
|
||||
version: 1.1
|
||||
version: 1.2
|
||||
main: de.mviper.spigot.IngameShopSpigot
|
||||
api-version: 1.19
|
||||
depend: [Vault]
|
||||
@@ -20,11 +20,11 @@ commands:
|
||||
usage: /flyredeem <Code>
|
||||
permission: ingameshop.flyredeem
|
||||
flycodes:
|
||||
description: Öffnet ein GUI mit deinen ungenutzten Fly-Gutscheinen (einlösen oder weitergeben)
|
||||
description: Öffnet ein GUI mit deinen ungenutzten Fly-Gutscheinen
|
||||
usage: /flycodes
|
||||
permission: ingameshop.flycodes
|
||||
flygive:
|
||||
description: Gibt einem Spieler einen Fly-Gutschein-Code
|
||||
description: Gibt einem Spieler einen Fly-Gutschein-Code (Admin)
|
||||
usage: /flygive <Spieler> <Sekunden> [Label]
|
||||
permission: ingameshop.flygive
|
||||
flypause:
|
||||
@@ -32,7 +32,7 @@ commands:
|
||||
usage: /flypause
|
||||
permission: ingameshop.flypause
|
||||
rankinfo:
|
||||
description: Zeigt deine aktiven (zeitbasierten) Ränge an
|
||||
description: Zeigt deine aktiven zeitbasierten Ränge an
|
||||
usage: /rankinfo
|
||||
permission: ingameshop.rankinfo
|
||||
sell:
|
||||
@@ -44,17 +44,37 @@ commands:
|
||||
usage: /wpis <reload>
|
||||
permission: ingameshop.reload
|
||||
flyabo:
|
||||
description: Zeigt deinen Fly-Abo Status und Tageslimit an
|
||||
description: Zeigt deinen Fly-Abo Status und heutiges Tageslimit
|
||||
usage: /flyabo
|
||||
permission: ingameshop.flyabo
|
||||
flyabocancel:
|
||||
description: Kündigt dein Fly-Abo zum Ablaufdatum
|
||||
description: Kündigt dein Fly-Abo zum Monatsende
|
||||
usage: /flyabocancel [confirm]
|
||||
permission: ingameshop.flyabocancel
|
||||
flyabogive:
|
||||
description: Gibt einem Spieler ein Fly-Abo (Admin)
|
||||
usage: /flyabogive <Spieler> <Tage> [Label]
|
||||
description: Gibt einem Spieler ein Fly-Abo manuell (Admin)
|
||||
usage: /flyabogive <Spieler> <Monatspreis> [Label]
|
||||
permission: ingameshop.flyabogive
|
||||
plotslots:
|
||||
description: Zeigt deine aktuellen Plot-Slots (Basis + Extra + Abo)
|
||||
usage: /plotslots
|
||||
permission: ingameshop.plotslots
|
||||
plotabo:
|
||||
description: Zeigt deinen Plot-Abo Status
|
||||
usage: /plotabo
|
||||
permission: ingameshop.plotabo
|
||||
plotabocancel:
|
||||
description: Kündigt dein Plot-Abo zum Monatsende
|
||||
usage: /plotabocancel [confirm]
|
||||
permission: ingameshop.plotabocancel
|
||||
plotabogive:
|
||||
description: Gibt einem Spieler ein Plot-Abo manuell (Admin)
|
||||
usage: /plotabogive <Spieler> <Slots> <Monatspreis> [Label]
|
||||
permission: ingameshop.plotabogive
|
||||
plotslotsgive:
|
||||
description: Gibt einem Spieler permanente Plot-Slots (Admin)
|
||||
usage: /plotslotsgive <Spieler> <Slots> [Label]
|
||||
permission: ingameshop.plotslotsgive
|
||||
|
||||
permissions:
|
||||
ingameshop.orders:
|
||||
@@ -70,7 +90,7 @@ permissions:
|
||||
description: Kann eigene ungenutzte Fly-Codes auflisten
|
||||
default: true
|
||||
ingameshop.flygive:
|
||||
description: Kann Spielern Fly-Gutscheine geben (Admin/OP/Mod)
|
||||
description: Kann Spielern Fly-Gutscheine geben (Admin)
|
||||
default: op
|
||||
ingameshop.flypause:
|
||||
description: Kann die eigene Fly-Zeit pausieren
|
||||
@@ -92,4 +112,19 @@ permissions:
|
||||
default: true
|
||||
ingameshop.flyabogive:
|
||||
description: Kann Spielern Fly-Abos manuell vergeben (Admin)
|
||||
default: op
|
||||
ingameshop.plotslots:
|
||||
description: Kann eigene Plot-Slot Übersicht einsehen
|
||||
default: true
|
||||
ingameshop.plotabo:
|
||||
description: Kann eigenen Plot-Abo-Status einsehen
|
||||
default: true
|
||||
ingameshop.plotabocancel:
|
||||
description: Kann eigenes Plot-Abo kündigen
|
||||
default: true
|
||||
ingameshop.plotabogive:
|
||||
description: Kann Spielern Plot-Abos manuell vergeben (Admin)
|
||||
default: op
|
||||
ingameshop.plotslotsgive:
|
||||
description: Kann Spielern permanente Plot-Slots vergeben (Admin)
|
||||
default: op
|
||||
Reference in New Issue
Block a user