diff --git a/pom.xml b/pom.xml
index 2efd14e..14882fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
de.viper
SurvivalPlus
- 1.0.7-Beta
+ 1.0.9-Beta
jar
@@ -113,6 +113,7 @@
warps.yml
tablist.yml
blockedcommands.yml
+ claims.yml
diff --git a/src/main/java/de/viper/survivalplus/Manager/TablistManager.java b/src/main/java/de/viper/survivalplus/Manager/TablistManager.java
index b20e371..2f73eda 100644
--- a/src/main/java/de/viper/survivalplus/Manager/TablistManager.java
+++ b/src/main/java/de/viper/survivalplus/Manager/TablistManager.java
@@ -58,13 +58,19 @@ public class TablistManager implements Listener {
// Resource sicherstellen, Config laden
try {
- plugin.saveResource("tablist.yml", false);
+ File tablistFile = new File(plugin.getDataFolder(), "tablist.yml");
+ if (!tablistFile.exists()) {
+ 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");
diff --git a/src/main/java/de/viper/survivalplus/SurvivalPlus.java b/src/main/java/de/viper/survivalplus/SurvivalPlus.java
index da2850b..c900b8b 100644
--- a/src/main/java/de/viper/survivalplus/SurvivalPlus.java
+++ b/src/main/java/de/viper/survivalplus/SurvivalPlus.java
@@ -11,6 +11,7 @@ import de.viper.survivalplus.recipe.BackpackRecipe;
import de.viper.survivalplus.Manager.StatsManager;
import de.viper.survivalplus.Manager.BlockManager;
import de.viper.survivalplus.util.LockSystem;
+import de.viper.survivalplus.util.Claim;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
@@ -38,24 +39,19 @@ import de.viper.survivalplus.Manager.CommandBlocker;
import de.viper.survivalplus.Manager.WarpManager;
import de.viper.survivalplus.commands.SetWarpCommand;
import de.viper.survivalplus.commands.WarpsCommand;
-
import de.viper.survivalplus.fun.FunChallengeManager;
import de.viper.survivalplus.listeners.ChallengeCollectListener;
import de.viper.survivalplus.commands.StartFunChallengeCommand;
import java.util.Map;
import java.util.UUID;
import java.util.HashMap;
-
import org.bukkit.NamespacedKey;
import org.bukkit.plugin.PluginManager;
-
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.logging.Level;
-
-// Zusätzliche Imports für Block-/Permission-Handling
import org.bukkit.GameRule;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
@@ -68,6 +64,15 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.command.Command;
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 {
@@ -89,15 +94,12 @@ public class SurvivalPlus extends JavaPlugin {
private FileConfiguration mobCapConfig;
private FileConfiguration tablistConfig;
private File tablistFile;
-
private File nicknamesFile;
private FileConfiguration nicknamesConfig;
private SpawnProtectionListener spawnProtectionListener;
private int autoClearTaskId = -1;
private StatsManager statsManager;
private NewbieProtectionListener newbieListener;
-
- // Listener als Felder speichern
private MobLeashLimitListener mobLeashLimitListener;
private MobCapListener mobCapListener;
private SleepListener sleepListener;
@@ -109,32 +111,33 @@ public class SurvivalPlus extends JavaPlugin {
private FunChallengeManager challengeManager;
private NamespacedKey droppedKey;
private Map progressMap = new HashMap<>();
-
- // WarpManager als Feld
private WarpManager warpManager;
-
- // FunChallengeManager als Feld
private FunChallengeManager funChallengeManager;
-
private File blockedCommandsFile;
private FileConfiguration blockedCommandsConfig;
-
- // Felder für Executor-Instanzen
private LockSystem lockSystem;
private PluginCommand pluginCommand;
+ private Map claims = new HashMap<>();
+ private File claimsFile;
+ private FileConfiguration claimsConfig;
+ private Map playerClaimCounts = new HashMap<>();
+ private Map point1Selections = new HashMap<>();
+ private Map point2Selections = new HashMap<>();
+ private BannerManager bannerManager;
+ private File debugFile;
+ private PrintWriter debugWriter;
+ private File consoleFile;
+ private PrintWriter consoleWriter;
- // ------------------- Tablist Config -------------------
public void reloadTablistConfig() {
- // Lädt die tablist.yml aus dem Plugin-Ordner neu
if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
if (!tablistFile.exists()) {
- saveResource("tablist.yml", false); // kopiert die default tablist.yml, falls sie fehlt
+ saveResource("tablist.yml", false);
}
tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
}
public FileConfiguration getTablistConfig() {
- // Stellt sicher, dass die Config geladen ist
if (tablistConfig == null) {
reloadTablistConfig();
}
@@ -174,329 +177,506 @@ public class SurvivalPlus extends JavaPlugin {
} catch (IOException ignored) {}
}
-@Override
-public void onEnable() {
- // Default-Config sicherstellen
- saveDefaultConfig();
+ @Override
+ public void onEnable() {
+ saveDefaultConfig();
- // bStats initialisieren
- int pluginId = 26886;
- Metrics metrics = new Metrics(this, pluginId);
+ // Version aus plugin.yml
+ String pluginVersion = getDescription().getVersion();
- metrics.addCustomChart(new SimplePie(
- "default_gamemode",
- () -> Bukkit.getDefaultGameMode().toString()
- ));
- metrics.addCustomChart(new SingleLineChart(
- "online_players",
- () -> Bukkit.getOnlinePlayers().size()
- ));
- metrics.addCustomChart(new SimplePie(
- "plugin_language",
- () -> getConfig().getString("language", "default")
- ));
+ // 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);
- // Konfigurationen/Dateien laden
- updateConfigFiles();
- createHomesFile();
- createGravesFile();
- createBackpackFile();
- createFriendsFile();
- createLeashesFile();
- createMobCapFile();
- createNicknamesFile();
- reloadBlockedCommandsConfig();
+ // Debug-Logging initialisieren
+ if (getConfig().getBoolean("debug-logging", false)) {
+ try {
+ // Ordner erstellen
+ File debugFolder = new File(getDataFolder(), "Debug");
+ if (!debugFolder.exists()) {
+ debugFolder.mkdirs();
+ }
- // PluginManager holen (vor Listener-Registrierung!)
- PluginManager pluginManager = getServer().getPluginManager();
+ // debug.log für Fehler
+ debugFile = new File(debugFolder, "debug.log");
+ if (!debugFile.exists()) debugFile.createNewFile();
+ debugWriter = new PrintWriter(new FileWriter(debugFile, true), true);
- // Permission registrieren: survivalplus.notify für OPs standardmäßig aktiv
- try {
- Permission notifyPerm = new Permission("survivalplus.notify", PermissionDefault.OP);
- if (pluginManager.getPermission("survivalplus.notify") == null) {
- pluginManager.addPermission(notifyPerm);
- getLogger().info("Permission survivalplus.notify erfolgreich registriert.");
- }
- } catch (Exception e) {
- getLogger().warning("Fehler beim Registrieren der Permission survivalplus.notify: " + e.getMessage());
- }
+ // 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);
- // NamespacedKey für Item-Drop-Markierung erzeugen
- droppedKey = new NamespacedKey(this, "droppedItem");
-
- // FunChallengeManager initialisieren und laden
- funChallengeManager = new FunChallengeManager();
- funChallengeManager.load(getConfig());
-
- // Listener registrieren mit droppedKey
- pluginManager.registerEvents(new ChallengeCollectListener(funChallengeManager, droppedKey), this);
- pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
-
- // FriendCommand
- FriendCommand friendCommand = new FriendCommand(this, friendsConfig, langConfig, getLogger());
-
- getCommand("day").setExecutor(new DayCommand(this));
- getCommand("night").setExecutor(new NightCommand(this));
-
- CommandBlocker commandBlocker = new CommandBlocker(this);
- pluginCommand = new PluginCommand(this);
- getCommand("sp").setExecutor(pluginCommand);
-
- // TradeManager und ReportManager initialisieren
- TradeManager tradeManager = new TradeManager(this);
- ReportManager reportManager = new ReportManager(this);
-
- // Report Commands registrieren
- getCommand("report").setExecutor(new ReportCommand(this, reportManager));
- getCommand("showreport").setExecutor(new ShowReportCommand(this, reportManager));
- getCommand("clearreport").setExecutor(new ClearReportCommand(this, reportManager));
-
- // Trade Commands registrieren
- getCommand("trade").setExecutor(new TradeCommand(this, tradeManager));
- getCommand("tradeaccept").setExecutor(new TradeAcceptCommand(this, tradeManager));
-
- // StatsManager initialisieren
- statsManager = new StatsManager(this);
-
- // warpManager initialisieren
- warpManager = new WarpManager(this);
-
- // TablistManager starten
- TablistManager tablistManager = new TablistManager(this);
-
- // Listener-Instanzen
- sitListener = new SitListener(this);
- afkListener = new AFKListener(this);
- graveListener = new GraveListener(this);
- playerJoinListener = new PlayerJoinListener(friendCommand);
-
- // Commands registrieren (Rest)
- getCommand("gm").setExecutor(new GamemodeCommand(this));
- getCommand("sp").setExecutor(new PluginCommand(this));
- getCommand("sethome").setExecutor(new HomeCommand(this));
- getCommand("delhome").setExecutor(new HomeCommand(this));
- getCommand("homelist").setExecutor(new HomeCommand(this));
- getCommand("inv").setExecutor(new InventoryCommand(this));
- getCommand("ec").setExecutor(new EnderchestCommand(this));
- getCommand("setspawn").setExecutor(new SetSpawnCommand(this));
- getCommand("setworldspawn").setExecutor(new SetWorldSpawnCommand(this));
- getCommand("clearchat").setExecutor(new ClearChatCommand());
- getCommand("clearitems").setExecutor(new ClearItemsCommand(this));
- getCommand("closedoors").setExecutor(new CloseDoorsCommand(this));
- getCommand("sit").setExecutor(new SitCommand(this, sitListener));
- getCommand("back").setExecutor(new BackCommand(this));
- getCommand("friend").setExecutor(friendCommand);
- getCommand("ir").setExecutor(new ItemRenameCommand(this));
- getCommand("showarmorstands").setExecutor(new ShowArmorStandsCommand(this));
- getCommand("cleardebugarmorstands").setExecutor(new ClearDebugArmorStandsCommand(this));
- getCommand("trash").setExecutor(new TrashCommand());
- getCommand("workbench").setExecutor(new WorkbenchCommand());
- getCommand("anvil").setExecutor(new AnvilCommand());
- getCommand("nick").setExecutor(new NickCommand(this));
- getCommand("shop").setExecutor(new ShopCommand(this));
- getCommand("stats").setExecutor(new StatsCommand(this, statsManager));
- getCommand("spawn").setExecutor(new SpawnCommand(this));
- getCommand("setwarp").setExecutor(new SetWarpCommand(this, warpManager));
- getCommand("warps").setExecutor(new WarpsCommand(this, warpManager));
- getCommand("delwarp").setExecutor(new DelWarpCommand(this, warpManager));
- TeleportCommands teleportCommands = new TeleportCommands(this);
- getCommand("tp").setExecutor(teleportCommands);
- getCommand("tphere").setExecutor(teleportCommands);
- getCommand("tpa").setExecutor(teleportCommands);
- getCommand("tpaccept").setExecutor(teleportCommands);
- getCommand("tpdeny").setExecutor(teleportCommands);
- getCommand("startchallenge").setExecutor(new StartFunChallengeCommand(this, funChallengeManager));
- getCommand("kit").setExecutor(new KitCommand(this));
- getCommand("heal").setExecutor(new HealCommand(this));
- getCommand("sp").setExecutor(commandBlocker);
-
- // LootChestManager + Befehle
- LootChestManager lootChestManager = new LootChestManager(this);
- pluginManager.registerEvents(lootChestManager, this);
- getCommand("lootchests").setExecutor(lootChestManager);
- getCommand("tploot").setExecutor(lootChestManager);
-
- // BlockManager
- BlockManager blockManager = new BlockManager();
- FileConfiguration config = getConfig();
-
- // Listener registrieren
- BackpackRecipe.register(this, langConfig);
- pluginManager.registerEvents(new ChatBlockListener(blockManager), this);
- pluginManager.registerEvents(new InventoryClickListener(this), this);
- pluginManager.registerEvents(sitListener, this);
- pluginManager.registerEvents(afkListener, this);
- pluginManager.registerEvents(graveListener, this);
- pluginManager.registerEvents(new BackpackListener(backpackConfig, langConfig, getLogger(), backpackFile), this);
- pluginManager.registerEvents(new StatsListener(this, statsManager), this);
- pluginManager.registerEvents(new LoginListener(this), this);
- pluginManager.registerEvents(new DebugArmorStandListener(), this);
- pluginManager.registerEvents(new ArmorStandDestroyListener(), this);
- pluginManager.registerEvents(new FirstJoinListener(), this);
- pluginManager.registerEvents(playerJoinListener, this);
- pluginManager.registerEvents(new SignColorListener(this), this);
- pluginManager.registerEvents(new SleepListener(this), this);
- pluginManager.registerEvents(new OreAlarmListener(this), this);
- pluginManager.registerEvents(new MobLeashLimitListener(this, getConfig()), this);
- pluginManager.registerEvents(new MobCapListener(this, getConfig()), this);
- pluginManager.registerEvents(new SpawnProtectionListener(this), this);
- pluginManager.registerEvents(new NewbieProtectionListener(this), this);
- pluginManager.registerEvents(new WarpInventoryListener(this, warpManager), this);
- pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
- pluginManager.registerEvents(new BlockDetectionListener(this), this);
-
- lockSystem = new LockSystem(this);
- pluginManager.registerEvents(lockSystem, this);
- getCommand("sp").setExecutor(lockSystem);
-
- // Kombinierter Executor für /sp, um alle Subcommands zu handhaben
- getCommand("sp").setExecutor(new CommandExecutor() {
- @Override
- public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
- if (!command.getName().equalsIgnoreCase("sp")) {
- return false;
+ 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());
}
- if (args.length == 0) {
+ }
+
+ int pluginId = 26886;
+ Metrics metrics = new Metrics(this, pluginId);
+ metrics.addCustomChart(new SimplePie(
+ "default_gamemode",
+ () -> Bukkit.getDefaultGameMode().toString()
+ ));
+ metrics.addCustomChart(new SingleLineChart(
+ "online_players",
+ () -> Bukkit.getOnlinePlayers().size()
+ ));
+ metrics.addCustomChart(new SimplePie(
+ "plugin_language",
+ () -> getConfig().getString("language", "default")
+ ));
+
+ bannerManager = new BannerManager(this);
+ bannerManager.displayConsoleBanner(); // Banner beim Serverstart
+
+ updateConfigFiles();
+ createHomesFile();
+ createGravesFile();
+ createBackpackFile();
+ createFriendsFile();
+ createLeashesFile();
+ createMobCapFile();
+ createNicknamesFile();
+ reloadBlockedCommandsConfig();
+ loadClaims();
+ PluginManager pluginManager = getServer().getPluginManager();
+ try {
+ Permission notifyPerm = new Permission("survivalplus.notify", PermissionDefault.OP);
+ if (pluginManager.getPermission("survivalplus.notify") == null) {
+ pluginManager.addPermission(notifyPerm);
+ getLogger().info("Permission survivalplus.notify erfolgreich registriert.");
+ }
+ } catch (Exception e) {
+ getLogger().warning("Fehler beim Registrieren der Permission survivalplus.notify: " + e.getMessage());
+ }
+ try {
+ Permission claimPerm = new Permission("survivalplus.claim.use", PermissionDefault.TRUE);
+ Permission trustPerm = new Permission("survivalplus.claim.trust", PermissionDefault.TRUE);
+ if (pluginManager.getPermission("survivalplus.claim.use") == null) {
+ pluginManager.addPermission(claimPerm);
+ getLogger().info("Permission survivalplus.claim.use erfolgreich registriert.");
+ }
+ if (pluginManager.getPermission("survivalplus.claim.trust") == null) {
+ pluginManager.addPermission(trustPerm);
+ getLogger().info("Permission survivalplus.claim.trust erfolgreich registriert.");
+ }
+ } catch (Exception e) {
+ getLogger().warning("Fehler beim Registrieren der Claim-Permissions: " + e.getMessage());
+ }
+ droppedKey = new NamespacedKey(this, "droppedItem");
+ funChallengeManager = new FunChallengeManager();
+ funChallengeManager.load(getConfig());
+ pluginManager.registerEvents(new ChallengeCollectListener(funChallengeManager, droppedKey), this);
+ pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
+ FriendCommand friendCommand = new FriendCommand(this, friendsConfig, langConfig, getLogger());
+ getCommand("day").setExecutor(new DayCommand(this));
+ getCommand("night").setExecutor(new NightCommand(this));
+ CommandBlocker commandBlocker = new CommandBlocker(this);
+ pluginCommand = new PluginCommand(this);
+ getCommand("sp").setExecutor(pluginCommand);
+ TradeManager tradeManager = new TradeManager(this);
+ ReportManager reportManager = new ReportManager(this);
+ getCommand("report").setExecutor(new ReportCommand(this, reportManager));
+ getCommand("showreport").setExecutor(new ShowReportCommand(this, reportManager));
+ getCommand("clearreport").setExecutor(new ClearReportCommand(this, reportManager));
+ getCommand("trade").setExecutor(new TradeCommand(this, tradeManager));
+ getCommand("tradeaccept").setExecutor(new TradeAcceptCommand(this, tradeManager));
+ statsManager = new StatsManager(this);
+ warpManager = new WarpManager(this);
+ TablistManager tablistManager = new TablistManager(this);
+ sitListener = new SitListener(this);
+ afkListener = new AFKListener(this);
+ graveListener = new GraveListener(this);
+ playerJoinListener = new PlayerJoinListener(friendCommand);
+ getCommand("gm").setExecutor(new GamemodeCommand(this));
+ getCommand("sp").setExecutor(new PluginCommand(this));
+ getCommand("sethome").setExecutor(new HomeCommand(this));
+ getCommand("delhome").setExecutor(new HomeCommand(this));
+ getCommand("homelist").setExecutor(new HomeCommand(this));
+ getCommand("inv").setExecutor(new InventoryCommand(this));
+ getCommand("ec").setExecutor(new EnderchestCommand(this));
+ getCommand("setspawn").setExecutor(new SetSpawnCommand(this));
+ getCommand("setworldspawn").setExecutor(new SetWorldSpawnCommand(this));
+ getCommand("clearchat").setExecutor(new ClearChatCommand());
+ getCommand("clearitems").setExecutor(new ClearItemsCommand(this));
+ getCommand("closedoors").setExecutor(new CloseDoorsCommand(this));
+ getCommand("sit").setExecutor(new SitCommand(this, sitListener));
+ getCommand("back").setExecutor(new BackCommand(this));
+ getCommand("friend").setExecutor(friendCommand);
+ getCommand("ir").setExecutor(new ItemRenameCommand(this));
+ getCommand("showarmorstands").setExecutor(new ShowArmorStandsCommand(this));
+ getCommand("cleardebugarmorstands").setExecutor(new ClearDebugArmorStandsCommand(this));
+ getCommand("trash").setExecutor(new TrashCommand());
+ getCommand("workbench").setExecutor(new WorkbenchCommand());
+ getCommand("anvil").setExecutor(new AnvilCommand());
+ getCommand("nick").setExecutor(new NickCommand(this));
+ getCommand("shop").setExecutor(new ShopCommand(this));
+ getCommand("stats").setExecutor(new StatsCommand(this, statsManager));
+ getCommand("spawn").setExecutor(new SpawnCommand(this));
+ getCommand("setwarp").setExecutor(new SetWarpCommand(this, warpManager));
+ getCommand("warps").setExecutor(new WarpsCommand(this, warpManager));
+ getCommand("delwarp").setExecutor(new DelWarpCommand(this, warpManager));
+ TeleportCommands teleportCommands = new TeleportCommands(this);
+ getCommand("tp").setExecutor(teleportCommands);
+ getCommand("tphere").setExecutor(teleportCommands);
+ getCommand("tpa").setExecutor(teleportCommands);
+ getCommand("tpaccept").setExecutor(teleportCommands);
+ getCommand("tpdeny").setExecutor(teleportCommands);
+ getCommand("startchallenge").setExecutor(new StartFunChallengeCommand(this, funChallengeManager));
+ getCommand("kit").setExecutor(new KitCommand(this));
+ getCommand("heal").setExecutor(new HealCommand(this));
+ getCommand("sp").setExecutor(commandBlocker);
+ LootChestManager lootChestManager = new LootChestManager(this);
+ pluginManager.registerEvents(lootChestManager, this);
+ getCommand("lootchests").setExecutor(lootChestManager);
+ getCommand("tploot").setExecutor(lootChestManager);
+ getCommand("claim").setExecutor(new ClaimCommand(this));
+ BlockManager blockManager = new BlockManager();
+ FileConfiguration config = getConfig();
+ BackpackRecipe.register(this, langConfig);
+ pluginManager.registerEvents(new ChatBlockListener(blockManager), this);
+ pluginManager.registerEvents(new InventoryClickListener(this), this);
+ pluginManager.registerEvents(sitListener, this);
+ pluginManager.registerEvents(afkListener, this);
+ pluginManager.registerEvents(graveListener, this);
+ pluginManager.registerEvents(new BackpackListener(backpackConfig, langConfig, getLogger(), backpackFile), this);
+ pluginManager.registerEvents(new StatsListener(this, statsManager), this);
+ pluginManager.registerEvents(new LoginListener(this), this);
+ pluginManager.registerEvents(new DebugArmorStandListener(), this);
+ pluginManager.registerEvents(new ArmorStandDestroyListener(), this);
+ pluginManager.registerEvents(new FirstJoinListener(), this);
+ pluginManager.registerEvents(playerJoinListener, this);
+ pluginManager.registerEvents(new SignColorListener(this), this);
+ pluginManager.registerEvents(new SleepListener(this), this);
+ pluginManager.registerEvents(new OreAlarmListener(this), this);
+ pluginManager.registerEvents(new MobLeashLimitListener(this, getConfig()), this);
+ pluginManager.registerEvents(new MobCapListener(this, getConfig()), this);
+ pluginManager.registerEvents(new SpawnProtectionListener(this), this);
+ pluginManager.registerEvents(new NewbieProtectionListener(this), this);
+ pluginManager.registerEvents(new WarpInventoryListener(this, warpManager), this);
+ pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
+ pluginManager.registerEvents(new BlockDetectionListener(this), this);
+ pluginManager.registerEvents(new ClaimListener(this), this);
+ lockSystem = new LockSystem(this);
+ pluginManager.registerEvents(lockSystem, this);
+ getCommand("sp").setExecutor(lockSystem);
+ getCommand("sp").setExecutor(new CommandExecutor() {
+ @Override
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (!command.getName().equalsIgnoreCase("sp")) {
+ return false;
+ }
+ if (args.length == 0) {
+ return pluginCommand.onCommand(sender, command, label, args);
+ }
+ String subCommand = args[0].toLowerCase();
+ if (subCommand.equals("cb")) {
+ return commandBlocker.onCommand(sender, command, label, args);
+ } else if (subCommand.equals("lock") || subCommand.equals("unlock") ||
+ subCommand.equals("friendadd") || subCommand.equals("friendremove")) {
+ return lockSystem.onCommand(sender, command, label, args);
+ }
return pluginCommand.onCommand(sender, command, label, args);
}
- String subCommand = args[0].toLowerCase();
- if (subCommand.equals("cb")) {
- return commandBlocker.onCommand(sender, command, label, args);
- } else if (subCommand.equals("lock") || subCommand.equals("unlock") ||
- subCommand.equals("friendadd") || subCommand.equals("friendremove")) {
- return lockSystem.onCommand(sender, command, label, args);
- }
- return pluginCommand.onCommand(sender, command, label, args);
+ });
+ pluginManager.registerEvents(new RepairSignListener(getConfig(), getLangConfig()), this);
+ pluginManager.registerEvents(new ToolUpgradeListener(this), this);
+ pluginManager.registerEvents(new NickLoadListener(this), this);
+ startAutoClearTask();
+ spawnArmorStandExample();
+ getLogger().info(getMessage("plugin.enabled"));
+ if (getConfig().getBoolean("set-keepinventory", true)) {
+ Bukkit.getScheduler().runTaskLater(this, () -> {
+ if (Bukkit.getWorlds().isEmpty()) return;
+ Bukkit.getWorlds().forEach(world -> {
+ world.setGameRule(GameRule.KEEP_INVENTORY, false);
+ getLogger().info("Gamerule keepInventory in Welt '" + world.getName() + "' wurde auf false gesetzt.");
+ });
+ }, 20L);
}
- });
-
- pluginManager.registerEvents(new RepairSignListener(getConfig(), getLangConfig()), this);
- pluginManager.registerEvents(new ToolUpgradeListener(this), this);
- pluginManager.registerEvents(new NickLoadListener(this), this);
-
- // AutoClear starten
- startAutoClearTask();
- spawnArmorStandExample();
- getLogger().info(getMessage("plugin.enabled"));
-
- // === Gamerule keepInventory aus Config setzen ===
- if (getConfig().getBoolean("set-keepinventory", true)) {
- Bukkit.getScheduler().runTaskLater(this, () -> {
- if (Bukkit.getWorlds().isEmpty()) return;
-
- Bukkit.getWorlds().forEach(world -> {
- world.setGameRule(GameRule.KEEP_INVENTORY, false);
- getLogger().info("Gamerule keepInventory in Welt '" + world.getName() + "' wurde auf false gesetzt.");
- });
- }, 20L);
- }
-
- // === Force Survival Mode aktivieren ===
- if (getConfig().getBoolean("force-survival", true)) {
- pluginManager.registerEvents(new ForceSurvivalListener(this), this);
- getLogger().info("Force-Survival ist aktiv. Spieler werden beim Joinen in Survival gesetzt.");
- }
-
- // === Animierte Tablist konfigurieren und starten ===
- try {
- // tablist.yml laden / defaults setzen
- if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
- if (!tablistFile.exists()) {
- saveResource("tablist.yml", false);
+ if (getConfig().getBoolean("force-survival", true)) {
+ pluginManager.registerEvents(new ForceSurvivalListener(this), this);
+ getLogger().info("Force-Survival ist aktiv. Spieler werden beim Joinen in Survival gesetzt.");
}
- tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
-
- // Standardwerte aus Resource als Defaults setzen (falls vorhanden)
- InputStream defStream = getResource("tablist.yml");
- if (defStream != null) {
- tablistConfig.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(defStream)));
- }
-
- getLogger().info("Animierte Tablist wurde geladen!");
- } catch (Exception e) {
- getLogger().log(Level.WARNING, "Fehler beim Laden der Tablist-Konfiguration", e);
- }
-
- // === Gamerules anwenden (kurze Verzögerung, damit Welten geladen sind) ===
- Bukkit.getScheduler().runTaskLater(this, this::applyBlockRules, 20L);
-}
-
-/**
- * Liest Config und setzt GameRule sowie entfernt verbotene Blöcke aus Inventaren online
- */
-public void applyBlockRules() {
- boolean cmdAllowed = getConfig().getBoolean("blocks.command-blocks.enabled", true);
- boolean structAllowed = getConfig().getBoolean("blocks.structure-blocks.enabled", true);
-
- for (World world : Bukkit.getWorlds()) {
try {
- // moderner API-Aufruf
- world.setGameRule(GameRule.COMMAND_BLOCK_OUTPUT, cmdAllowed);
- } catch (NoSuchMethodError | NoClassDefFoundError e) {
- // Fallback für ältere Server-Implementationen
- world.setGameRuleValue(GameRule.COMMAND_BLOCK_OUTPUT.getName(), Boolean.toString(cmdAllowed));
- }
- getLogger().info("Gamerule commandBlockOutput in Welt '" + world.getName() + "' gesetzt auf " + cmdAllowed);
- }
-
- // Entferne verbotenes Zeug aus Inventaren aller online-Spieler direkt beim Start
- removeForbiddenBlocksFromInventories(cmdAllowed, structAllowed);
-
- getLogger().info("Block-Regeln angewendet: CommandBlocks erlaubt=" + cmdAllowed + ", StructureBlocks erlaubt=" + structAllowed);
-}
-
-/** Entfernt Command-/Structure-Blöcke aus Inventaren falls deaktiviert, ausgenommen Admins */
-private void removeForbiddenBlocksFromInventories(boolean cmdAllowed, boolean structAllowed) {
- for (Player p : Bukkit.getOnlinePlayers()) {
- if (p.hasPermission("survivalplus.notify")) {
- continue; // Admins dürfen Blöcke behalten
- }
- Inventory inv = p.getInventory();
- boolean removedCommandBlock = false;
- boolean removedStructureBlock = false;
- if (!cmdAllowed && inv.contains(Material.COMMAND_BLOCK)) {
- inv.remove(Material.COMMAND_BLOCK);
- removedCommandBlock = true;
- p.sendMessage(ChatColor.RED + "[SurvivalPlus] Command-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
- }
- if (!structAllowed && inv.contains(Material.STRUCTURE_BLOCK)) {
- inv.remove(Material.STRUCTURE_BLOCK);
- removedStructureBlock = true;
- p.sendMessage(ChatColor.RED + "[SurvivalPlus] Structure-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
- }
- // Benachrichtige Admins über entfernte Blöcke
- if ((removedCommandBlock || removedStructureBlock) && getConfig().getBoolean("blocks.notify-admins-on-possession", true)) {
- notifyAdmins(p.getName(), removedCommandBlock, removedStructureBlock);
- }
- }
-}
-
-/** Benachrichtigt Admins über entfernte Blöcke */
-private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean hadStructureBlock) {
- String baseTag = ChatColor.GRAY + "[" + ChatColor.GREEN + "SurvivalPlus" + ChatColor.GRAY + "] ";
- for (Player admin : Bukkit.getOnlinePlayers()) {
- if (admin.hasPermission("survivalplus.notify")) {
- if (hadCommandBlock) {
- admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
- ChatColor.RED + " hatte einen Command-Block im Inventar, der entfernt wurde.");
+ if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
+ if (!tablistFile.exists()) {
+ saveResource("tablist.yml", false);
}
- if (hadStructureBlock) {
- admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
- ChatColor.RED + " hatte einen Structure-Block im Inventar, der entfernt wurde.");
+ tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
+ InputStream defStream = getResource("tablist.yml");
+ if (defStream != null) {
+ tablistConfig.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(defStream)));
+ }
+ getLogger().info("Animierte Tablist wurde geladen!");
+ } catch (Exception e) {
+ getLogger().log(Level.WARNING, "Fehler beim Laden der Tablist-Konfiguration", e);
+ }
+ Bukkit.getScheduler().runTaskLater(this, this::applyBlockRules, 20L);
+ }
+
+ public void applyBlockRules() {
+ boolean cmdAllowed = getConfig().getBoolean("blocks.command-blocks.enabled", true);
+ boolean structAllowed = getConfig().getBoolean("blocks.structure-blocks.enabled", true);
+ for (World world : Bukkit.getWorlds()) {
+ try {
+ world.setGameRule(GameRule.COMMAND_BLOCK_OUTPUT, cmdAllowed);
+ } catch (NoSuchMethodError | NoClassDefFoundError e) {
+ world.setGameRuleValue(GameRule.COMMAND_BLOCK_OUTPUT.getName(), Boolean.toString(cmdAllowed));
+ }
+ getLogger().info("Gamerule commandBlockOutput in Welt '" + world.getName() + "' gesetzt auf " + cmdAllowed);
+ }
+ removeForbiddenBlocksFromInventories(cmdAllowed, structAllowed);
+ 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 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 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")) {
+ continue;
+ }
+ Inventory inv = p.getInventory();
+ boolean removedCommandBlock = false;
+ boolean removedStructureBlock = false;
+ if (!cmdAllowed && inv.contains(Material.COMMAND_BLOCK)) {
+ inv.remove(Material.COMMAND_BLOCK);
+ removedCommandBlock = true;
+ p.sendMessage(ChatColor.RED + "[SurvivalPlus] Command-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
+ }
+ if (!structAllowed && inv.contains(Material.STRUCTURE_BLOCK)) {
+ inv.remove(Material.STRUCTURE_BLOCK);
+ removedStructureBlock = true;
+ p.sendMessage(ChatColor.RED + "[SurvivalPlus] Structure-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
+ }
+ if ((removedCommandBlock || removedStructureBlock) && getConfig().getBoolean("blocks.notify-admins-on-possession", true)) {
+ notifyAdmins(p.getName(), removedCommandBlock, removedStructureBlock);
}
}
}
-}
+ private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean hadStructureBlock) {
+ String baseTag = ChatColor.GRAY + "[" + ChatColor.GREEN + "SurvivalPlus" + ChatColor.GRAY + "] ";
+ for (Player admin : Bukkit.getOnlinePlayers()) {
+ if (admin.hasPermission("survivalplus.notify")) {
+ if (hadCommandBlock) {
+ admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
+ ChatColor.RED + " hatte einen Command-Block im Inventar, der entfernt wurde.");
+ }
+ if (hadStructureBlock) {
+ admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
+ ChatColor.RED + " hatte einen Structure-Block im Inventar, der entfernt wurde.");
+ }
+ }
+ }
+ }
-
+ private void createClaimsFile() {
+ claimsFile = new File(getDataFolder(), "claims.yml");
+ if (!claimsFile.exists()) {
+ try {
+ claimsFile.createNewFile();
+ } catch (IOException e) {
+ getLogger().log(Level.SEVERE, "Fehler beim Erstellen der claims.yml", e);
+ }
+ }
+ claimsConfig = YamlConfiguration.loadConfiguration(claimsFile);
+ }
+ private void loadClaims() {
+ createClaimsFile();
+ for (String key : claimsConfig.getKeys(false)) {
+ try {
+ UUID owner = UUID.fromString(claimsConfig.getString(key + ".owner"));
+ String worldName = claimsConfig.getString(key + ".world");
+ int x1 = claimsConfig.getInt(key + ".x1");
+ int z1 = claimsConfig.getInt(key + ".z1");
+ int x2 = claimsConfig.getInt(key + ".x2");
+ int z2 = claimsConfig.getInt(key + ".z2");
+ Claim claim = new Claim(owner, worldName, x1, z1, x2, z2);
+ List trustedList = claimsConfig.getStringList(key + ".trusted");
+ for (String trustedStr : trustedList) {
+ claim.addTrusted(UUID.fromString(trustedStr));
+ }
+ claims.put(key, claim);
+ playerClaimCounts.merge(owner, 1, Integer::sum);
+ } catch (Exception e) {
+ getLogger().warning("Invalid claim data for key: " + key);
+ }
+ }
+ }
+ public void saveClaims() {
+ for (Map.Entry entry : claims.entrySet()) {
+ String key = entry.getKey();
+ Claim claim = entry.getValue();
+ claimsConfig.set(key + ".owner", claim.getOwner().toString());
+ claimsConfig.set(key + ".x1", claim.getX1());
+ claimsConfig.set(key + ".z1", claim.getZ1());
+ claimsConfig.set(key + ".x2", claim.getX2());
+ claimsConfig.set(key + ".z2", claim.getZ2());
+ claimsConfig.set(key + ".world", claim.getWorldName());
+ List trustedList = new ArrayList<>();
+ for (UUID trusted : claim.getTrusted()) {
+ trustedList.add(trusted.toString());
+ }
+ claimsConfig.set(key + ".trusted", trustedList);
+ }
+ try {
+ claimsConfig.save(claimsFile);
+ } catch (IOException e) {
+ getLogger().log(Level.SEVERE, "Fehler beim Speichern der claims.yml", e);
+ }
+ }
+ public Claim getClaim(Location location) {
+ for (Claim claim : claims.values()) {
+ if (claim.isInside(location)) {
+ return claim;
+ }
+ }
+ return null;
+ }
+ public void addClaim(Claim claim, Player player) {
+ String key = claim.getWorldName() + ":" + claim.getX1() + ":" + claim.getZ1() + ":" + claim.getX2() + ":" + claim.getZ2();
+ claims.put(key, claim);
+ playerClaimCounts.merge(player.getUniqueId(), 1, Integer::sum);
+ saveClaims();
+ }
+ public void removeClaim(Location location, Player player) {
+ String key = null;
+ for (Map.Entry entry : claims.entrySet()) {
+ if (entry.getValue().isInside(location)) {
+ key = entry.getKey();
+ break;
+ }
+ }
+ if (key != null) {
+ claims.remove(key);
+ playerClaimCounts.merge(player.getUniqueId(), -1, Integer::sum);
+ saveClaims();
+ }
+ }
+ public void removeClaimByKey(String key, UUID playerUUID) {
+ claims.remove(key);
+ playerClaimCounts.merge(playerUUID, -1, Integer::sum);
+ saveClaims();
+ }
+ public Map getClaims() {
+ return claims;
+ }
+
+ public int getClaimCount(Player player) {
+ return playerClaimCounts.getOrDefault(player.getUniqueId(), 0);
+ }
+
+ public void setPoint1(Player player, Location location) {
+ point1Selections.put(player.getUniqueId(), location);
+ }
+
+ public void setPoint2(Player player, Location location) {
+ point2Selections.put(player.getUniqueId(), location);
+ }
+
+ public Location getPoint1(Player player) {
+ return point1Selections.get(player.getUniqueId());
+ }
+
+ public Location getPoint2(Player player) {
+ return point2Selections.get(player.getUniqueId());
+ }
+
+ public void clearSelections(Player player) {
+ point1Selections.remove(player.getUniqueId());
+ point2Selections.remove(player.getUniqueId());
+ }
+
+ public boolean hasOverlap(Claim newClaim) {
+ for (Claim existingClaim : claims.values()) {
+ if (existingClaim.overlaps(newClaim)) {
+ return true;
+ }
+ }
+ return false;
+ }
@@ -547,6 +727,9 @@ private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean ha
@Override
public void onDisable() {
+ if (debugWriter != null) {
+ debugWriter.close();
+ }
if (autoClearTaskId != -1) {
Bukkit.getScheduler().cancelTask(autoClearTaskId);
}
@@ -995,4 +1178,34 @@ private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean ha
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
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/de/viper/survivalplus/commands/ClaimCommand.java b/src/main/java/de/viper/survivalplus/commands/ClaimCommand.java
new file mode 100644
index 0000000..66a12e4
--- /dev/null
+++ b/src/main/java/de/viper/survivalplus/commands/ClaimCommand.java
@@ -0,0 +1,226 @@
+package de.viper.survivalplus.commands;
+
+import de.viper.survivalplus.SurvivalPlus;
+import de.viper.survivalplus.util.Claim;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.UUID;
+import java.util.Map;
+import java.util.HashMap;
+
+public class ClaimCommand implements CommandExecutor {
+ private SurvivalPlus plugin;
+ private static final int MAX_CLAIMS = 10;
+ private static final int MAX_AREA = 10000; // 100x100 blocks
+
+ public ClaimCommand(SurvivalPlus plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
+ if (!(sender instanceof Player)) {
+ sender.sendMessage(plugin.getMessage("commands.player-only"));
+ return true;
+ }
+ Player player = (Player) sender;
+
+ if (args.length == 0) {
+ if (!player.hasPermission("survivalplus.claim.use")) {
+ player.sendMessage(plugin.getMessage("commands.no-permission"));
+ return true;
+ }
+ Location point1 = plugin.getPoint1(player);
+ Location point2 = plugin.getPoint2(player);
+ if (point1 == null || point2 == null) {
+ player.sendMessage(plugin.getMessage("claim.points-not-set"));
+ return true;
+ }
+ if (!point1.getWorld().equals(point2.getWorld())) {
+ player.sendMessage(plugin.getMessage("claim.different-worlds"));
+ return true;
+ }
+ int x1 = point1.getBlockX();
+ int z1 = point1.getBlockZ();
+ int x2 = point2.getBlockX();
+ int z2 = point2.getBlockZ();
+ int width = Math.abs(x2 - x1) + 1;
+ int length = Math.abs(z2 - z1) + 1;
+ if (width * length > MAX_AREA) {
+ player.sendMessage(plugin.getMessage("claim.too-large").replace("%max%", String.valueOf(MAX_AREA)));
+ return true;
+ }
+ Claim newClaim = new Claim(player, point1.getWorld().getName(), x1, z1, x2, z2);
+ if (plugin.hasOverlap(newClaim)) {
+ player.sendMessage(plugin.getMessage("claim.overlap"));
+ return true;
+ }
+ if (plugin.getClaimCount(player) >= MAX_CLAIMS) {
+ player.sendMessage(plugin.getMessage("claim.max-reached").replace("%max%", String.valueOf(MAX_CLAIMS)));
+ return true;
+ }
+ plugin.addClaim(newClaim, player);
+ player.sendMessage(plugin.getMessage("claim.success").replace("%count%", String.valueOf(plugin.getClaimCount(player))).replace("%max%", String.valueOf(MAX_CLAIMS)));
+ plugin.clearSelections(player);
+ return true;
+ }
+
+ switch (args[0].toLowerCase()) {
+ case "mark":
+ if (!player.hasPermission("survivalplus.claim.use")) {
+ player.sendMessage(plugin.getMessage("commands.no-permission"));
+ return true;
+ }
+ if (args.length < 2 || (!args[1].equals("1") && !args[1].equals("2"))) {
+ player.sendMessage(plugin.getMessage("claim.usage-mark"));
+ return true;
+ }
+ Location location = player.getLocation();
+ if (args[1].equals("1")) {
+ plugin.setPoint1(player, location);
+ player.sendMessage(plugin.getMessage("claim.point1-set").replace("%x%", String.valueOf(location.getBlockX())).replace("%z%", String.valueOf(location.getBlockZ())));
+ } else {
+ plugin.setPoint2(player, location);
+ player.sendMessage(plugin.getMessage("claim.point2-set").replace("%x%", String.valueOf(location.getBlockX())).replace("%z%", String.valueOf(location.getBlockZ())));
+ }
+ return true;
+
+ case "unclaim":
+ if (args.length == 1) {
+ if (!player.hasPermission("survivalplus.claim.use")) {
+ player.sendMessage(plugin.getMessage("commands.no-permission"));
+ return true;
+ }
+ Claim claim = plugin.getClaim(player.getLocation());
+ if (claim == null || !claim.getOwner().equals(player.getUniqueId())) {
+ player.sendMessage(plugin.getMessage("claim.not-owner"));
+ return true;
+ }
+ plugin.removeClaim(player.getLocation(), player);
+ player.sendMessage(plugin.getMessage("claim.unclaimed"));
+ return true;
+ } else if (args.length == 2 && player.isOp()) {
+ Player target = Bukkit.getPlayer(args[1]);
+ UUID targetUUID;
+ if (target != null) {
+ targetUUID = target.getUniqueId();
+ } else {
+ try {
+ targetUUID = UUID.fromString(args[1]);
+ } catch (IllegalArgumentException e) {
+ player.sendMessage(plugin.getMessage("commands.player-not-found"));
+ return true;
+ }
+ }
+ int removedCount = removePlayerClaims(targetUUID);
+ if (removedCount > 0) {
+ player.sendMessage(plugin.getMessage("claim.op-unclaimed")
+ .replace("%player%", args[1])
+ .replace("%count%", String.valueOf(removedCount)));
+ } else {
+ player.sendMessage(plugin.getMessage("claim.no-claims-found")
+ .replace("%player%", args[1]));
+ }
+ return true;
+ } else {
+ player.sendMessage(plugin.getMessage("claim.usage"));
+ return true;
+ }
+
+ case "trust":
+ if (!player.hasPermission("survivalplus.claim.trust")) {
+ player.sendMessage(plugin.getMessage("commands.no-permission"));
+ return true;
+ }
+ if (args.length < 2) {
+ player.sendMessage(plugin.getMessage("claim.usage-trust"));
+ return true;
+ }
+ Player target = Bukkit.getPlayer(args[1]);
+ if (target == null) {
+ player.sendMessage(plugin.getMessage("commands.player-not-found"));
+ return true;
+ }
+ Claim claim = plugin.getClaim(player.getLocation());
+ if (claim == null || !claim.getOwner().equals(player.getUniqueId())) {
+ player.sendMessage(plugin.getMessage("claim.not-owner"));
+ return true;
+ }
+ claim.addTrusted(target.getUniqueId());
+ player.sendMessage(plugin.getMessage("claim.trusted").replace("%player%", args[1]));
+ plugin.saveClaims();
+ break;
+
+ case "untrust":
+ if (!player.hasPermission("survivalplus.claim.trust")) {
+ player.sendMessage(plugin.getMessage("commands.no-permission"));
+ return true;
+ }
+ if (args.length < 2) {
+ player.sendMessage(plugin.getMessage("claim.usage-untrust"));
+ return true;
+ }
+ target = Bukkit.getPlayer(args[1]);
+ if (target == null) {
+ player.sendMessage(plugin.getMessage("commands.player-not-found"));
+ return true;
+ }
+ claim = plugin.getClaim(player.getLocation());
+ if (claim == null || !claim.getOwner().equals(player.getUniqueId())) {
+ player.sendMessage(plugin.getMessage("claim.not-owner"));
+ return true;
+ }
+ claim.removeTrusted(target.getUniqueId());
+ player.sendMessage(plugin.getMessage("claim.untrusted").replace("%player%", args[1]));
+ plugin.saveClaims();
+ break;
+
+ case "info":
+ if (!player.hasPermission("survivalplus.claim.use")) {
+ player.sendMessage(plugin.getMessage("commands.no-permission"));
+ return true;
+ }
+ claim = plugin.getClaim(player.getLocation());
+ if (claim == null) {
+ player.sendMessage(plugin.getMessage("claim.no-claim-at-location"));
+ return true;
+ }
+ String ownerName = Bukkit.getOfflinePlayer(claim.getOwner()).getName();
+ if (ownerName == null) {
+ ownerName = claim.getOwner().toString(); // Fallback to UUID if name not found
+ }
+ player.sendMessage(plugin.getMessage("claim.info")
+ .replace("%owner%", ownerName)
+ .replace("%world%", claim.getWorldName())
+ .replace("%x1%", String.valueOf(claim.getX1()))
+ .replace("%z1%", String.valueOf(claim.getZ1()))
+ .replace("%x2%", String.valueOf(claim.getX2()))
+ .replace("%z2%", String.valueOf(claim.getZ2())));
+ return true;
+
+ default:
+ player.sendMessage(plugin.getMessage("claim.usage"));
+ }
+ return true;
+ }
+
+ private int removePlayerClaims(UUID targetUUID) {
+ Map claims = new HashMap<>(plugin.getClaims());
+ int removedCount = 0;
+ for (Map.Entry entry : claims.entrySet()) {
+ if (entry.getValue().getOwner().equals(targetUUID)) {
+ plugin.removeClaimByKey(entry.getKey(), targetUUID);
+ removedCount++;
+ }
+ }
+ if (removedCount > 0) {
+ plugin.saveClaims();
+ }
+ return removedCount;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/viper/survivalplus/listeners/ClaimListener.java b/src/main/java/de/viper/survivalplus/listeners/ClaimListener.java
new file mode 100644
index 0000000..0eb967d
--- /dev/null
+++ b/src/main/java/de/viper/survivalplus/listeners/ClaimListener.java
@@ -0,0 +1,73 @@
+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 lastClaim = new HashMap<>();
+
+ public ClaimListener(SurvivalPlus plugin) {
+ this.plugin = plugin;
+ }
+
+ @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())) {
+ event.setCancelled(true);
+ player.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())) {
+ 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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/viper/survivalplus/listeners/NewbieProtectionListener.java b/src/main/java/de/viper/survivalplus/listeners/NewbieProtectionListener.java
index 631f7d6..60d54e4 100644
--- a/src/main/java/de/viper/survivalplus/listeners/NewbieProtectionListener.java
+++ b/src/main/java/de/viper/survivalplus/listeners/NewbieProtectionListener.java
@@ -26,10 +26,12 @@ 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 und BossBars
+ // Maps für Zeiten, BossBars und Nachrichten-Abklingzeit
private final Map remainingSeconds = new HashMap<>();
private final Map bossBars = new HashMap<>();
+ private final Map messageCooldowns = new HashMap<>();
// YAML Datei
private File dataFile;
@@ -89,14 +91,29 @@ public class NewbieProtectionListener implements Listener {
if (!(event.getEntity() instanceof Player)) return;
Player victim = (Player) event.getEntity();
- UUID vid = victim.getUniqueId();
- Integer timeLeft = remainingSeconds.get(vid);
+ UUID victimId = victim.getUniqueId();
+ Integer timeLeft = remainingSeconds.get(victimId);
if (timeLeft != null && timeLeft > 0) {
event.setCancelled(true);
- victim.sendMessage(ChatColor.GREEN + "Du bist noch im Neulingsschutz!");
+
+ // 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
if (event.getDamager() instanceof Player) {
- ((Player) event.getDamager()).sendMessage(ChatColor.RED + victim.getName() + " ist noch geschützt!");
+ 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);
+ }
}
}
}
@@ -158,7 +175,6 @@ public class NewbieProtectionListener implements Listener {
}
}
- // WICHTIG: Public gemacht, damit von SurvivalPlus.java aufrufbar
public void saveData() {
if (dataConfig == null) return;
for (Map.Entry entry : remainingSeconds.entrySet()) {
@@ -176,4 +192,4 @@ public class NewbieProtectionListener implements Listener {
int sec = totalSec % 60;
return String.format("%02d:%02d", min, sec);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/de/viper/survivalplus/util/BannerManager.java b/src/main/java/de/viper/survivalplus/util/BannerManager.java
new file mode 100644
index 0000000..2b9a9be
--- /dev/null
+++ b/src/main/java/de/viper/survivalplus/util/BannerManager.java
@@ -0,0 +1,28 @@
+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 banner = Arrays.asList(
+ "******************************",
+ "* SurvivalPlus " + version + " *",
+ "* *",
+ "* M_Viper *",
+ "******************************"
+ );
+ for (String line : banner) {
+ plugin.getLogger().info(line);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/viper/survivalplus/util/Claim.java b/src/main/java/de/viper/survivalplus/util/Claim.java
new file mode 100644
index 0000000..172ea03
--- /dev/null
+++ b/src/main/java/de/viper/survivalplus/util/Claim.java
@@ -0,0 +1,91 @@
+package de.viper.survivalplus.util;
+
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+public class Claim {
+ private UUID owner;
+ private Set trusted = new HashSet<>();
+ private int x1, z1, x2, z2;
+ private String worldName;
+
+ public Claim(Player owner, String worldName, int x1, int z1, int x2, int z2) {
+ this.owner = owner.getUniqueId();
+ this.worldName = worldName;
+ this.x1 = Math.min(x1, x2);
+ this.z1 = Math.min(z1, z2);
+ this.x2 = Math.max(x1, x2);
+ this.z2 = Math.max(z1, z2);
+ trusted.add(owner.getUniqueId());
+ }
+
+ public Claim(UUID owner, String worldName, int x1, int z1, int x2, int z2) {
+ this.owner = owner;
+ this.worldName = worldName;
+ this.x1 = Math.min(x1, x2);
+ this.z1 = Math.min(z1, z2);
+ this.x2 = Math.max(x1, x2);
+ this.z2 = Math.max(z1, z2);
+ trusted.add(owner);
+ }
+
+ public boolean canInteract(UUID uuid) {
+ return trusted.contains(uuid);
+ }
+
+ public void addTrusted(UUID uuid) {
+ trusted.add(uuid);
+ }
+
+ public void removeTrusted(UUID uuid) {
+ trusted.remove(uuid);
+ }
+
+ public UUID getOwner() {
+ return owner;
+ }
+
+ public Set getTrusted() {
+ return trusted;
+ }
+
+ public int getX1() {
+ return x1;
+ }
+
+ public int getZ1() {
+ return z1;
+ }
+
+ public int getX2() {
+ return x2;
+ }
+
+ public int getZ2() {
+ return z2;
+ }
+
+ public String getWorldName() {
+ return worldName;
+ }
+
+ public boolean isInside(Location location) {
+ if (!location.getWorld().getName().equals(worldName)) {
+ return false;
+ }
+ int x = location.getBlockX();
+ int z = location.getBlockZ();
+ return x >= x1 && x <= x2 && z >= z1 && z <= z2;
+ }
+
+ public boolean overlaps(Claim other) {
+ if (!this.worldName.equals(other.worldName)) {
+ return false;
+ }
+ return !(this.x2 < other.x1 || this.x1 > other.x2 || this.z2 < other.z1 || this.z1 > other.z2);
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/claims.yml b/src/main/resources/claims.yml
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 9db582b..853be75 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -1,3 +1,9 @@
+# Version (Nicht Ändern!)
+version: 1.0.9
+
+# Debug-Option
+debug-logging: false
+
# Neulings Schutz
newbie-protection:
enabled: true
diff --git a/src/main/resources/help.yml b/src/main/resources/help.yml
index 2939797..370250d 100644
--- a/src/main/resources/help.yml
+++ b/src/main/resources/help.yml
@@ -273,6 +273,23 @@ commands:
description: "&eHeilt einen Spieler vollständig."
usage: "&b/heal [spieler]"
+ claim:
+ description: "&eVerwaltet Claims für den Anti-Grief-Schutz."
+ usage: "&b/claim [mark <1|2>| unclaim | trust | untrust ]"
+ subcommands:
+ mark:
+ description: "&eMarkiert die erste oder zweite Ecke eines zu schützenden Bereichs."
+ usage: "&b/claim mark <1|2>"
+ unclaim:
+ description: "&eGibt den geschützten Bereich frei, in dem du stehst."
+ usage: "&b/claim unclaim"
+ trust:
+ description: "&eFügt einen Spieler als vertrauenswürdig hinzu, sodass er im Bereich bauen kann."
+ usage: "&b/claim trust "
+ untrust:
+ description: "&eEntfernt die Vertrauensberechtigung eines Spielers für den Bereich."
+ usage: "&b/claim untrust "
+
messages:
header: "&6=== Befehle ==="
footer: "&6================"
diff --git a/src/main/resources/lang.yml b/src/main/resources/lang.yml
index 1d6b32e..3fcc9b4 100644
--- a/src/main/resources/lang.yml
+++ b/src/main/resources/lang.yml
@@ -402,5 +402,31 @@ inventory:
no-permission-others: "§cDu hast keine Berechtigung, das Inventar anderer Spieler anzusehen!"
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."
+
force-survival:
join-message: "§aDu wurdest in den Survivalmodus gesetzt!"
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 10c4543..6a8374d 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,5 +1,6 @@
name: SurvivalPlus
-version: 1.0.7
+version: 1.0.9
+
main: de.viper.survivalplus.SurvivalPlus
api-version: 1.21
@@ -265,6 +266,17 @@ commands:
permission: survivalplus.heal
permission-message: "§cDu hast keine Berechtigung, Spieler zu heilen!"
+ claim:
+ description: Manages claims for anti-griefing
+ usage: / [unclaim | trust | untrust ]
+ aliases: [cl]
+ survivalplus.claim.use:
+ description: Allows claiming and unclaiming chunks
+ default: true
+ survivalplus.claim.trust:
+ description: Allows trusting/untrusting players in claims
+ default: true
+
permissions:
survivalplus.*:
description: Gibt Zugriff auf alle SurvivalPlus-Befehle