Compare commits
1 Commits
1.0.9
...
77ae1d6ed9
Author | SHA1 | Date | |
---|---|---|---|
77ae1d6ed9 |
3
pom.xml
3
pom.xml
@@ -6,8 +6,7 @@
|
||||
|
||||
<groupId>de.viper</groupId>
|
||||
<artifactId>SurvivalPlus</artifactId>
|
||||
<version>1.0.9-Beta</version>
|
||||
|
||||
<version>1.0.8-Beta</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>SurvivalPlus</name>
|
||||
|
@@ -58,19 +58,13 @@ public class TablistManager implements Listener {
|
||||
|
||||
// Resource sicherstellen, Config laden
|
||||
try {
|
||||
File tablistFile = new File(plugin.getDataFolder(), "tablist.yml");
|
||||
if (!tablistFile.exists()) {
|
||||
plugin.saveResource("tablist.yml", false);
|
||||
}
|
||||
plugin.saveResource("tablist.yml", false);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
try {
|
||||
plugin.reloadTablistConfig();
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
FileConfiguration config = plugin.getTablistConfig();
|
||||
|
||||
|
||||
// Nicknames.yml laden
|
||||
try {
|
||||
File nicknameFile = new File(plugin.getDataFolder(), "nicknames.yml");
|
||||
|
@@ -66,13 +66,6 @@ import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import de.viper.survivalplus.util.BannerManager;
|
||||
import java.io.FileWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
|
||||
public class SurvivalPlus extends JavaPlugin {
|
||||
|
||||
@@ -123,11 +116,6 @@ public class SurvivalPlus extends JavaPlugin {
|
||||
private Map<UUID, Integer> playerClaimCounts = new HashMap<>();
|
||||
private Map<UUID, Location> point1Selections = new HashMap<>();
|
||||
private Map<UUID, Location> point2Selections = new HashMap<>();
|
||||
private BannerManager bannerManager;
|
||||
private File debugFile;
|
||||
private PrintWriter debugWriter;
|
||||
private File consoleFile;
|
||||
private PrintWriter consoleWriter;
|
||||
|
||||
public void reloadTablistConfig() {
|
||||
if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
|
||||
@@ -180,41 +168,6 @@ public class SurvivalPlus extends JavaPlugin {
|
||||
@Override
|
||||
public void onEnable() {
|
||||
saveDefaultConfig();
|
||||
|
||||
// Version aus plugin.yml
|
||||
String pluginVersion = getDescription().getVersion();
|
||||
|
||||
// Sicherstellen, dass 'version:' ganz oben steht
|
||||
ensureConfigVersion(getConfig(), new File(getDataFolder(), "config.yml"), pluginVersion);
|
||||
ensureVersionAtTop(new File(getDataFolder(), "lang.yml"), pluginVersion);
|
||||
ensureVersionAtTop(new File(getDataFolder(), "help.yml"), pluginVersion);
|
||||
ensureVersionAtTop(new File(getDataFolder(), "tablist.yml"), pluginVersion);
|
||||
|
||||
// Debug-Logging initialisieren
|
||||
if (getConfig().getBoolean("debug-logging", false)) {
|
||||
try {
|
||||
// Ordner erstellen
|
||||
File debugFolder = new File(getDataFolder(), "Debug");
|
||||
if (!debugFolder.exists()) {
|
||||
debugFolder.mkdirs();
|
||||
}
|
||||
|
||||
// debug.log für Fehler
|
||||
debugFile = new File(debugFolder, "debug.log");
|
||||
if (!debugFile.exists()) debugFile.createNewFile();
|
||||
debugWriter = new PrintWriter(new FileWriter(debugFile, true), true);
|
||||
|
||||
// console.log für komplette Plugin-Infos
|
||||
consoleFile = new File(debugFolder, "console.log");
|
||||
if (!consoleFile.exists()) consoleFile.createNewFile();
|
||||
consoleWriter = new PrintWriter(new FileWriter(consoleFile, true), true);
|
||||
|
||||
logConsole("Debug-Logging ist aktiviert. Alle Plugin-Logs werden in Debug/console.log gespeichert.");
|
||||
} catch (IOException e) {
|
||||
getLogger().warning("Konnte Debug-Dateien nicht erstellen: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
int pluginId = 26886;
|
||||
Metrics metrics = new Metrics(this, pluginId);
|
||||
metrics.addCustomChart(new SimplePie(
|
||||
@@ -229,10 +182,6 @@ public class SurvivalPlus extends JavaPlugin {
|
||||
"plugin_language",
|
||||
() -> getConfig().getString("language", "default")
|
||||
));
|
||||
|
||||
bannerManager = new BannerManager(this);
|
||||
bannerManager.displayConsoleBanner(); // Banner beim Serverstart
|
||||
|
||||
updateConfigFiles();
|
||||
createHomesFile();
|
||||
createGravesFile();
|
||||
@@ -434,77 +383,6 @@ public class SurvivalPlus extends JavaPlugin {
|
||||
getLogger().info("Block-Regeln angewendet: CommandBlocks erlaubt=" + cmdAllowed + ", StructureBlocks erlaubt=" + structAllowed);
|
||||
}
|
||||
|
||||
private void ensureVersionAtTop(File file, String version) {
|
||||
try {
|
||||
if (!file.exists()) return; // Datei existiert nicht
|
||||
List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
|
||||
|
||||
if (!lines.isEmpty() && lines.get(0).startsWith("version:")) {
|
||||
// Alte Versionsnummer ersetzen
|
||||
lines.set(0, "version: " + version);
|
||||
} else {
|
||||
// Version an den Anfang setzen
|
||||
lines.add(0, "version: " + version);
|
||||
}
|
||||
|
||||
Files.write(file.toPath(), lines, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
getLogger().warning("Konnte Version in " + file.getName() + " nicht setzen: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Speziell für config.yml:
|
||||
* - Setzt die Version in der geladenen FileConfiguration (getConfig()) und speichert sie,
|
||||
* - und sorgt anschließend dafür, dass die 'version:'-Zeile ganz oben in der Datei steht.
|
||||
*/
|
||||
private void ensureConfigVersion(FileConfiguration config, File file, String version) {
|
||||
try {
|
||||
if (!file.exists()) return; // nichts zu tun, Datei existiert nicht
|
||||
|
||||
// 1) Version in der geladenen Config setzen und speichern (Bukkit nutzt diese Config im Speicher)
|
||||
String current = config.getString("version", "");
|
||||
if (!version.equals(current)) {
|
||||
config.set("version", version);
|
||||
try {
|
||||
config.save(file);
|
||||
} catch (IOException e) {
|
||||
getLogger().warning("Konnte config.yml nicht speichern: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Text-Nachbearbeitung: sicherstellen, dass 'version:' als erste Zeile steht
|
||||
List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
|
||||
|
||||
// Entferne alle vorhandenen version:-Zeilen (falls irgendwo)
|
||||
int foundIndex = -1;
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
if (lines.get(i).trim().startsWith("version:")) {
|
||||
foundIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundIndex == 0) {
|
||||
// bereits oben -> ersetzen
|
||||
lines.set(0, "version: " + version);
|
||||
} else {
|
||||
// entferne alte Stelle (wenn vorhanden)
|
||||
if (foundIndex > 0) {
|
||||
lines.remove(foundIndex);
|
||||
}
|
||||
// füge neue version ganz oben ein
|
||||
lines.add(0, "version: " + version);
|
||||
}
|
||||
|
||||
Files.write(file.toPath(), lines, StandardCharsets.UTF_8);
|
||||
getLogger().info("config.yml: Version oben gesetzt auf " + version);
|
||||
} catch (IOException e) {
|
||||
getLogger().warning("Konnte Version in config.yml nicht setzen: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void removeForbiddenBlocksFromInventories(boolean cmdAllowed, boolean structAllowed) {
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
if (p.hasPermission("survivalplus.notify")) {
|
||||
@@ -680,6 +558,19 @@ private void ensureConfigVersion(FileConfiguration config, File file, String ver
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Methoden für nicknames.yml
|
||||
public void createNicknamesFile() {
|
||||
nicknamesFile = new File(getDataFolder(), "nicknames.yml");
|
||||
@@ -727,9 +618,6 @@ private void ensureConfigVersion(FileConfiguration config, File file, String ver
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (debugWriter != null) {
|
||||
debugWriter.close();
|
||||
}
|
||||
if (autoClearTaskId != -1) {
|
||||
Bukkit.getScheduler().cancelTask(autoClearTaskId);
|
||||
}
|
||||
@@ -1178,34 +1066,4 @@ private void ensureConfigVersion(FileConfiguration config, File file, String ver
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public BannerManager getBannerManager() {
|
||||
return bannerManager;
|
||||
}
|
||||
|
||||
// Nur Fehler/Exceptions
|
||||
public void log(String msg) {
|
||||
if (getConfig().getBoolean("debug-logging", false) && debugWriter != null) {
|
||||
debugWriter.println("[" + new java.util.Date() + "] " + msg);
|
||||
} else {
|
||||
getLogger().info(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void logError(String msg, Throwable t) {
|
||||
if (getConfig().getBoolean("debug-logging", false) && debugWriter != null) {
|
||||
debugWriter.println("[" + new java.util.Date() + "] ERROR: " + msg);
|
||||
t.printStackTrace(debugWriter);
|
||||
} else {
|
||||
getLogger().log(Level.SEVERE, msg, t);
|
||||
}
|
||||
}
|
||||
|
||||
// Komplette Plugin-Logs in console.log
|
||||
public void logConsole(String msg) {
|
||||
if (getConfig().getBoolean("debug-logging", false) && consoleWriter != null) {
|
||||
consoleWriter.println("[" + new java.util.Date() + "] " + msg);
|
||||
}
|
||||
getLogger().info(msg); // Optional: zusätzlich Konsole ausgeben
|
||||
}
|
||||
|
||||
}
|
@@ -2,20 +2,13 @@ package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import de.viper.survivalplus.util.Claim;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ClaimListener implements Listener {
|
||||
private final SurvivalPlus plugin;
|
||||
private final Map<UUID, Claim> lastClaim = new HashMap<>();
|
||||
private SurvivalPlus plugin;
|
||||
|
||||
public ClaimListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -23,51 +16,19 @@ public class ClaimListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (player.isOp()) return;
|
||||
Claim claim = plugin.getClaim(event.getBlock().getLocation());
|
||||
if (claim != null && !claim.getOwner().equals(player.getUniqueId()) && !claim.getTrusted().contains(player.getUniqueId())) {
|
||||
if (claim != null && !claim.canInteract(event.getPlayer().getUniqueId()) && !event.getPlayer().isOp()) {
|
||||
event.setCancelled(true);
|
||||
player.sendMessage(plugin.getMessage("claim.no-break"));
|
||||
event.getPlayer().sendMessage(plugin.getMessage("claim.no-break"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (player.isOp()) return;
|
||||
Claim claim = plugin.getClaim(event.getBlock().getLocation());
|
||||
if (claim != null && !claim.getOwner().equals(player.getUniqueId()) && !claim.getTrusted().contains(player.getUniqueId())) {
|
||||
if (claim != null && !claim.canInteract(event.getPlayer().getUniqueId()) && !event.getPlayer().isOp()) {
|
||||
event.setCancelled(true);
|
||||
player.sendMessage(plugin.getMessage("claim.no-place"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
UUID playerId = player.getUniqueId();
|
||||
Claim currentClaim = plugin.getClaim(event.getTo());
|
||||
|
||||
// Prüfe, ob sich der Claim-Status geändert hat
|
||||
Claim previousClaim = lastClaim.getOrDefault(playerId, null);
|
||||
if (currentClaim != previousClaim) {
|
||||
if (currentClaim != null) {
|
||||
// Spieler betritt einen Claim
|
||||
String ownerName = plugin.getServer().getOfflinePlayer(currentClaim.getOwner()).getName();
|
||||
if (ownerName == null) {
|
||||
ownerName = currentClaim.getOwner().toString(); // Fallback auf UUID
|
||||
}
|
||||
player.sendMessage(plugin.getMessage("claim.enter").replace("%owner%", ownerName));
|
||||
} else if (previousClaim != null) {
|
||||
// Spieler verlässt einen Claim
|
||||
String ownerName = plugin.getServer().getOfflinePlayer(previousClaim.getOwner()).getName();
|
||||
if (ownerName == null) {
|
||||
ownerName = previousClaim.getOwner().toString(); // Fallback auf UUID
|
||||
}
|
||||
player.sendMessage(plugin.getMessage("claim.leave").replace("%owner%", ownerName));
|
||||
}
|
||||
lastClaim.put(playerId, currentClaim);
|
||||
event.getPlayer().sendMessage(plugin.getMessage("claim.no-place"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -26,12 +26,10 @@ public class NewbieProtectionListener implements Listener {
|
||||
private final SurvivalPlus plugin;
|
||||
private final boolean enabled;
|
||||
private final int durationMinutes;
|
||||
private final int COOLDOWN_SECONDS = 60; // Abklingzeit für Nachrichten in Sekunden (1 Minute)
|
||||
|
||||
// Maps für Zeiten, BossBars und Nachrichten-Abklingzeit
|
||||
// Maps für Zeiten und BossBars
|
||||
private final Map<UUID, Integer> remainingSeconds = new HashMap<>();
|
||||
private final Map<UUID, BossBar> bossBars = new HashMap<>();
|
||||
private final Map<UUID, Long> messageCooldowns = new HashMap<>();
|
||||
|
||||
// YAML Datei
|
||||
private File dataFile;
|
||||
@@ -91,29 +89,14 @@ public class NewbieProtectionListener implements Listener {
|
||||
if (!(event.getEntity() instanceof Player)) return;
|
||||
|
||||
Player victim = (Player) event.getEntity();
|
||||
UUID victimId = victim.getUniqueId();
|
||||
Integer timeLeft = remainingSeconds.get(victimId);
|
||||
UUID vid = victim.getUniqueId();
|
||||
Integer timeLeft = remainingSeconds.get(vid);
|
||||
|
||||
if (timeLeft != null && timeLeft > 0) {
|
||||
event.setCancelled(true);
|
||||
|
||||
// Prüfe Abklingzeit für Opfer
|
||||
long currentTime = System.currentTimeMillis() / 1000;
|
||||
long lastMessageTimeVictim = messageCooldowns.getOrDefault(victimId, 0L);
|
||||
if (currentTime >= lastMessageTimeVictim + COOLDOWN_SECONDS) {
|
||||
victim.sendMessage(ChatColor.GREEN + "Du bist noch im Neulingsschutz!");
|
||||
messageCooldowns.put(victimId, currentTime);
|
||||
}
|
||||
|
||||
// Prüfe Abklingzeit für Angreifer, falls es ein Spieler ist
|
||||
victim.sendMessage(ChatColor.GREEN + "Du bist noch im Neulingsschutz!");
|
||||
if (event.getDamager() instanceof Player) {
|
||||
Player damager = (Player) event.getDamager();
|
||||
UUID damagerId = damager.getUniqueId();
|
||||
long lastMessageTimeDamager = messageCooldowns.getOrDefault(damagerId, 0L);
|
||||
if (currentTime >= lastMessageTimeDamager + COOLDOWN_SECONDS) {
|
||||
damager.sendMessage(ChatColor.RED + victim.getName() + " ist noch geschützt!");
|
||||
messageCooldowns.put(damagerId, currentTime);
|
||||
}
|
||||
((Player) event.getDamager()).sendMessage(ChatColor.RED + victim.getName() + " ist noch geschützt!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,6 +158,7 @@ public class NewbieProtectionListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
// WICHTIG: Public gemacht, damit von SurvivalPlus.java aufrufbar
|
||||
public void saveData() {
|
||||
if (dataConfig == null) return;
|
||||
for (Map.Entry<UUID, Integer> entry : remainingSeconds.entrySet()) {
|
||||
@@ -192,4 +176,4 @@ public class NewbieProtectionListener implements Listener {
|
||||
int sec = totalSec % 60;
|
||||
return String.format("%02d:%02d", min, sec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,28 +0,0 @@
|
||||
package de.viper.survivalplus.util;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class BannerManager {
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public BannerManager(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void displayConsoleBanner() {
|
||||
String version = plugin.getDescription().getVersion();
|
||||
List<String> banner = Arrays.asList(
|
||||
"******************************",
|
||||
"* SurvivalPlus " + version + " *",
|
||||
"* *",
|
||||
"* M_Viper *",
|
||||
"******************************"
|
||||
);
|
||||
for (String line : banner) {
|
||||
plugin.getLogger().info(line);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,9 +1,3 @@
|
||||
# Version (Nicht Ändern!)
|
||||
version: 1.0.9
|
||||
|
||||
# Debug-Option
|
||||
debug-logging: false
|
||||
|
||||
# Neulings Schutz
|
||||
newbie-protection:
|
||||
enabled: true
|
||||
|
@@ -403,30 +403,24 @@ inventory:
|
||||
player-only: "§cDieser Befehl ist nur für Spieler!"
|
||||
|
||||
claim:
|
||||
points-not-set: "&cDu musst zuerst zwei Punkte markieren! Verwende /claim mark <1|2>."
|
||||
different-worlds: "&cDie markierten Punkte müssen in derselben Welt liegen!"
|
||||
too-large: "&cDer Bereich ist zu groß! Maximal erlaubt: %max% Blöcke²."
|
||||
overlap: "&cDieser Bereich überschneidet sich mit einem bestehenden Claim!"
|
||||
max-reached: "&cDu hast das Maximum von %max% Claims erreicht!"
|
||||
success: "&aBereich beansprucht! (%count%/%max%)"
|
||||
unclaimed: "&aBereich freigegeben!"
|
||||
not-owner: "&cDies ist nicht dein Claim!"
|
||||
point1-set: "&aPunkt 1 gesetzt bei x=%x%, z=%z%."
|
||||
point2-set: "&aPunkt 2 gesetzt bei x=%x%, z=%z%."
|
||||
trusted: "&a%player% ist jetzt in diesem Claim vertraut!"
|
||||
untrusted: "&a%player% ist in diesem Claim nicht mehr vertraut!"
|
||||
no-break: "&cDu kannst in diesem beanspruchten Bereich keine Blöcke abbauen!"
|
||||
no-place: "&cDu kannst in diesem beanspruchten Bereich keine Blöcke platzieren!"
|
||||
op-unclaimed: "&a%count% Claims von %player% wurden entfernt!"
|
||||
no-claims-found: "&cKeine Claims für %player% gefunden!"
|
||||
no-claim-at-location: "&cKein Claim an dieser Position!"
|
||||
info:
|
||||
- "&eClaim-Info:"
|
||||
- "&7Besitzer: &e%owner%"
|
||||
- "&7Welt: &e%world%"
|
||||
- "&7Koordinaten: &eX1: %x1%, Z1: %z1% bis X2: %x2%, Z2: %z2%"
|
||||
enter: "&aDu hast das Gebiet von %owner% betreten."
|
||||
leave: "&eDu hast das Gebiet von %owner% verlassen."
|
||||
points-not-set: "&cDu musst zuerst zwei Punkte markieren! Verwende /claim mark <1|2>."
|
||||
different-worlds: "&cDie markierten Punkte müssen in derselben Welt liegen!"
|
||||
too-large: "&cDer Bereich ist zu groß! Maximal erlaubt: %max% Blöcke²."
|
||||
overlap: "&cDieser Bereich überschneidet sich mit einem bestehenden Claim!"
|
||||
max-reached: "&cDu hast das Maximum von %max% Claims erreicht!"
|
||||
success: "&aBereich beansprucht! (%count%/%max%)"
|
||||
unclaimed: "&aBereich freigegeben!"
|
||||
not-owner: "&cDies ist nicht dein Claim!"
|
||||
point1-set: "&aPunkt 1 gesetzt bei x=%x%, z=%z%."
|
||||
point2-set: "&aPunkt 2 gesetzt bei x=%x%, z=%z%."
|
||||
trusted: "&a%player% ist jetzt in diesem Claim vertraut!"
|
||||
untrusted: "&a%player% ist in diesem Claim nicht mehr vertraut!"
|
||||
no-break: "&cDu kannst in diesem beanspruchten Bereich keine Blöcke abbauen!"
|
||||
no-place: "&cDu kannst in diesem beanspruchten Bereich keine Blöcke platzieren!"
|
||||
op-unclaimed: "&a%count% Claims von %player% wurden entfernt!"
|
||||
no-claims-found: "&cKeine Claims für %player% gefunden!"
|
||||
no-claim-at-location: "&cKein Claim an dieser Position!"
|
||||
info: "&eClaim-Info:\n&7Besitzer: &e%owner%\n&7Welt: &e%world%\n&7Koordinaten: &eX1: %x1%, Z1: %z1% bis X2: %x2%, Z2: %z2%"
|
||||
|
||||
force-survival:
|
||||
join-message: "§aDu wurdest in den Survivalmodus gesetzt!"
|
@@ -1,6 +1,5 @@
|
||||
name: SurvivalPlus
|
||||
version: 1.0.9
|
||||
|
||||
version: 1.0.8
|
||||
|
||||
main: de.viper.survivalplus.SurvivalPlus
|
||||
api-version: 1.21
|
||||
|
Reference in New Issue
Block a user