Initial commit of SurvivalPlus plugin
This commit is contained in:
148
src/main/java/de/viper/survivalplus/Manager/AFKManager.java
Normal file
148
src/main/java/de/viper/survivalplus/Manager/AFKManager.java
Normal file
@@ -0,0 +1,148 @@
|
||||
package de.viper.survivalplus.tasks;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.boss.BarFlag;
|
||||
import org.bukkit.boss.BarStyle;
|
||||
import org.bukkit.boss.BossBar;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class AFKManager {
|
||||
|
||||
private final Plugin plugin;
|
||||
private final long afkAfterMillis;
|
||||
private final long kickAfterMillis;
|
||||
private final long joinGracePeriodMillis = 5000; // 5 Sekunden Schonfrist
|
||||
|
||||
private final Map<UUID, Long> lastActivity = new HashMap<>();
|
||||
private final Map<UUID, Long> joinTimes = new HashMap<>();
|
||||
private final Set<UUID> afkPlayers = new HashSet<>();
|
||||
private final Map<UUID, BossBar> bossBars = new WeakHashMap<>();
|
||||
private final Map<UUID, Integer> colorIndex = new HashMap<>();
|
||||
private final Map<UUID, BukkitRunnable> colorTasks = new HashMap<>();
|
||||
|
||||
private final List<BarColor> colorCycle = List.of(
|
||||
BarColor.RED, BarColor.YELLOW, BarColor.GREEN,
|
||||
BarColor.BLUE, BarColor.PURPLE, BarColor.PINK
|
||||
);
|
||||
|
||||
public AFKManager(Plugin plugin, long afkAfterSeconds, long kickAfterSeconds) {
|
||||
this.plugin = plugin;
|
||||
this.afkAfterMillis = afkAfterSeconds * 1000;
|
||||
this.kickAfterMillis = kickAfterSeconds * 1000;
|
||||
}
|
||||
|
||||
public void updateActivity(Player player) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
long now = System.currentTimeMillis();
|
||||
lastActivity.put(uuid, now);
|
||||
// Optional: Schonfrist erneuern
|
||||
joinTimes.put(uuid, now);
|
||||
if (afkPlayers.remove(uuid)) {
|
||||
removeAFKBossBar(player);
|
||||
plugin.getLogger().fine("AFK-Status entfernt für " + player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void reset(Player player) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
lastActivity.remove(uuid);
|
||||
joinTimes.remove(uuid);
|
||||
afkPlayers.remove(uuid);
|
||||
removeAFKBossBar(player);
|
||||
}
|
||||
|
||||
public boolean isAFK(Player player) {
|
||||
return afkPlayers.contains(player.getUniqueId());
|
||||
}
|
||||
|
||||
public void checkAFKStatus(Player player) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
// Schonfrist nach Join
|
||||
if (joinTimes.containsKey(uuid) && (currentTime - joinTimes.get(uuid) < joinGracePeriodMillis)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Kreativ- oder Zuschauermodus ausschließen
|
||||
if (player.getGameMode() == GameMode.CREATIVE ||
|
||||
player.getGameMode() == GameMode.SPECTATOR) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lastActivity.containsKey(uuid)) {
|
||||
lastActivity.put(uuid, currentTime);
|
||||
return;
|
||||
}
|
||||
|
||||
long diff = currentTime - lastActivity.get(uuid);
|
||||
|
||||
if (diff >= afkAfterMillis) {
|
||||
if (afkPlayers.add(uuid)) {
|
||||
showAFKBossBar(player, "§cDu bist AFK!");
|
||||
}
|
||||
if (kickAfterMillis > 0 && diff >= kickAfterMillis) {
|
||||
plugin.getLogger().info("Spieler " + player.getName() + " wird wegen AFK gekickt. Inaktiv seit: " + (diff / 1000) + " Sekunden");
|
||||
player.kickPlayer("§cDu wurdest wegen AFK gekickt.");
|
||||
removeAFKBossBar(player);
|
||||
}
|
||||
} else if (afkPlayers.remove(uuid)) {
|
||||
removeAFKBossBar(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void showAFKBossBar(Player player, String message) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
removeAFKBossBar(player); // nur eine BossBar pro Spieler
|
||||
|
||||
BossBar bar = Bukkit.createBossBar(message, BarColor.YELLOW, BarStyle.SOLID, BarFlag.CREATE_FOG);
|
||||
bar.addPlayer(player);
|
||||
bar.setVisible(true);
|
||||
|
||||
bossBars.put(uuid, bar);
|
||||
colorIndex.put(uuid, 0);
|
||||
|
||||
// ggf. alten Farbwechsel-Task stoppen
|
||||
if (colorTasks.containsKey(uuid)) {
|
||||
colorTasks.get(uuid).cancel();
|
||||
colorTasks.remove(uuid);
|
||||
}
|
||||
|
||||
// Farben wechseln
|
||||
BukkitRunnable task = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
BossBar activeBar = bossBars.get(uuid);
|
||||
if (activeBar == null) {
|
||||
this.cancel();
|
||||
colorTasks.remove(uuid);
|
||||
return;
|
||||
}
|
||||
int index = colorIndex.getOrDefault(uuid, 0);
|
||||
activeBar.setColor(colorCycle.get(index));
|
||||
colorIndex.put(uuid, (index + 1) % colorCycle.size());
|
||||
}
|
||||
};
|
||||
task.runTaskTimer(plugin, 0L, 20L);
|
||||
colorTasks.put(uuid, task);
|
||||
}
|
||||
|
||||
public void removeAFKBossBar(Player player) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
if (colorTasks.containsKey(uuid)) {
|
||||
colorTasks.get(uuid).cancel();
|
||||
colorTasks.remove(uuid);
|
||||
}
|
||||
BossBar bar = bossBars.remove(uuid);
|
||||
if (bar != null) {
|
||||
bar.removeAll();
|
||||
}
|
||||
colorIndex.remove(uuid);
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package de.viper.survivalplus.Manager;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class BlockManager {
|
||||
|
||||
private final Map<UUID, Set<UUID>> blockedPlayers = new HashMap<>();
|
||||
|
||||
public void blockPlayer(Player blocker, Player toBlock) {
|
||||
blockedPlayers.computeIfAbsent(blocker.getUniqueId(), k -> new HashSet<>()).add(toBlock.getUniqueId());
|
||||
}
|
||||
|
||||
public void unblockPlayer(Player blocker, Player toUnblock) {
|
||||
Set<UUID> blocked = blockedPlayers.get(blocker.getUniqueId());
|
||||
if (blocked != null) {
|
||||
blocked.remove(toUnblock.getUniqueId());
|
||||
if (blocked.isEmpty()) {
|
||||
blockedPlayers.remove(blocker.getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasBlocked(Player blocker, Player potentialBlocked) {
|
||||
return blockedPlayers.getOrDefault(blocker.getUniqueId(), Collections.emptySet())
|
||||
.contains(potentialBlocked.getUniqueId());
|
||||
}
|
||||
|
||||
public Set<UUID> getBlockedPlayers(Player player) {
|
||||
return blockedPlayers.getOrDefault(player.getUniqueId(), Collections.emptySet());
|
||||
}
|
||||
|
||||
public void clear(Player player) {
|
||||
blockedPlayers.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
@@ -0,0 +1,323 @@
|
||||
package de.viper.survivalplus.Manager;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.command.*;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class LootChestManager implements Listener, CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final List<Location> activeChests = new ArrayList<>();
|
||||
private final Map<Location, Long> chestSpawnTimes = new HashMap<>();
|
||||
private final List<LootItem> lootItems = new ArrayList<>();
|
||||
private final Map<UUID, Integer> playerLootCount = new HashMap<>();
|
||||
|
||||
private final long despawnMillis;
|
||||
private final int maxActiveChests;
|
||||
private final int maxLootPerPlayer;
|
||||
private final long lootLimitResetMillis;
|
||||
|
||||
public LootChestManager(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
loadLootFromConfig();
|
||||
|
||||
FileConfiguration cfg = plugin.getConfig();
|
||||
this.despawnMillis = cfg.getLong("lootchest.despawn-minutes", 10) * 60 * 1000;
|
||||
this.maxActiveChests = cfg.getInt("lootchest.max-active-chests", 10);
|
||||
this.maxLootPerPlayer = cfg.getInt("lootchest.max-loot-per-player", 3);
|
||||
this.lootLimitResetMillis = cfg.getLong("lootchest.loot-limit-reset-minutes", 60) * 60 * 1000;
|
||||
|
||||
startChestSpawnTask();
|
||||
startChestDespawnTask();
|
||||
startLootLimitResetTask();
|
||||
}
|
||||
|
||||
private void loadLootFromConfig() {
|
||||
FileConfiguration cfg = plugin.getConfig();
|
||||
lootItems.clear();
|
||||
if (cfg.isConfigurationSection("lootchest.items")) {
|
||||
for (String key : cfg.getConfigurationSection("lootchest.items").getKeys(false)) {
|
||||
lootItems.add(new LootItem(cfg, "lootchest.items." + key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startLootLimitResetTask() {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
playerLootCount.clear();
|
||||
}
|
||||
}.runTaskTimer(plugin, lootLimitResetMillis / 50, lootLimitResetMillis / 50);
|
||||
}
|
||||
|
||||
private void startChestSpawnTask() {
|
||||
long intervalTicks = plugin.getConfig().getLong("lootchest.interval-minutes", 30) * 60 * 20;
|
||||
int spawnCount = plugin.getConfig().getInt("lootchest.spawn-count", 3);
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!plugin.getConfig().getBoolean("lootchest.enabled", true)) return;
|
||||
clearAllActiveChests();
|
||||
for (int i = 0; i < spawnCount; i++) {
|
||||
spawnRandomLootChest();
|
||||
}
|
||||
Bukkit.broadcastMessage(color(
|
||||
plugin.getLangConfig().getString("lootchest.spawn-simple", "&aNeue Loot-Kisten sind gespawnt!")
|
||||
));
|
||||
}
|
||||
}.runTaskTimer(plugin, 0L, intervalTicks);
|
||||
}
|
||||
|
||||
private void startChestDespawnTask() {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long now = System.currentTimeMillis();
|
||||
Iterator<Location> it = activeChests.iterator();
|
||||
while (it.hasNext()) {
|
||||
Location loc = it.next();
|
||||
Long spawnTime = chestSpawnTimes.get(loc);
|
||||
if (spawnTime != null && now - spawnTime >= despawnMillis) {
|
||||
if (loc.getBlock().getType() == Material.CHEST) {
|
||||
loc.getBlock().setType(Material.AIR);
|
||||
}
|
||||
it.remove();
|
||||
chestSpawnTimes.remove(loc);
|
||||
Bukkit.broadcastMessage(color(
|
||||
plugin.getLangConfig().getString("lootchest.despawn-msg",
|
||||
"&eEine Lootkiste ist von selbst verschwunden.")
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(plugin, 20L * 60, 20L * 60);
|
||||
}
|
||||
|
||||
private void clearAllActiveChests() {
|
||||
for (Location loc : new ArrayList<>(activeChests)) {
|
||||
if (loc.getBlock().getType() == Material.CHEST) {
|
||||
loc.getBlock().setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
activeChests.clear();
|
||||
chestSpawnTimes.clear();
|
||||
}
|
||||
|
||||
private void spawnRandomLootChest() {
|
||||
if (activeChests.size() >= maxActiveChests) {
|
||||
return;
|
||||
}
|
||||
|
||||
World world = Bukkit.getWorld(plugin.getConfig().getString("lootchest.world", "world"));
|
||||
if (world == null) return;
|
||||
|
||||
int radius = plugin.getConfig().getInt("lootchest.spawn-radius", 500);
|
||||
ThreadLocalRandom r = ThreadLocalRandom.current();
|
||||
|
||||
int x = r.nextInt(-radius, radius);
|
||||
int z = r.nextInt(-radius, radius);
|
||||
int y = world.getHighestBlockYAt(x, z);
|
||||
|
||||
Location loc = new Location(world, x, y, z);
|
||||
|
||||
// Kein Spawn auf Wasser, Lava, Kelp, Seegras
|
||||
Material below = world.getBlockAt(x, y - 1, z).getType();
|
||||
if (below == Material.WATER || below == Material.LAVA
|
||||
|| below == Material.KELP || below == Material.SEAGRASS
|
||||
|| below == Material.TALL_SEAGRASS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (loc.getBlock().getType() != Material.AIR) {
|
||||
loc.add(0, 1, 0);
|
||||
}
|
||||
|
||||
loc.getBlock().setType(Material.CHEST);
|
||||
Chest chest = (Chest) loc.getBlock().getState();
|
||||
fillChestWithRandomLoot(chest.getInventory());
|
||||
|
||||
activeChests.add(loc);
|
||||
chestSpawnTimes.put(loc, System.currentTimeMillis());
|
||||
|
||||
world.spawnParticle(Particle.FIREWORK, loc.clone().add(0.5, 1.0, 0.5),
|
||||
20, 0.3, 0.5, 0.3);
|
||||
world.playSound(loc, Sound.BLOCK_CHEST_OPEN, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
private void fillChestWithRandomLoot(Inventory inv) {
|
||||
inv.clear();
|
||||
Random random = new Random();
|
||||
for (LootItem lootItem : lootItems) {
|
||||
if (lootItem.shouldSpawn(random)) {
|
||||
inv.addItem(lootItem.createStack(random));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (!(sender instanceof Player p)) {
|
||||
sender.sendMessage(color(plugin.getLangConfig().getString("lootchest.player-only", "")));
|
||||
return true;
|
||||
}
|
||||
if (!p.hasPermission("survivalplus.lootchests")) {
|
||||
p.sendMessage(color(plugin.getLangConfig().getString("lootchest.no-permission", "")));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cmd.getName().equalsIgnoreCase("lootchests")) {
|
||||
if (activeChests.isEmpty()) {
|
||||
p.sendMessage(color(plugin.getLangConfig().getString("lootchest.no-chests", "")));
|
||||
return true;
|
||||
}
|
||||
p.sendMessage(color(plugin.getLangConfig().getString("lootchest.list-header", "")));
|
||||
for (Location loc : activeChests) {
|
||||
String coords = loc.getBlockX() + " " + loc.getBlockY() + " " + loc.getBlockZ();
|
||||
net.md_5.bungee.api.chat.TextComponent msg =
|
||||
new net.md_5.bungee.api.chat.TextComponent(ChatColor.AQUA + " - " + coords + " " + ChatColor.GREEN + "[TP]");
|
||||
msg.setClickEvent(new net.md_5.bungee.api.chat.ClickEvent(
|
||||
net.md_5.bungee.api.chat.ClickEvent.Action.RUN_COMMAND,
|
||||
"/tploot " + loc.getWorld().getName() + " " + loc.getBlockX()
|
||||
+ " " + loc.getBlockY() + " " + loc.getBlockZ()
|
||||
));
|
||||
msg.setHoverEvent(new net.md_5.bungee.api.chat.HoverEvent(
|
||||
net.md_5.bungee.api.chat.HoverEvent.Action.SHOW_TEXT,
|
||||
new net.md_5.bungee.api.chat.ComponentBuilder(color(
|
||||
plugin.getLangConfig().getString("lootchest.list-tp-hover", "")
|
||||
)).create()
|
||||
));
|
||||
p.spigot().sendMessage(msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cmd.getName().equalsIgnoreCase("tploot")) {
|
||||
if (!p.isOp() && !p.hasPermission("survivalplus.lootchests")) return true;
|
||||
if (args.length != 4) {
|
||||
p.sendMessage(color(plugin.getLangConfig().getString("lootchest.tp-usage", "")));
|
||||
return true;
|
||||
}
|
||||
World w = Bukkit.getWorld(args[0]);
|
||||
if (w == null) {
|
||||
p.sendMessage(color(plugin.getLangConfig().getString("lootchest.tp-world-not-found", "")));
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
double x = Double.parseDouble(args[1]);
|
||||
double y = Double.parseDouble(args[2]);
|
||||
double z = Double.parseDouble(args[3]);
|
||||
p.teleport(new Location(w, x + 0.5, y, z + 0.5));
|
||||
p.sendMessage(color(plugin.getLangConfig().getString("lootchest.tp-success", "")));
|
||||
} catch (NumberFormatException e) {
|
||||
p.sendMessage(color(plugin.getLangConfig().getString("lootchest.tp-invalid-coords", "")));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryOpen(InventoryOpenEvent event) {
|
||||
if (!(event.getPlayer() instanceof Player player)) return;
|
||||
InventoryHolder holder = event.getInventory().getHolder();
|
||||
if (!(holder instanceof Chest chest)) return;
|
||||
|
||||
if (activeChests.contains(chest.getLocation())) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
int looted = playerLootCount.getOrDefault(uuid, 0);
|
||||
if (looted >= maxLootPerPlayer) {
|
||||
player.sendMessage(color(plugin.getLangConfig().getString("lootchest.limit-reached", "&cDu hast dein Loot-Limit erreicht!")));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent event) {
|
||||
if (!(event.getPlayer() instanceof Player player)) return;
|
||||
InventoryHolder holder = event.getInventory().getHolder();
|
||||
if (!(holder instanceof Chest chest)) return;
|
||||
|
||||
Location chestLoc = chest.getLocation();
|
||||
if (activeChests.contains(chestLoc) && isInventoryEmpty(event.getInventory())) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
int looted = playerLootCount.getOrDefault(uuid, 0);
|
||||
if (looted >= maxLootPerPlayer) return;
|
||||
playerLootCount.put(uuid, looted + 1);
|
||||
chestLoc.getBlock().setType(Material.AIR);
|
||||
activeChests.remove(chestLoc);
|
||||
chestSpawnTimes.remove(chestLoc);
|
||||
Bukkit.broadcastMessage(color(
|
||||
plugin.getLangConfig().getString("lootchest.removed-msg", "&aEine Lootkiste wurde geleert und entfernt.")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInventoryEmpty(Inventory inventory) {
|
||||
for (ItemStack item : inventory.getContents()) {
|
||||
if (item != null && item.getType() != Material.AIR) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String color(String msg) {
|
||||
return ChatColor.translateAlternateColorCodes('&', msg == null ? "" : msg);
|
||||
}
|
||||
|
||||
private static class LootItem {
|
||||
private final Material material;
|
||||
private final String name;
|
||||
private final Map<Enchantment, Integer> enchantments = new HashMap<>();
|
||||
private final double chance;
|
||||
private final int min;
|
||||
private final int max;
|
||||
|
||||
LootItem(FileConfiguration cfg, String path) {
|
||||
material = Material.valueOf(cfg.getString(path + ".material", "STONE"));
|
||||
name = cfg.getString(path + ".name", null);
|
||||
chance = cfg.getDouble(path + ".chance", 1.0);
|
||||
min = cfg.getInt(path + ".min", 1);
|
||||
max = cfg.getInt(path + ".max", 1);
|
||||
if (cfg.isConfigurationSection(path + ".enchantments")) {
|
||||
for (String enchKey : cfg.getConfigurationSection(path + ".enchantments").getKeys(false)) {
|
||||
Enchantment ench = Enchantment.getByName(enchKey.toUpperCase());
|
||||
if (ench != null) {
|
||||
enchantments.put(ench, cfg.getInt(path + ".enchantments." + enchKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean shouldSpawn(Random r) { return r.nextDouble() <= chance; }
|
||||
ItemStack createStack(Random r) {
|
||||
int amt = min + r.nextInt(max - min + 1);
|
||||
ItemStack stack = new ItemStack(material, amt);
|
||||
ItemMeta meta = stack.getItemMeta();
|
||||
if (name != null) meta.setDisplayName(ChatColor.translateAlternateColorCodes('&', name));
|
||||
stack.setItemMeta(meta);
|
||||
for (Map.Entry<Enchantment, Integer> e : enchantments.entrySet()) {
|
||||
stack.addUnsafeEnchantment(e.getKey(), e.getValue());
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
package de.viper.survivalplus.report;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ReportManager {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final File reportFile;
|
||||
private FileConfiguration reportConfig;
|
||||
|
||||
public ReportManager(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
this.reportFile = new File(plugin.getDataFolder(), "reports.yml");
|
||||
if (!reportFile.exists()) {
|
||||
try {
|
||||
reportFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().severe("Konnte reports.yml nicht erstellen!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
this.reportConfig = YamlConfiguration.loadConfiguration(reportFile);
|
||||
}
|
||||
|
||||
public void addReport(String reportedPlayer, String reporter, String reason, String time) {
|
||||
String path = "reports." + reportedPlayer;
|
||||
List<String> reports = reportConfig.getStringList(path);
|
||||
reports.add(time + " - Von: " + reporter + " | Grund: " + reason);
|
||||
reportConfig.set(path, reports);
|
||||
saveReports();
|
||||
}
|
||||
|
||||
public List<String> getReports(String reportedPlayer) {
|
||||
return reportConfig.getStringList("reports." + reportedPlayer);
|
||||
}
|
||||
|
||||
public void clearReports(String reportedPlayer) {
|
||||
reportConfig.set("reports." + reportedPlayer, null);
|
||||
saveReports();
|
||||
}
|
||||
|
||||
private void saveReports() {
|
||||
try {
|
||||
reportConfig.save(reportFile);
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().severe("Fehler beim Speichern der reports.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
70
src/main/java/de/viper/survivalplus/Manager/ShopManager.java
Normal file
70
src/main/java/de/viper/survivalplus/Manager/ShopManager.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package de.viper.survivalplus.Manager;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ShopManager {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final File shopFile;
|
||||
private final FileConfiguration shopConfig;
|
||||
|
||||
public ShopManager(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
this.shopFile = new File(plugin.getDataFolder(), "shop.yml");
|
||||
|
||||
if (!shopFile.exists()) {
|
||||
plugin.saveResource("shop.yml", false);
|
||||
}
|
||||
|
||||
this.shopConfig = YamlConfiguration.loadConfiguration(shopFile);
|
||||
}
|
||||
|
||||
public double getCurrentPrice(String itemKey) {
|
||||
return shopConfig.getDouble("items." + itemKey + ".current-price", 0);
|
||||
}
|
||||
|
||||
public boolean buyItem(String itemKey, int amount) {
|
||||
int stock = shopConfig.getInt("items." + itemKey + ".stock", 0);
|
||||
if (stock < amount) {
|
||||
return false;
|
||||
}
|
||||
double price = shopConfig.getDouble("items." + itemKey + ".current-price", 0);
|
||||
shopConfig.set("items." + itemKey + ".stock", stock - amount);
|
||||
shopConfig.set("items." + itemKey + ".current-price", price * 0.95);
|
||||
saveShop();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void sellItem(String itemKey, int amount) {
|
||||
int stock = shopConfig.getInt("items." + itemKey + ".stock", 0);
|
||||
double price = shopConfig.getDouble("items." + itemKey + ".current-price", 0);
|
||||
shopConfig.set("items." + itemKey + ".stock", stock + amount);
|
||||
shopConfig.set("items." + itemKey + ".current-price", price * 0.95);
|
||||
saveShop();
|
||||
}
|
||||
|
||||
public void addOrUpdateItem(String itemKey, double basePrice, int stock) {
|
||||
shopConfig.set("items." + itemKey + ".base-price", basePrice);
|
||||
shopConfig.set("items." + itemKey + ".stock", stock);
|
||||
shopConfig.set("items." + itemKey + ".current-price", basePrice);
|
||||
saveShop();
|
||||
}
|
||||
|
||||
private void saveShop() {
|
||||
try {
|
||||
shopConfig.save(shopFile);
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().severe("Fehler beim Speichern von shop.yml");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public FileConfiguration getShopConfig() {
|
||||
return shopConfig;
|
||||
}
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
package de.viper.survivalplus.Manager;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class StatsManager {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private File statsFile;
|
||||
private FileConfiguration statsConfig;
|
||||
|
||||
public StatsManager(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
createStatsFile();
|
||||
}
|
||||
|
||||
private void createStatsFile() {
|
||||
statsFile = new File(plugin.getDataFolder(), "stats.yml");
|
||||
if (!statsFile.exists()) {
|
||||
plugin.saveResource("stats.yml", false);
|
||||
}
|
||||
statsConfig = YamlConfiguration.loadConfiguration(statsFile);
|
||||
}
|
||||
|
||||
public void saveStats() {
|
||||
try {
|
||||
statsConfig.save(statsFile);
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().severe("Fehler beim Speichern der stats.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Spielzeit in Sekunden addieren
|
||||
public void addPlayTime(UUID playerUUID, long seconds) {
|
||||
long current = statsConfig.getLong(playerUUID + ".playtime", 0);
|
||||
statsConfig.set(playerUUID + ".playtime", current + seconds);
|
||||
}
|
||||
|
||||
// Kills addieren
|
||||
public void addKills(UUID playerUUID, int amount) {
|
||||
int current = statsConfig.getInt(playerUUID + ".kills", 0);
|
||||
statsConfig.set(playerUUID + ".kills", current + amount);
|
||||
}
|
||||
|
||||
// Tode addieren
|
||||
public void addDeaths(UUID playerUUID, int amount) {
|
||||
int current = statsConfig.getInt(playerUUID + ".deaths", 0);
|
||||
statsConfig.set(playerUUID + ".deaths", current + amount);
|
||||
}
|
||||
|
||||
// Abgebaute Blöcke addieren
|
||||
public void addBlocksBroken(UUID playerUUID, int amount) {
|
||||
int current = statsConfig.getInt(playerUUID + ".blocks_broken", 0);
|
||||
statsConfig.set(playerUUID + ".blocks_broken", current + amount);
|
||||
}
|
||||
|
||||
// Platzierte Blöcke addieren
|
||||
public void addBlocksPlaced(UUID playerUUID, int amount) {
|
||||
int current = statsConfig.getInt(playerUUID + ".blocks_placed", 0);
|
||||
statsConfig.set(playerUUID + ".blocks_placed", current + amount);
|
||||
}
|
||||
|
||||
// Getter für Statistikwerte
|
||||
|
||||
public long getPlayTime(UUID playerUUID) {
|
||||
return statsConfig.getLong(playerUUID + ".playtime", 0);
|
||||
}
|
||||
|
||||
public int getKills(UUID playerUUID) {
|
||||
return statsConfig.getInt(playerUUID + ".kills", 0);
|
||||
}
|
||||
|
||||
public int getDeaths(UUID playerUUID) {
|
||||
return statsConfig.getInt(playerUUID + ".deaths", 0);
|
||||
}
|
||||
|
||||
public int getBlocksBroken(UUID playerUUID) {
|
||||
return statsConfig.getInt(playerUUID + ".blocks_broken", 0);
|
||||
}
|
||||
|
||||
public int getBlocksPlaced(UUID playerUUID) {
|
||||
return statsConfig.getInt(playerUUID + ".blocks_placed", 0);
|
||||
}
|
||||
|
||||
}
|
327
src/main/java/de/viper/survivalplus/Manager/TablistManager.java
Normal file
327
src/main/java/de/viper/survivalplus/Manager/TablistManager.java
Normal file
@@ -0,0 +1,327 @@
|
||||
package de.viper.survivalplus.Manager;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import net.luckperms.api.LuckPerms;
|
||||
import net.luckperms.api.LuckPermsProvider;
|
||||
import net.luckperms.api.model.user.User;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class TablistManager {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final List<String> headerAnim = new ArrayList<>();
|
||||
private final List<String> footerAnim = new ArrayList<>();
|
||||
private int headerIndex = 0;
|
||||
private int footerIndex = 0;
|
||||
private boolean enabled;
|
||||
private String serverName;
|
||||
private String website;
|
||||
private String teamspeakAddress;
|
||||
private String discordAddress;
|
||||
private boolean showTeamspeak;
|
||||
private boolean showDiscord;
|
||||
private String staffPermission;
|
||||
private String separatorLine;
|
||||
private LuckPerms luckPerms;
|
||||
|
||||
public TablistManager(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
// Resource sicherstellen, Config laden
|
||||
try { plugin.saveResource("tablist.yml", false); } catch (Exception ignored) {}
|
||||
try { plugin.reloadTablistConfig(); } catch (Throwable ignored) {}
|
||||
FileConfiguration config = plugin.getTablistConfig();
|
||||
|
||||
// Konfigurationswerte laden
|
||||
this.enabled = config.getBoolean("enabled", true);
|
||||
this.serverName = config.getString("server-name", "SurvivalPlus");
|
||||
this.website = config.getString("website", "www.example.com");
|
||||
this.teamspeakAddress = config.getString("teamspeak-address", "ts.example.com");
|
||||
this.discordAddress = config.getString("discord-address", "discord.gg/example");
|
||||
this.showTeamspeak = config.getBoolean("show-teamspeak", true);
|
||||
this.showDiscord = config.getBoolean("show-discord", true);
|
||||
this.staffPermission = config.getString("staff-permission", "survivalplus.staff");
|
||||
this.separatorLine = config.getString("separator-line", "&8&l&m================");
|
||||
|
||||
// LuckPerms API initialisieren
|
||||
try {
|
||||
this.luckPerms = LuckPermsProvider.get();
|
||||
} catch (IllegalStateException e) {
|
||||
plugin.getLogger().warning("LuckPerms nicht gefunden! Versuche Fallback auf PlaceholderAPI.");
|
||||
}
|
||||
|
||||
// Prüfen, ob PlaceholderAPI verfügbar ist
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
||||
plugin.getLogger().warning("PlaceholderAPI nicht gefunden! Verwende Standard-Prefix als Fallback.");
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
plugin.getLogger().info("Tablist ist deaktiviert (tablist.yml -> enabled: false)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Header- und Footer-Animationen füllen
|
||||
List<String> configHeader = config.getStringList("header-animations");
|
||||
List<String> configFooter = config.getStringList("footer-animations");
|
||||
|
||||
if (configHeader != null && !configHeader.isEmpty()) {
|
||||
headerAnim.addAll(configHeader);
|
||||
} else {
|
||||
headerAnim.add("&6&l{server}\n&7Willkommen, &a{player}\n&7Online Player: &e{online}\n&6Online Staff: &e{staff}\n");
|
||||
}
|
||||
|
||||
if (configFooter != null && !configFooter.isEmpty()) {
|
||||
footerAnim.addAll(configFooter);
|
||||
} else {
|
||||
footerAnim.add("&7SurvivalPlus &8| &eDein Abenteuer!");
|
||||
}
|
||||
|
||||
startAnimation();
|
||||
}
|
||||
|
||||
private void startAnimation() {
|
||||
if (!enabled) return;
|
||||
|
||||
int interval = Math.max(1, plugin.getTablistConfig().getInt("interval-ticks", 20));
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (headerAnim.isEmpty() || footerAnim.isEmpty()) return;
|
||||
|
||||
// Online-Spieler und Staff zählen
|
||||
int onlinePlayers = Bukkit.getOnlinePlayers().size();
|
||||
int onlineStaff = (int) Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p.hasPermission(staffPermission))
|
||||
.count();
|
||||
|
||||
// Aktuelles Datum und Uhrzeit formatieren
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
|
||||
String currentTime = dateFormat.format(new Date());
|
||||
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
try {
|
||||
// Spieler-Prefix abrufen (LuckPerms primär, PlaceholderAPI als Fallback)
|
||||
String prefix = getPlayerPrefix(player);
|
||||
int ping = getPlayerPing(player);
|
||||
// Korrigierte Formatierung: Gesamten String durch color-Methode leiten
|
||||
String prefixedName = color(prefix + player.getName() + "&8 | &e" + ping + "ms");
|
||||
player.setPlayerListName(prefixedName);
|
||||
|
||||
// Header mit Spielername und Statistiken
|
||||
String headerRaw = headerAnim.get(headerIndex)
|
||||
.replace("{server}", serverName)
|
||||
.replace("{player}", player.getName())
|
||||
.replace("{online}", String.valueOf(onlinePlayers))
|
||||
.replace("{staff}", String.valueOf(onlineStaff));
|
||||
String footerRaw = footerAnim.get(footerIndex);
|
||||
|
||||
// Footer zusammenstellen: TS und Discord nebeneinander, Webseite zentriert
|
||||
StringBuilder footerBuilder = new StringBuilder();
|
||||
footerBuilder.append("\n"); // Extra Abstand
|
||||
footerBuilder.append(color(footerRaw)).append("\n");
|
||||
|
||||
footerBuilder.append(color(separatorLine)).append("\n");
|
||||
if (showTeamspeak || showDiscord) {
|
||||
StringBuilder socialLine = new StringBuilder();
|
||||
if (showTeamspeak) {
|
||||
socialLine.append("&7TS: &a").append(teamspeakAddress);
|
||||
}
|
||||
if (showTeamspeak && showDiscord) {
|
||||
socialLine.append(" &8| ");
|
||||
}
|
||||
if (showDiscord) {
|
||||
socialLine.append("&7Discord: &d").append(discordAddress);
|
||||
}
|
||||
footerBuilder.append(color(socialLine.toString())).append("\n");
|
||||
}
|
||||
footerBuilder.append(" &7Webseite: &b").append(website).append("\n");
|
||||
footerBuilder.append(color(separatorLine)).append("\n");
|
||||
footerBuilder.append("&7Datum & Uhrzeit: &e").append(currentTime);
|
||||
|
||||
String header = color(headerRaw);
|
||||
String footer = color(footerBuilder.toString());
|
||||
|
||||
// 1) Adventure (Component) Variante
|
||||
boolean done = tryAdventureComponent(player, headerRaw, footerBuilder.toString());
|
||||
|
||||
// 2) String-Variante fallback
|
||||
if (!done) {
|
||||
done = tryStringMethod(player, header, footer);
|
||||
}
|
||||
|
||||
// 3) Wenn alles fehlschlägt -> Log
|
||||
if (!done) {
|
||||
plugin.getLogger().warning("Tablist: Keine geeignete Methode gefunden für Spieler " + player.getName());
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
plugin.getLogger().log(Level.FINE, "Fehler beim Setzen der Tablist für Spieler " + player.getName(), t);
|
||||
}
|
||||
}
|
||||
|
||||
headerIndex = (headerIndex + 1) % headerAnim.size();
|
||||
footerIndex = (footerIndex + 1) % footerAnim.size();
|
||||
}
|
||||
}.runTaskTimer(plugin, 0L, interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spieler-Prefix abrufen (LuckPerms primär, PlaceholderAPI als Fallback)
|
||||
*/
|
||||
private String getPlayerPrefix(Player player) {
|
||||
// Versuche LuckPerms-API zuerst
|
||||
if (luckPerms != null) {
|
||||
try {
|
||||
User user = luckPerms.getPlayerAdapter(Player.class).getUser(player);
|
||||
String prefix = user.getCachedData().getMetaData().getPrefix();
|
||||
return (prefix == null || prefix.isEmpty()) ? "&7[Spieler] " : prefix + " ";
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.FINE, "Fehler beim Abrufen des Prefix aus LuckPerms für Spieler " + player.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback auf PlaceholderAPI
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
||||
String prefix = PlaceholderAPI.setPlaceholders(player, "%luckperms_prefix%");
|
||||
return (prefix == null || prefix.isEmpty()) ? "&7[Spieler] " : prefix + " ";
|
||||
}
|
||||
|
||||
// Letzter Fallback: Standard-Prefix
|
||||
return "&7[Spieler] ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Spieler-Ping abrufen
|
||||
*/
|
||||
private int getPlayerPing(Player player) {
|
||||
try {
|
||||
Method getHandle = player.getClass().getMethod("getHandle");
|
||||
Object entityPlayer = getHandle.invoke(player);
|
||||
return entityPlayer.getClass().getField("ping").getInt(entityPlayer);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.FINE, "Fehler beim Abrufen des Pings für Spieler " + player.getName(), e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adventure-Variante mit Components
|
||||
*/
|
||||
private boolean tryAdventureComponent(Player player, String headerRaw, String footerRaw) {
|
||||
try {
|
||||
Class<?> compClass = Class.forName("net.kyori.adventure.text.Component");
|
||||
Method textMethod = null;
|
||||
try {
|
||||
textMethod = compClass.getMethod("text", CharSequence.class);
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
try { textMethod = compClass.getMethod("text", String.class); } catch (NoSuchMethodException ignored2) {}
|
||||
}
|
||||
|
||||
Object headerComp = null;
|
||||
Object footerComp = null;
|
||||
|
||||
if (textMethod != null) {
|
||||
headerComp = textMethod.invoke(null, color(headerRaw));
|
||||
footerComp = textMethod.invoke(null, color(footerRaw));
|
||||
} else {
|
||||
// Fallback: MiniMessage
|
||||
try {
|
||||
Class<?> miniMsgClass = Class.forName("net.kyori.adventure.text.minimessage.MiniMessage");
|
||||
Method miniMsgSingleton = miniMsgClass.getMethod("miniMessage");
|
||||
Object miniMsg = miniMsgSingleton.invoke(null);
|
||||
Method deserialize = miniMsgClass.getMethod("deserialize", String.class);
|
||||
headerComp = deserialize.invoke(miniMsg, headerRaw);
|
||||
footerComp = deserialize.invoke(miniMsg, footerRaw);
|
||||
} catch (Throwable t) {
|
||||
// kein MiniMessage
|
||||
}
|
||||
}
|
||||
|
||||
if (headerComp == null || footerComp == null) return false;
|
||||
|
||||
Method m = findMethod(player.getClass(), "sendPlayerListHeaderAndFooter", compClass, compClass);
|
||||
if (m == null) m = findMethod(player.getClass(), "setPlayerListHeaderFooter", compClass, compClass);
|
||||
|
||||
if (m != null) {
|
||||
m.invoke(player, headerComp, footerComp);
|
||||
return true;
|
||||
} else {
|
||||
Method mh = findMethod(player.getClass(), "sendPlayerListHeader", compClass);
|
||||
Method mf = findMethod(player.getClass(), "sendPlayerListFooter", compClass);
|
||||
if (mh != null && mf != null) {
|
||||
mh.invoke(player, headerComp);
|
||||
mf.invoke(player, footerComp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException cnf) {
|
||||
return false;
|
||||
} catch (Throwable t) {
|
||||
plugin.getLogger().log(Level.FINER, "Adventure-Variante fehlgeschlagen: " + t.getMessage());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* String-Variante
|
||||
*/
|
||||
private boolean tryStringMethod(Player player, String header, String footer) {
|
||||
try {
|
||||
Method m = findMethod(player.getClass(), "sendPlayerListHeaderFooter", String.class, String.class);
|
||||
if (m == null) {
|
||||
m = findMethod(player.getClass(), "setPlayerListHeaderFooter", String.class, String.class);
|
||||
}
|
||||
if (m != null) {
|
||||
m.invoke(player, header, footer);
|
||||
return true;
|
||||
}
|
||||
|
||||
Method mh = findMethod(player.getClass(), "sendPlayerListHeader", String.class);
|
||||
Method mf = findMethod(player.getClass(), "sendPlayerListFooter", String.class);
|
||||
if (mh != null && mf != null) {
|
||||
mh.invoke(player, header);
|
||||
mf.invoke(player, footer);
|
||||
return true;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
plugin.getLogger().log(Level.FINER, "String-Variante fehlgeschlagen: " + t.getMessage());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hilfsmethode für Reflection
|
||||
*/
|
||||
private Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
|
||||
Class<?> current = clazz;
|
||||
while (current != null) {
|
||||
try {
|
||||
Method m = current.getMethod(name, paramTypes);
|
||||
if (m != null) return m;
|
||||
} catch (NoSuchMethodException ignored) { }
|
||||
current = current.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Farbcode-Konvertierung (& -> §)
|
||||
*/
|
||||
private String color(String msg) {
|
||||
if (msg == null) return "";
|
||||
return msg.replace("&", "§");
|
||||
}
|
||||
}
|
44
src/main/java/de/viper/survivalplus/Manager/Warp.java
Normal file
44
src/main/java/de/viper/survivalplus/Manager/Warp.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package de.viper.survivalplus.Manager;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class Warp {
|
||||
|
||||
private final String owner;
|
||||
private final String name;
|
||||
private final ItemStack item;
|
||||
private final String worldName;
|
||||
private final double x, y, z;
|
||||
|
||||
public Warp(String owner, String name, ItemStack item, String worldName, double x, double y, double z) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.item = item;
|
||||
this.worldName = worldName;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public ItemStack getItem() {
|
||||
return item;
|
||||
}
|
||||
public String getWorldName() {
|
||||
return worldName;
|
||||
}
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
}
|
113
src/main/java/de/viper/survivalplus/Manager/WarpManager.java
Normal file
113
src/main/java/de/viper/survivalplus/Manager/WarpManager.java
Normal file
@@ -0,0 +1,113 @@
|
||||
package de.viper.survivalplus.Manager;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class WarpManager {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private File warpsFile;
|
||||
private FileConfiguration warpsConfig;
|
||||
|
||||
private final Map<String, Warp> warps = new HashMap<>(); // key: owner:name
|
||||
|
||||
public WarpManager(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
loadWarpsFile();
|
||||
loadWarps();
|
||||
}
|
||||
|
||||
private void loadWarpsFile() {
|
||||
warpsFile = new File(plugin.getDataFolder(), "warps.yml");
|
||||
if (!warpsFile.exists()) {
|
||||
plugin.saveResource("warps.yml", false);
|
||||
}
|
||||
warpsConfig = YamlConfiguration.loadConfiguration(warpsFile);
|
||||
}
|
||||
|
||||
public void saveWarpsFile() {
|
||||
try {
|
||||
warpsConfig.save(warpsFile);
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().severe("Konnte warps.yml nicht speichern!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadWarps() {
|
||||
warps.clear();
|
||||
if (warpsConfig.contains("warps")) {
|
||||
for (String key : warpsConfig.getConfigurationSection("warps").getKeys(false)) {
|
||||
String path = "warps." + key;
|
||||
String owner = warpsConfig.getString(path + ".owner");
|
||||
String name = warpsConfig.getString(path + ".name");
|
||||
ItemStack item = warpsConfig.getItemStack(path + ".item");
|
||||
double x = warpsConfig.getDouble(path + ".location.x");
|
||||
double y = warpsConfig.getDouble(path + ".location.y");
|
||||
double z = warpsConfig.getDouble(path + ".location.z");
|
||||
String worldName = warpsConfig.getString(path + ".location.world");
|
||||
|
||||
Warp warp = new Warp(owner, name, item, worldName, x, y, z);
|
||||
warps.put(owner + ":" + name, warp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addWarp(Warp warp) {
|
||||
warps.put(warp.getOwner() + ":" + warp.getName(), warp);
|
||||
saveWarpToConfig(warp);
|
||||
saveWarpsFile();
|
||||
}
|
||||
|
||||
private void saveWarpToConfig(Warp warp) {
|
||||
String path = "warps." + warp.getOwner() + "_" + warp.getName();
|
||||
warpsConfig.set(path + ".owner", warp.getOwner());
|
||||
warpsConfig.set(path + ".name", warp.getName());
|
||||
warpsConfig.set(path + ".item", warp.getItem());
|
||||
warpsConfig.set(path + ".location.x", warp.getX());
|
||||
warpsConfig.set(path + ".location.y", warp.getY());
|
||||
warpsConfig.set(path + ".location.z", warp.getZ());
|
||||
warpsConfig.set(path + ".location.world", warp.getWorldName());
|
||||
}
|
||||
|
||||
public Map<String, Warp> getWarps() {
|
||||
return warps;
|
||||
}
|
||||
|
||||
public Warp getWarp(String owner, String name) {
|
||||
return warps.get(owner + ":" + name);
|
||||
}
|
||||
|
||||
// Neu hinzugefügt: Anzahl der Warps eines Spielers zählen
|
||||
public int getWarpCountForPlayer(String playerName) {
|
||||
int count = 0;
|
||||
for (Warp warp : warps.values()) {
|
||||
if (warp.getOwner().equalsIgnoreCase(playerName)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Neu hinzugefügt: Warp eines Spielers löschen
|
||||
public boolean removeWarp(String owner, String name) {
|
||||
String key = owner + ":" + name;
|
||||
if (!warps.containsKey(key)) {
|
||||
return false;
|
||||
}
|
||||
warps.remove(key);
|
||||
|
||||
String path = "warps." + owner + "_" + name;
|
||||
warpsConfig.set(path, null); // Eintrag in Config entfernen
|
||||
saveWarpsFile();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
931
src/main/java/de/viper/survivalplus/SurvivalPlus.java
Normal file
931
src/main/java/de/viper/survivalplus/SurvivalPlus.java
Normal file
@@ -0,0 +1,931 @@
|
||||
package de.viper.survivalplus;
|
||||
|
||||
import de.viper.survivalplus.commands.*;
|
||||
import de.viper.survivalplus.listeners.*;
|
||||
import de.viper.survivalplus.report.ReportManager;
|
||||
import de.viper.survivalplus.trade.TradeManager;
|
||||
import de.viper.survivalplus.listeners.DebugArmorStandListener;
|
||||
import de.viper.survivalplus.listeners.ArmorStandDestroyListener;
|
||||
import de.viper.survivalplus.tasks.AutoClearTask;
|
||||
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 org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import de.viper.survivalplus.listeners.RepairSignListener;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
import de.viper.survivalplus.listeners.NickLoadListener;
|
||||
import de.viper.survivalplus.Manager.LootChestManager;
|
||||
import de.viper.survivalplus.commands.DayCommand;
|
||||
import de.viper.survivalplus.commands.NightCommand;
|
||||
import de.viper.survivalplus.commands.TradeCommand;
|
||||
import de.viper.survivalplus.commands.ReportCommand;
|
||||
import de.viper.survivalplus.Manager.ShopManager;
|
||||
import de.viper.survivalplus.commands.HealCommand;
|
||||
import de.viper.survivalplus.Manager.TablistManager;
|
||||
|
||||
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;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
|
||||
public class SurvivalPlus extends JavaPlugin {
|
||||
|
||||
private File langFile;
|
||||
private FileConfiguration langConfig;
|
||||
private File homesFile;
|
||||
private FileConfiguration homesConfig;
|
||||
private File gravesFile;
|
||||
private FileConfiguration gravesConfig;
|
||||
private File helpFile;
|
||||
private FileConfiguration helpConfig;
|
||||
private File backpackFile;
|
||||
private FileConfiguration backpackConfig;
|
||||
private File friendsFile;
|
||||
private FileConfiguration friendsConfig;
|
||||
private File leashesFile;
|
||||
private FileConfiguration leashesConfig;
|
||||
private File mobCapFile;
|
||||
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;
|
||||
private OreAlarmListener oreAlarmListener;
|
||||
private AFKListener afkListener;
|
||||
private GraveListener graveListener;
|
||||
private SitListener sitListener;
|
||||
private PlayerJoinListener playerJoinListener;
|
||||
private FunChallengeManager challengeManager;
|
||||
private NamespacedKey droppedKey;
|
||||
private Map<UUID, Integer> progressMap = new HashMap<>();
|
||||
|
||||
// WarpManager als Feld
|
||||
private WarpManager warpManager;
|
||||
|
||||
// FunChallengeManager als Feld
|
||||
private FunChallengeManager funChallengeManager;
|
||||
|
||||
// ------------------- 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
|
||||
}
|
||||
tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
|
||||
}
|
||||
|
||||
public FileConfiguration getTablistConfig() {
|
||||
// Stellt sicher, dass die Config geladen ist
|
||||
if (tablistConfig == null) {
|
||||
reloadTablistConfig();
|
||||
}
|
||||
return tablistConfig;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Default-Config sicherstellen
|
||||
saveDefaultConfig();
|
||||
|
||||
// bStats initialisieren
|
||||
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")
|
||||
));
|
||||
|
||||
// Konfigurationen/Dateien laden
|
||||
updateConfigFiles();
|
||||
createHomesFile();
|
||||
createGravesFile();
|
||||
createBackpackFile();
|
||||
createFriendsFile();
|
||||
createLeashesFile();
|
||||
createMobCapFile();
|
||||
createNicknamesFile();
|
||||
|
||||
// PluginManager holen (vor Listener-Registrierung!)
|
||||
PluginManager pluginManager = getServer().getPluginManager();
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
// 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));
|
||||
|
||||
// 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 lockSystem = new LockSystem(this);
|
||||
pluginManager.registerEvents(lockSystem, this);
|
||||
getCommand("sp").setExecutor(lockSystem);
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
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 (hadStructureBlock) {
|
||||
admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
|
||||
ChatColor.RED + " hatte einen Structure-Block im Inventar, der entfernt wurde.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Methoden für nicknames.yml
|
||||
public void createNicknamesFile() {
|
||||
nicknamesFile = new File(getDataFolder(), "nicknames.yml");
|
||||
if (!nicknamesFile.exists()) {
|
||||
try {
|
||||
nicknamesFile.getParentFile().mkdirs();
|
||||
nicknamesFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Konnte nicknames.yml nicht erstellen!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
nicknamesConfig = YamlConfiguration.loadConfiguration(nicknamesFile);
|
||||
}
|
||||
|
||||
public FileConfiguration getNicknamesConfig() {
|
||||
return nicknamesConfig;
|
||||
}
|
||||
|
||||
public void saveNicknamesConfig() {
|
||||
try {
|
||||
nicknamesConfig.save(nicknamesFile);
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Konnte nicknames.yml nicht speichern!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnArmorStandExample() {
|
||||
World world = Bukkit.getWorld("world");
|
||||
if (world == null) {
|
||||
getLogger().warning("Welt 'world' nicht gefunden, ArmorStand wird nicht gespawnt.");
|
||||
return;
|
||||
}
|
||||
|
||||
Location loc = new Location(world, 0.5, 100, 0.5);
|
||||
ArmorStand armorStand = world.spawn(loc, ArmorStand.class);
|
||||
armorStand.setVisible(false);
|
||||
armorStand.setCustomName(ChatColor.GREEN + "Mein ArmorStand");
|
||||
armorStand.setCustomNameVisible(true);
|
||||
armorStand.setGravity(false);
|
||||
armorStand.setMarker(true);
|
||||
armorStand.addScoreboardTag("debugArmorStand");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (autoClearTaskId != -1) {
|
||||
Bukkit.getScheduler().cancelTask(autoClearTaskId);
|
||||
}
|
||||
saveStats();
|
||||
saveLeashesConfig();
|
||||
saveMobCapConfig();
|
||||
|
||||
// NEU: NewbieProtection-Daten sichern
|
||||
if (newbieListener != null) {
|
||||
newbieListener.saveData();
|
||||
}
|
||||
|
||||
getLogger().info(getMessage("plugin.disabled"));
|
||||
}
|
||||
|
||||
|
||||
public void saveStats() {
|
||||
if (statsManager != null) {
|
||||
statsManager.saveStats();
|
||||
}
|
||||
}
|
||||
|
||||
public String getPluginInfo() {
|
||||
return ChatColor.translateAlternateColorCodes('&', getMessage("plugin.info"));
|
||||
}
|
||||
|
||||
// === Config Updating Logic ===
|
||||
private void updateConfigFiles() {
|
||||
updateConfigFile("config.yml");
|
||||
updateConfigFile("lang.yml");
|
||||
updateConfigFile("help.yml");
|
||||
}
|
||||
|
||||
private void updateConfigFile(String fileName) {
|
||||
File file = new File(getDataFolder(), fileName);
|
||||
FileConfiguration currentConfig = YamlConfiguration.loadConfiguration(file);
|
||||
InputStream defaultStream = getResource(fileName);
|
||||
|
||||
if (defaultStream == null) {
|
||||
getLogger().warning(fileName + " nicht im JAR gefunden. Erstelle leere Datei.");
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
file.createNewFile();
|
||||
if (fileName.equals("config.yml")) {
|
||||
saveDefaultConfig();
|
||||
} else if (fileName.equals("lang.yml")) {
|
||||
createLangFile();
|
||||
} else if (fileName.equals("help.yml")) {
|
||||
createHelpFile();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Fehler beim Erstellen der " + fileName + ": " + e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FileConfiguration defaultConfig = defaultStream != null ?
|
||||
YamlConfiguration.loadConfiguration(new InputStreamReader(defaultStream)) : new YamlConfiguration();
|
||||
|
||||
// Merge default config into current config
|
||||
mergeConfigs(defaultConfig, currentConfig);
|
||||
|
||||
// Save updated config
|
||||
try {
|
||||
currentConfig.save(file);
|
||||
getLogger().info(fileName + " erfolgreich aktualisiert.");
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Fehler beim Speichern der " + fileName + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
// Update instance variables
|
||||
if (fileName.equals("config.yml")) {
|
||||
reloadConfig();
|
||||
} else if (fileName.equals("lang.yml")) {
|
||||
langFile = file;
|
||||
langConfig = currentConfig;
|
||||
} else if (fileName.equals("help.yml")) {
|
||||
helpFile = file;
|
||||
helpConfig = currentConfig;
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeConfigs(FileConfiguration defaultConfig, FileConfiguration currentConfig) {
|
||||
for (String key : defaultConfig.getKeys(true)) {
|
||||
if (!currentConfig.contains(key)) {
|
||||
currentConfig.set(key, defaultConfig.get(key));
|
||||
} else if (defaultConfig.isConfigurationSection(key) && currentConfig.isConfigurationSection(key)) {
|
||||
// Rekursiv für Untersektionen
|
||||
mergeConfigs(defaultConfig.getConfigurationSection(key), currentConfig.getConfigurationSection(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeConfigs(ConfigurationSection defaultSection, ConfigurationSection currentSection) {
|
||||
for (String key : defaultSection.getKeys(false)) {
|
||||
if (!currentSection.contains(key)) {
|
||||
currentSection.set(key, defaultSection.get(key));
|
||||
} else if (defaultSection.isConfigurationSection(key) && currentSection.isConfigurationSection(key)) {
|
||||
mergeConfigs(defaultSection.getConfigurationSection(key), currentSection.getConfigurationSection(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// === Lang.yml ===
|
||||
private void createLangFile() {
|
||||
langFile = new File(getDataFolder(), "lang.yml");
|
||||
if (!langFile.exists()) {
|
||||
saveResource("lang.yml", false);
|
||||
}
|
||||
langConfig = YamlConfiguration.loadConfiguration(langFile);
|
||||
}
|
||||
|
||||
public String getMessage(String key) {
|
||||
String message = langConfig.getString(key);
|
||||
if (message == null) {
|
||||
getLogger().warning("Fehlender Sprachschlüssel: " + key);
|
||||
return ChatColor.RED + "[Missing lang key: " + key + "]";
|
||||
}
|
||||
return ChatColor.translateAlternateColorCodes('&', message);
|
||||
}
|
||||
|
||||
public void reloadLangConfig() {
|
||||
updateConfigFile("lang.yml");
|
||||
}
|
||||
|
||||
public FileConfiguration getLangConfig() {
|
||||
return langConfig;
|
||||
}
|
||||
|
||||
// === Homes.yml ===
|
||||
private void createHomesFile() {
|
||||
homesFile = new File(getDataFolder(), "homes.yml");
|
||||
if (!homesFile.exists()) {
|
||||
try {
|
||||
homesFile.createNewFile();
|
||||
getLogger().info("homes.yml wurde erstellt.");
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Fehler beim Erstellen der homes.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
homesConfig = YamlConfiguration.loadConfiguration(homesFile);
|
||||
}
|
||||
|
||||
public FileConfiguration getHomesConfig() {
|
||||
return homesConfig;
|
||||
}
|
||||
|
||||
public void saveHomesConfig() {
|
||||
try {
|
||||
homesConfig.save(homesFile);
|
||||
getLogger().info("homes.yml erfolgreich gespeichert.");
|
||||
} catch (IOException e) {
|
||||
getLogger().log(Level.SEVERE, "Fehler beim Speichern der homes.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadHomesConfig() {
|
||||
homesConfig = YamlConfiguration.loadConfiguration(homesFile);
|
||||
getLogger().info("homes.yml erfolgreich neu geladen.");
|
||||
}
|
||||
|
||||
// === Graves.yml ===
|
||||
private void createGravesFile() {
|
||||
gravesFile = new File(getDataFolder(), "graves.yml");
|
||||
if (!gravesFile.exists()) {
|
||||
try {
|
||||
gravesFile.createNewFile();
|
||||
getLogger().info("graves.yml wurde erstellt.");
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Fehler beim Erstellen der graves.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
gravesConfig = YamlConfiguration.loadConfiguration(gravesFile);
|
||||
}
|
||||
|
||||
public FileConfiguration getGravesConfig() {
|
||||
return gravesConfig;
|
||||
}
|
||||
|
||||
public void saveGravesConfig() {
|
||||
try {
|
||||
gravesConfig.save(gravesFile);
|
||||
getLogger().info("graves.yml erfolgreich gespeichert.");
|
||||
} catch (IOException e) {
|
||||
getLogger().log(Level.SEVERE, "Fehler beim Speichern der graves.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadGravesConfig() {
|
||||
gravesConfig = YamlConfiguration.loadConfiguration(gravesFile);
|
||||
getLogger().info("graves.yml erfolgreich neu geladen.");
|
||||
}
|
||||
|
||||
// === Help.yml ===
|
||||
private void createHelpFile() {
|
||||
helpFile = new File(getDataFolder(), "help.yml");
|
||||
if (!helpFile.exists()) {
|
||||
try {
|
||||
InputStream resource = getResource("help.yml");
|
||||
if (resource != null) {
|
||||
saveResource("help.yml", false);
|
||||
} else {
|
||||
getLogger().warning("help.yml nicht im JAR gefunden. Erstelle leere Datei.");
|
||||
helpConfig = new YamlConfiguration();
|
||||
helpConfig.set("header", "§6=== SurvivalPlus Hilfe ===");
|
||||
helpConfig.set("footer", "§6=====================");
|
||||
helpConfig.save(helpFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Fehler beim Erstellen der help.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
helpConfig = YamlConfiguration.loadConfiguration(helpFile);
|
||||
}
|
||||
|
||||
public FileConfiguration getHelpConfig() {
|
||||
return helpConfig;
|
||||
}
|
||||
|
||||
public void reloadHelpConfig() {
|
||||
updateConfigFile("help.yml");
|
||||
}
|
||||
|
||||
// === Backpack.yml ===
|
||||
private void createBackpackFile() {
|
||||
backpackFile = new File(getDataFolder(), "backpacks.yml");
|
||||
if (!backpackFile.exists()) {
|
||||
try {
|
||||
backpackFile.createNewFile();
|
||||
getLogger().info("backpacks.yml wurde erstellt.");
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Fehler beim Erstellen der backpacks.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
backpackConfig = YamlConfiguration.loadConfiguration(backpackFile);
|
||||
}
|
||||
|
||||
public FileConfiguration getBackpackConfig() {
|
||||
return backpackConfig;
|
||||
}
|
||||
|
||||
public void saveBackpackConfig() {
|
||||
try {
|
||||
backpackConfig.save(backpackFile);
|
||||
getLogger().info("backpacks.yml erfolgreich gespeichert.");
|
||||
} catch (IOException e) {
|
||||
getLogger().log(Level.SEVERE, "Fehler beim Speichern der backpacks.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadBackpackConfig() {
|
||||
backpackConfig = YamlConfiguration.loadConfiguration(backpackFile);
|
||||
getLogger().info("backpacks.yml erfolgreich neu geladen.");
|
||||
}
|
||||
|
||||
// === Friends.yml ===
|
||||
private void createFriendsFile() {
|
||||
friendsFile = new File(getDataFolder(), "friends.yml");
|
||||
if (!friendsFile.exists()) {
|
||||
try {
|
||||
friendsFile.createNewFile();
|
||||
getLogger().info("friends.yml wurde erstellt.");
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Fehler beim Erstellen der friends.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
friendsConfig = YamlConfiguration.loadConfiguration(friendsFile);
|
||||
}
|
||||
|
||||
public FileConfiguration getFriendsConfig() {
|
||||
return friendsConfig;
|
||||
}
|
||||
|
||||
public void saveFriendsConfig() {
|
||||
try {
|
||||
friendsConfig.save(friendsFile);
|
||||
getLogger().info("friends.yml erfolgreich gespeichert.");
|
||||
} catch (IOException e) {
|
||||
getLogger().log(Level.SEVERE, "Fehler beim Speichern der friends.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadFriendsConfig() {
|
||||
friendsConfig = YamlConfiguration.loadConfiguration(friendsFile);
|
||||
getLogger().info("friends.yml erfolgreich neu geladen.");
|
||||
}
|
||||
|
||||
// === Leashes.yml ===
|
||||
private void createLeashesFile() {
|
||||
leashesFile = new File(getDataFolder(), "leashes.yml");
|
||||
if (!leashesFile.exists()) {
|
||||
try {
|
||||
leashesFile.createNewFile();
|
||||
getLogger().info("leashes.yml wurde erstellt.");
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Fehler beim Erstellen der leashes.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
leashesConfig = YamlConfiguration.loadConfiguration(leashesFile);
|
||||
}
|
||||
|
||||
public FileConfiguration getLeashesConfig() {
|
||||
return leashesConfig;
|
||||
}
|
||||
|
||||
public void saveLeashesConfig() {
|
||||
try {
|
||||
leashesConfig.save(leashesFile);
|
||||
getLogger().info("leashes.yml erfolgreich gespeichert.");
|
||||
} catch (IOException e) {
|
||||
getLogger().log(Level.SEVERE, "Fehler beim Speichern der leashes.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadLeashesConfig() {
|
||||
leashesConfig = YamlConfiguration.loadConfiguration(leashesFile);
|
||||
getLogger().info("leashes.yml erfolgreich neu geladen.");
|
||||
}
|
||||
|
||||
// === MobCap.yml ===
|
||||
private void createMobCapFile() {
|
||||
mobCapFile = new File(getDataFolder(), "mobcap.yml");
|
||||
if (!mobCapFile.exists()) {
|
||||
try {
|
||||
mobCapFile.createNewFile();
|
||||
getLogger().info("mobcap.yml wurde erstellt.");
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Fehler beim Erstellen der mobcap.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
mobCapConfig = YamlConfiguration.loadConfiguration(mobCapFile);
|
||||
}
|
||||
|
||||
public FileConfiguration getMobCapConfig() {
|
||||
return mobCapConfig;
|
||||
}
|
||||
|
||||
public void saveMobCapConfig() {
|
||||
try {
|
||||
mobCapConfig.save(mobCapFile);
|
||||
getLogger().info("mobcap.yml erfolgreich gespeichert.");
|
||||
} catch (IOException e) {
|
||||
getLogger().log(Level.SEVERE, "Fehler beim Speichern der mobcap.yml: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadMobCapConfig() {
|
||||
mobCapConfig = YamlConfiguration.loadConfiguration(mobCapFile);
|
||||
getLogger().info("mobcap.yml erfolgreich neu geladen.");
|
||||
}
|
||||
|
||||
// === AutoClearTask ===
|
||||
private void startAutoClearTask() {
|
||||
if (autoClearTaskId != -1) {
|
||||
Bukkit.getScheduler().cancelTask(autoClearTaskId);
|
||||
autoClearTaskId = -1;
|
||||
}
|
||||
|
||||
if (getConfig().getBoolean("auto-clear-enabled", true)) {
|
||||
int intervalMinutes = getConfig().getInt("auto-clear-interval-minutes", 15);
|
||||
int intervalTicks = intervalMinutes * 60 * 20; // Minuten in Ticks umrechnen
|
||||
if (intervalTicks > 0) {
|
||||
autoClearTaskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new AutoClearTask(this), intervalTicks, intervalTicks);
|
||||
getLogger().info("AutoClearTask gestartet mit Intervall von " + intervalMinutes + " Minuten.");
|
||||
}
|
||||
} else {
|
||||
getLogger().info("AutoClearTask deaktiviert, da auto-clear-enabled auf false gesetzt ist.");
|
||||
}
|
||||
}
|
||||
|
||||
// === Reload Plugin ===
|
||||
public void reloadPlugin() {
|
||||
try {
|
||||
// Config-Dateien aktualisieren
|
||||
updateConfigFiles();
|
||||
reloadBackpackConfig();
|
||||
reloadFriendsConfig();
|
||||
reloadHomesConfig();
|
||||
reloadGravesConfig();
|
||||
reloadLeashesConfig();
|
||||
reloadMobCapConfig();
|
||||
|
||||
// AutoClearTask neu starten
|
||||
startAutoClearTask();
|
||||
|
||||
// Bestehende Listener abmelden
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
HandlerList.unregisterAll(this);
|
||||
|
||||
// FriendCommand instanzieren für PlayerJoinListener
|
||||
FriendCommand friendCommand = new FriendCommand(this, friendsConfig, langConfig, getLogger());
|
||||
|
||||
// Listener neu erstellen und registrieren
|
||||
mobLeashLimitListener = new MobLeashLimitListener(this, getConfig());
|
||||
mobLeashLimitListener.reloadConfig(getConfig());
|
||||
pm.registerEvents(mobLeashLimitListener, this);
|
||||
|
||||
mobCapListener = new MobCapListener(this, getConfig());
|
||||
mobCapListener.reloadConfig(getConfig());
|
||||
pm.registerEvents(mobCapListener, this);
|
||||
|
||||
sleepListener = new SleepListener(this);
|
||||
sleepListener.reloadConfig(getConfig());
|
||||
pm.registerEvents(sleepListener, this);
|
||||
|
||||
oreAlarmListener = new OreAlarmListener(this);
|
||||
oreAlarmListener.reloadConfig(getConfig());
|
||||
pm.registerEvents(oreAlarmListener, this);
|
||||
|
||||
afkListener = new AFKListener(this);
|
||||
afkListener.reloadConfig(getConfig());
|
||||
pm.registerEvents(afkListener, this);
|
||||
|
||||
graveListener = new GraveListener(this);
|
||||
graveListener.reloadConfig(getConfig());
|
||||
pm.registerEvents(graveListener, this);
|
||||
|
||||
sitListener = new SitListener(this);
|
||||
pm.registerEvents(sitListener, this);
|
||||
|
||||
playerJoinListener = new PlayerJoinListener(friendCommand);
|
||||
pm.registerEvents(playerJoinListener, this);
|
||||
|
||||
pm.registerEvents(new InventoryClickListener(this), this);
|
||||
pm.registerEvents(new BackpackListener(backpackConfig, langConfig, getLogger(), backpackFile), this);
|
||||
pm.registerEvents(new StatsListener(this, statsManager), this);
|
||||
pm.registerEvents(new LoginListener(this), this);
|
||||
pm.registerEvents(new DebugArmorStandListener(), this);
|
||||
pm.registerEvents(new ArmorStandDestroyListener(), this);
|
||||
pm.registerEvents(new FirstJoinListener(), this);
|
||||
|
||||
spawnProtectionListener = new SpawnProtectionListener(this);
|
||||
pm.registerEvents(spawnProtectionListener, this);
|
||||
|
||||
LockSystem lockSystem = new LockSystem(this);
|
||||
pm.registerEvents(lockSystem, this);
|
||||
getCommand("lock").setExecutor(lockSystem);
|
||||
|
||||
// Commands neu registrieren
|
||||
getCommand("friend").setExecutor(friendCommand);
|
||||
|
||||
getLogger().info(getMessage("plugin.reloaded"));
|
||||
} catch (Exception e) {
|
||||
getLogger().severe("Fehler beim Neuladen des Plugins: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
public class AnvilCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("Nur Spieler können diesen Befehl ausführen.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Inventory anvil = Bukkit.createInventory(player, InventoryType.ANVIL, "Amboss");
|
||||
player.openInventory(anvil);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class BackCommand implements CommandExecutor {
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public BackCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("player-only", "§cDieser Befehl ist nur für Spieler!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
FileConfiguration gravesConfig = plugin.getGravesConfig();
|
||||
|
||||
if (!player.hasPermission("survivalplus.back")) {
|
||||
player.sendMessage(lang.getString("no-permission", "§cDu hast keine Berechtigung für diesen Befehl!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 0) {
|
||||
player.sendMessage(lang.getString("back.usage", "§cVerwendung: /back"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Lade Todesposition
|
||||
String path = "graves." + player.getUniqueId();
|
||||
if (!gravesConfig.contains(path)) {
|
||||
player.sendMessage(lang.getString("back.no-death-point", "§cDu hast keinen Todespunkt!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String worldName = gravesConfig.getString(path + ".world");
|
||||
double x = gravesConfig.getDouble(path + ".x");
|
||||
double y = gravesConfig.getDouble(path + ".y");
|
||||
double z = gravesConfig.getDouble(path + ".z");
|
||||
|
||||
World world = plugin.getServer().getWorld(worldName);
|
||||
if (world == null) {
|
||||
player.sendMessage(lang.getString("back.no-death-point", "§cDu hast keinen Todespunkt!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Location location = new Location(world, x, y, z);
|
||||
player.teleport(location);
|
||||
|
||||
player.sendMessage(String.format(
|
||||
lang.getString("back.success", "§aTeleportiert zum Todespunkt bei x=%.2f, y=%.2f, z=%.2f!"),
|
||||
x, y, z
|
||||
));
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.Manager.BlockManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class BlockCommand implements CommandExecutor {
|
||||
|
||||
private final BlockManager blockManager;
|
||||
private final FileConfiguration config;
|
||||
|
||||
public BlockCommand(BlockManager blockManager, FileConfiguration config) {
|
||||
this.blockManager = blockManager;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(config.getString("messages.general.only_players"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
player.sendMessage(config.getString("messages.block.usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayerExact(args[0]);
|
||||
if (target == null || target == player) {
|
||||
player.sendMessage(config.getString("messages.block.invalid_player"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (blockManager.hasBlocked(player, target)) {
|
||||
player.sendMessage(config.getString("messages.block.already_blocked").replace("%player%", target.getName()));
|
||||
} else {
|
||||
blockManager.blockPlayer(player, target);
|
||||
player.sendMessage(config.getString("messages.block.blocked").replace("%player%", target.getName()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.Manager.BlockManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BlockListCommand implements CommandExecutor {
|
||||
|
||||
private final BlockManager blockManager;
|
||||
private final FileConfiguration config;
|
||||
|
||||
public BlockListCommand(BlockManager blockManager, FileConfiguration config) {
|
||||
this.blockManager = blockManager;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(config.getString("messages.general.only_players"));
|
||||
return true;
|
||||
}
|
||||
|
||||
var blocked = blockManager.getBlockedPlayers(player);
|
||||
if (blocked.isEmpty()) {
|
||||
player.sendMessage(config.getString("messages.blocklist.no_blocked_players"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String list = blocked.stream()
|
||||
.map(Bukkit::getOfflinePlayer)
|
||||
.map(p -> p.getName() != null ? p.getName() : "Unbekannt")
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
player.sendMessage(config.getString("messages.blocklist.blocked_players").replace("%list%", list));
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class ClearChatCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!sender.hasPermission("survivalplus.clearchat")) {
|
||||
sender.sendMessage("§cDu hast keine Rechte, den Chat zu löschen.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Chat für alle "leeren" (100 leere Zeilen senden)
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Bukkit.broadcastMessage(" ");
|
||||
}
|
||||
|
||||
Bukkit.broadcastMessage("§aDer Chat wurde von §e" + sender.getName() + " §agelöscht.");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ClearDebugArmorStandsCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public ClearDebugArmorStandsCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage("Dieser Befehl kann nur von einem Spieler ausgeführt werden.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
int removedCount = 0;
|
||||
|
||||
for (Entity entity : player.getWorld().getEntities()) {
|
||||
if (entity instanceof ArmorStand) {
|
||||
ArmorStand armorStand = (ArmorStand) entity;
|
||||
armorStand.setInvulnerable(false);
|
||||
armorStand.setMarker(false);
|
||||
armorStand.setGravity(true);
|
||||
armorStand.remove();
|
||||
removedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
player.sendMessage("Es wurden " + removedCount + " ArmorStands entfernt.");
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Item;
|
||||
|
||||
public class ClearItemsCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public ClearItemsCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
int totalRemoved = 0;
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
for (Item item : world.getEntitiesByClass(Item.class)) {
|
||||
item.remove();
|
||||
totalRemoved++;
|
||||
}
|
||||
}
|
||||
sender.sendMessage(ChatColor.RED + "Alle Items wurden entfernt (" + totalRemoved + " Stück).");
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import de.viper.survivalplus.report.ReportManager;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ClearReportCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final ReportManager reportManager;
|
||||
|
||||
public ClearReportCommand(SurvivalPlus plugin, ReportManager reportManager) {
|
||||
this.plugin = plugin;
|
||||
this.reportManager = reportManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("clearreport.only-players", "§cNur Spieler können diesen Befehl ausführen!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("survivalplus.report.clear")) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("no-permission", "§cDu hast keine Berechtigung!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("clearreport.usage", "§cVerwendung: /clearreport <Spieler>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String targetName = args[0];
|
||||
reportManager.clearReports(targetName);
|
||||
|
||||
player.sendMessage(plugin.getLangConfig().getString("clearreport.cleared", "§aReports von %player% wurden gelöscht.").replace("%player%", targetName));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.Openable;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
|
||||
public class CloseDoorsCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public CloseDoorsCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("commands.closedoors.noplayer", "Nur Spieler können diesen Befehl nutzen!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("survivalplus.closedoors")) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("commands.closedoors.nopermission", "Dafür hast du keine Rechte!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("commands.closedoors.usage", "Benutzung: /closedoors <radius>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
int radius;
|
||||
try {
|
||||
radius = Integer.parseInt(args[0]);
|
||||
if (radius <= 0) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("commands.closedoors.invalidradius", "Der Radius muss größer als 0 sein!"));
|
||||
return true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("commands.closedoors.invalidradius", "Der Radius muss eine Zahl sein!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
int closedCount = 0;
|
||||
var center = player.getLocation().getBlock();
|
||||
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int z = -radius; z <= radius; z++) {
|
||||
Block block = center.getRelative(x, y, z);
|
||||
Material type = block.getType();
|
||||
|
||||
if (type == Material.OAK_DOOR ||
|
||||
type == Material.SPRUCE_DOOR ||
|
||||
type == Material.BIRCH_DOOR ||
|
||||
type == Material.JUNGLE_DOOR ||
|
||||
type == Material.ACACIA_DOOR ||
|
||||
type == Material.DARK_OAK_DOOR ||
|
||||
type == Material.CRIMSON_DOOR ||
|
||||
type == Material.WARPED_DOOR ||
|
||||
type == Material.IRON_DOOR) {
|
||||
|
||||
var blockData = block.getBlockData();
|
||||
if (blockData instanceof Openable openable) {
|
||||
if (openable.isOpen()) {
|
||||
openable.setOpen(false);
|
||||
block.setBlockData(openable);
|
||||
closedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player.sendMessage(plugin.getLangConfig()
|
||||
.getString("commands.closedoors.success", "Es wurden %count% Türen geschlossen.")
|
||||
.replace("%count%", String.valueOf(closedCount)));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
33
src/main/java/de/viper/survivalplus/commands/DayCommand.java
Normal file
33
src/main/java/de/viper/survivalplus/commands/DayCommand.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class DayCommand implements CommandExecutor {
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public DayCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("§cNur Spieler können diesen Befehl ausführen!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("survivalplus.day")) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("no-permission", "§cDu hast keine Berechtigung!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
player.getWorld().setTime(1000); // Tag setzen
|
||||
player.sendMessage("§aEs ist jetzt Tag!");
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.Manager.WarpManager;
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class DelWarpCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final WarpManager warpManager;
|
||||
|
||||
public DelWarpCommand(SurvivalPlus plugin, WarpManager warpManager) {
|
||||
this.plugin = plugin;
|
||||
this.warpManager = warpManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getMessage("warp.only_players"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
|
||||
if (args.length < 1) {
|
||||
player.sendMessage(ChatColor.RED + "Benutze: /delwarp <name>");
|
||||
return true;
|
||||
}
|
||||
|
||||
String warpName = args[0];
|
||||
boolean removed = warpManager.removeWarp(player.getName(), warpName);
|
||||
|
||||
if (removed) {
|
||||
player.sendMessage(ChatColor.GREEN + "Warp '" + warpName + "' wurde gelöscht.");
|
||||
} else {
|
||||
player.sendMessage(ChatColor.RED + "Du hast keinen Warp mit dem Namen '" + warpName + "'.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,123 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class EnderchestCommand implements CommandExecutor {
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public EnderchestCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("player-only", "§cDieser Befehl ist nur für Spieler!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
|
||||
if (!player.hasPermission("survivalplus.enderchest.own")) {
|
||||
player.sendMessage(lang.getString("no-permission", "§cDu hast keine Berechtigung für diesen Befehl!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
OfflinePlayer target;
|
||||
String targetName;
|
||||
|
||||
if (args.length == 0) {
|
||||
// Öffne die eigene Enderchest
|
||||
target = player;
|
||||
targetName = player.getName();
|
||||
} else if (args.length == 1) {
|
||||
// Öffne die Enderchest eines anderen Spielers
|
||||
if (!player.hasPermission("survivalplus.enderchest.others")) {
|
||||
player.sendMessage(lang.getString("no-permission-others-ec", "§cDu hast keine Berechtigung, die Enderchest anderer Spieler anzusehen!"));
|
||||
return true;
|
||||
}
|
||||
targetName = args[0];
|
||||
Player onlineTarget = Bukkit.getPlayerExact(targetName);
|
||||
if (onlineTarget != null) {
|
||||
target = onlineTarget;
|
||||
} else {
|
||||
target = Bukkit.getOfflinePlayer(targetName);
|
||||
if (target.getName() == null || !target.hasPlayedBefore()) {
|
||||
player.sendMessage(lang.getString("player-not-found", "§cSpieler nicht gefunden!"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.sendMessage(lang.getString("enderchest.usage", "§cVerwendung: /ec [spieler]"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Erstelle die GUI
|
||||
Inventory gui = Bukkit.createInventory(null, 27, lang.getString("enderchest.gui-title", "Enderchest von ") + targetName);
|
||||
|
||||
// Lade die Enderchest
|
||||
if (target.isOnline()) {
|
||||
Player onlineTarget = target.getPlayer();
|
||||
Inventory enderChest = onlineTarget.getEnderChest();
|
||||
for (int i = 0; i < 27; i++) {
|
||||
gui.setItem(i, enderChest.getItem(i));
|
||||
}
|
||||
plugin.getLogger().log(Level.INFO, "Enderchest für " + targetName + " (online) erfolgreich geladen");
|
||||
} else {
|
||||
UUID uuid = target.getUniqueId();
|
||||
try {
|
||||
// Lade Offline-Spieler-Enderchest aus playerdata
|
||||
File dataFolder = new File(plugin.getServer().getWorlds().get(0).getWorldFolder(), "playerdata");
|
||||
File playerFile = new File(dataFolder, uuid.toString() + ".dat");
|
||||
|
||||
if (!playerFile.exists()) {
|
||||
player.sendMessage(lang.getString("enderchest.data-not-found", "§cDie Enderchest-Daten des Spielers konnten nicht gefunden werden! Der Spieler war möglicherweise nie auf diesem Server."));
|
||||
return true;
|
||||
}
|
||||
|
||||
String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
plugin.getLogger().log(Level.INFO, "Versuche, Enderchest für " + targetName + " zu laden (UUID: " + uuid + ", Version: " + version + ")");
|
||||
|
||||
// Verwende Reflection, um die Enderchest-Daten zu laden
|
||||
Class<?> nbtIoClass = Class.forName("net.minecraft.nbt.NbtIo");
|
||||
Class<?> nbtCompoundClass = Class.forName("net.minecraft.nbt.NbtCompound");
|
||||
Class<?> nbtListClass = Class.forName("net.minecraft.nbt.NbtList");
|
||||
Class<?> craftInventoryClass = Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftInventory");
|
||||
|
||||
Object nbtCompound = nbtIoClass.getMethod("readCompressed", java.nio.file.Path.class).invoke(null, playerFile.toPath());
|
||||
Object enderItemsList = nbtCompoundClass.getMethod("getList", String.class, int.class).invoke(nbtCompound, "EnderItems", 10);
|
||||
Object craftInventory = craftInventoryClass.getConstructor(nbtListClass).newInstance(enderItemsList);
|
||||
|
||||
ItemStack[] items = (ItemStack[]) craftInventoryClass.getMethod("getContents").invoke(craftInventory);
|
||||
for (int i = 0; i < Math.min(items.length, 27); i++) {
|
||||
gui.setItem(i, items[i]);
|
||||
}
|
||||
plugin.getLogger().log(Level.INFO, "Enderchest für " + targetName + " erfolgreich geladen");
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Fehler beim Laden der Enderchest für " + targetName + " (UUID: " + uuid + ")", e);
|
||||
String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
|
||||
player.sendMessage(lang.getString("enderchest.load-error", "§cFehler beim Laden der Enderchest: %error%")
|
||||
.replace("%error%", errorMessage));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
player.openInventory(gui);
|
||||
player.sendMessage(lang.getString("enderchest.opened", "§aEnderchest von %player% geöffnet!")
|
||||
.replace("%player%", targetName));
|
||||
return true;
|
||||
}
|
||||
}
|
423
src/main/java/de/viper/survivalplus/commands/FriendCommand.java
Normal file
423
src/main/java/de/viper/survivalplus/commands/FriendCommand.java
Normal file
@@ -0,0 +1,423 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class FriendCommand implements CommandExecutor {
|
||||
private final JavaPlugin plugin;
|
||||
private final FileConfiguration friendsConfig;
|
||||
private final FileConfiguration langConfig;
|
||||
private final Logger logger;
|
||||
|
||||
public FriendCommand(JavaPlugin plugin, FileConfiguration friendsConfig, FileConfiguration langConfig, Logger logger) {
|
||||
this.plugin = plugin;
|
||||
this.friendsConfig = friendsConfig;
|
||||
this.langConfig = langConfig;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.player-only", "&cDieser Befehl ist nur für Spieler!")));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
|
||||
if (args.length == 0) {
|
||||
sendHelpMessage(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
String subCommand = args[0].toLowerCase();
|
||||
|
||||
switch (subCommand) {
|
||||
case "add":
|
||||
if (args.length != 2) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.add-usage", "&cVerwendung: /friend add <Spielername>")));
|
||||
return true;
|
||||
}
|
||||
handleFriendAdd(player, args[1]);
|
||||
break;
|
||||
|
||||
case "accept":
|
||||
if (args.length != 2) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.accept-usage", "&cVerwendung: /friend accept <Spielername>")));
|
||||
return true;
|
||||
}
|
||||
handleFriendAccept(player, args[1]);
|
||||
break;
|
||||
|
||||
case "deny":
|
||||
if (args.length != 2) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.deny-usage", "&cVerwendung: /friend deny <Spielername>")));
|
||||
return true;
|
||||
}
|
||||
handleFriendDeny(player, args[1]);
|
||||
break;
|
||||
|
||||
case "list":
|
||||
if (args.length != 1) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.list-usage", "&cVerwendung: /friend list")));
|
||||
return true;
|
||||
}
|
||||
handleFriendList(player);
|
||||
break;
|
||||
|
||||
case "del":
|
||||
if (args.length != 2) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.del-usage", "&cVerwendung: /friend del <Spielername>")));
|
||||
return true;
|
||||
}
|
||||
handleFriendDelete(player, args[1]);
|
||||
break;
|
||||
|
||||
case "confirm":
|
||||
if (args.length != 2) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.confirm-usage", "&cVerwendung: /friend confirm <Spielername>")));
|
||||
return true;
|
||||
}
|
||||
handleFriendConfirmDelete(player, args[1]);
|
||||
break;
|
||||
|
||||
case "tp":
|
||||
if (args.length != 2) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.tp-usage", "&cVerwendung: /friend tp <Spielername>")));
|
||||
return true;
|
||||
}
|
||||
handleFriendTeleport(player, args[1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
sendHelpMessage(player);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendHelpMessage(Player player) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.help.header", "&6=== Freundesliste Hilfe ===")));
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.help.add", "&e/friend add <Spielername> &7- Freundschaftsanfrage senden")));
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.help.accept", "&e/friend accept <Spielername> &7- Freundschaftsanfrage akzeptieren")));
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.help.deny", "&e/friend deny <Spielername> &7- Freundschaftsanfrage ablehnen")));
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.help.list", "&e/friend list &7- Liste deiner Freunde anzeigen")));
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.help.del", "&e/friend del <Spielername> &7- Freund aus der Liste entfernen")));
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.help.tp", "&e/friend tp <Spielername> &7- Zu einem Freund teleportieren")));
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.help.footer", "&6=====================")));
|
||||
}
|
||||
|
||||
private void handleFriendAdd(Player player, String targetName) {
|
||||
Player target = Bukkit.getPlayerExact(targetName);
|
||||
if (target == null) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.player-not-found", "&cSpieler %s nicht gefunden!").replace("%s", targetName)));
|
||||
return;
|
||||
}
|
||||
if (target.getUniqueId().equals(player.getUniqueId())) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.self", "&cDu kannst dich nicht selbst hinzufügen!")));
|
||||
return;
|
||||
}
|
||||
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
UUID targetUUID = target.getUniqueId();
|
||||
List<String> playerFriends = friendsConfig.getStringList(playerUUID + ".friends");
|
||||
List<String> pendingRequests = friendsConfig.getStringList(targetUUID + ".pending_requests");
|
||||
|
||||
if (playerFriends.contains(targetUUID.toString())) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.already-friends", "&cDu bist bereits mit %s befreundet!").replace("%s", targetName)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingRequests.contains(playerUUID.toString())) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.request-pending", "&cDu hast bereits eine Anfrage an %s gesendet!").replace("%s", targetName)));
|
||||
return;
|
||||
}
|
||||
|
||||
pendingRequests.add(playerUUID.toString());
|
||||
friendsConfig.set(targetUUID + ".pending_requests", pendingRequests);
|
||||
friendsConfig.set(targetUUID + ".name", targetName);
|
||||
saveFriendsConfig();
|
||||
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.add.sent", "&aFreundschaftsanfrage an %s gesendet!").replace("%s", targetName)));
|
||||
|
||||
TextComponent message = new TextComponent(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.add.received", "&aDu hast eine Freundschaftsanfrage von %s erhalten! ").replace("%s", player.getName())));
|
||||
TextComponent accept = new TextComponent(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.add.accept-button", "&a[Accept]")));
|
||||
accept.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/friend accept " + player.getName()));
|
||||
TextComponent deny = new TextComponent(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.add.deny-button", "&c [Deny]")));
|
||||
deny.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/friend deny " + player.getName()));
|
||||
message.addExtra(accept);
|
||||
message.addExtra(deny);
|
||||
target.spigot().sendMessage(message);
|
||||
|
||||
logger.info("Freundschaftsanfrage von " + player.getName() + " an " + targetName + " gesendet.");
|
||||
}
|
||||
|
||||
private void handleFriendAccept(Player player, String requesterName) {
|
||||
Player requester = Bukkit.getPlayerExact(requesterName);
|
||||
if (requester == null) {
|
||||
UUID requesterUUID = getUUIDFromName(requesterName);
|
||||
if (requesterUUID == null) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.player-not-found", "&cSpieler %s nicht gefunden!").replace("%s", requesterName)));
|
||||
return;
|
||||
}
|
||||
acceptFriendRequest(player, requesterUUID, requesterName);
|
||||
} else {
|
||||
acceptFriendRequest(player, requester.getUniqueId(), requesterName);
|
||||
}
|
||||
}
|
||||
|
||||
private void acceptFriendRequest(Player player, UUID requesterUUID, String requesterName) {
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
List<String> pendingRequests = friendsConfig.getStringList(playerUUID + ".pending_requests");
|
||||
|
||||
if (!pendingRequests.contains(requesterUUID.toString())) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.no-request", "&cKeine Anfrage von %s gefunden!").replace("%s", requesterName)));
|
||||
return;
|
||||
}
|
||||
|
||||
pendingRequests.remove(requesterUUID.toString());
|
||||
friendsConfig.set(playerUUID + ".pending_requests", pendingRequests);
|
||||
|
||||
List<String> playerFriends = friendsConfig.getStringList(playerUUID + ".friends");
|
||||
List<String> requesterFriends = friendsConfig.getStringList(requesterUUID + ".friends");
|
||||
|
||||
playerFriends.add(requesterUUID.toString());
|
||||
requesterFriends.add(playerUUID.toString());
|
||||
|
||||
friendsConfig.set(playerUUID + ".friends", playerFriends);
|
||||
friendsConfig.set(playerUUID + ".name", player.getName());
|
||||
friendsConfig.set(requesterUUID + ".friends", requesterFriends);
|
||||
friendsConfig.set(requesterUUID + ".name", requesterName);
|
||||
|
||||
saveFriendsConfig();
|
||||
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.accept.success", "&aDu bist jetzt mit %s befreundet!").replace("%s", requesterName)));
|
||||
Player requester = Bukkit.getPlayer(requesterUUID);
|
||||
if (requester != null) {
|
||||
requester.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.accept.notify", "&a%s hat deine Freundschaftsanfrage akzeptiert!").replace("%s", player.getName())));
|
||||
}
|
||||
logger.info(player.getName() + " hat die Freundschaftsanfrage von " + requesterName + " akzeptiert.");
|
||||
}
|
||||
|
||||
private void handleFriendDeny(Player player, String requesterName) {
|
||||
UUID requesterUUID = getUUIDFromName(requesterName);
|
||||
if (requesterUUID == null) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.player-not-found", "&cSpieler %s nicht gefunden!").replace("%s", requesterName)));
|
||||
return;
|
||||
}
|
||||
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
List<String> pendingRequests = friendsConfig.getStringList(playerUUID + ".pending_requests");
|
||||
|
||||
if (!pendingRequests.contains(requesterUUID.toString())) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.no-request", "&cKeine Anfrage von %s gefunden!").replace("%s", requesterName)));
|
||||
return;
|
||||
}
|
||||
|
||||
pendingRequests.remove(requesterUUID.toString());
|
||||
friendsConfig.set(playerUUID + ".pending_requests", pendingRequests);
|
||||
saveFriendsConfig();
|
||||
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.deny.success", "&aFreundschaftsanfrage von %s abgelehnt.").replace("%s", requesterName)));
|
||||
Player requester = Bukkit.getPlayer(requesterUUID);
|
||||
if (requester != null) {
|
||||
requester.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.deny.notify", "&c%s hat deine Freundschaftsanfrage abgelehnt.").replace("%s", player.getName())));
|
||||
}
|
||||
logger.info(player.getName() + " hat die Freundschaftsanfrage von " + requesterName + " abgelehnt.");
|
||||
}
|
||||
|
||||
private void handleFriendList(Player player) {
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
List<String> friendUUIDs = friendsConfig.getStringList(playerUUID + ".friends");
|
||||
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.list.header", "&6=== Deine Freundesliste ===")));
|
||||
if (friendUUIDs.isEmpty()) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.list.empty", "&7Du hast keine Freunde.")));
|
||||
} else {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat(langConfig.getString("friend.list.date-format", "dd.MM.yyyy HH:mm:ss"));
|
||||
for (String friendUUID : friendUUIDs) {
|
||||
String friendName = getNameFromUUID(UUID.fromString(friendUUID));
|
||||
Player friend = Bukkit.getPlayer(UUID.fromString(friendUUID));
|
||||
TextComponent entry = new TextComponent();
|
||||
|
||||
if (friend != null) {
|
||||
entry.addExtra(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.list.entry", "&e%s: %s").replaceFirst("%s", friendName).replaceFirst("%s", langConfig.getString("friend.list.online", "&aOnline"))));
|
||||
} else {
|
||||
long lastOnline = friendsConfig.getLong(friendUUID + ".last-online", 0);
|
||||
String lastOnlineStr = lastOnline > 0 ? dateFormat.format(new Date(lastOnline)) : langConfig.getString("friend.list.unknown", "&7Unbekannt");
|
||||
entry.addExtra(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.list.entry-offline", "&e%s: %s &7(Zuletzt online: %s)").replaceFirst("%s", friendName).replaceFirst("%s", langConfig.getString("friend.list.offline", "&7Offline")).replace("%s", lastOnlineStr)));
|
||||
}
|
||||
|
||||
TextComponent removeButton = new TextComponent(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.list.remove-button", "&c[X]")));
|
||||
removeButton.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/friend del " + friendName));
|
||||
entry.addExtra(" ");
|
||||
entry.addExtra(removeButton);
|
||||
|
||||
player.spigot().sendMessage(entry);
|
||||
}
|
||||
}
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.list.footer", "&6=====================")));
|
||||
logger.info("Freundesliste für " + player.getName() + " angezeigt.");
|
||||
}
|
||||
|
||||
private void handleFriendDelete(Player player, String friendName) {
|
||||
UUID friendUUID = getUUIDFromName(friendName);
|
||||
if (friendUUID == null) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.player-not-found", "&cSpieler %s nicht gefunden!").replace("%s", friendName)));
|
||||
return;
|
||||
}
|
||||
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
List<String> playerFriends = friendsConfig.getStringList(playerUUID + ".friends");
|
||||
|
||||
if (!playerFriends.contains(friendUUID.toString())) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.not-friends", "&c%s ist nicht in deiner Freundesliste!").replace("%s", friendName)));
|
||||
return;
|
||||
}
|
||||
|
||||
TextComponent confirmMessage = new TextComponent(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.del.confirm", "&cMöchtest du %s wirklich aus deiner Freundesliste entfernen? ").replace("%s", friendName)));
|
||||
TextComponent confirmButton = new TextComponent(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.del.confirm-button", "&a[Confirm]")));
|
||||
confirmButton.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/friend confirm " + friendName));
|
||||
TextComponent cancelButton = new TextComponent(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.del.cancel-button", "&c[Cancel]")));
|
||||
cancelButton.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/friend list"));
|
||||
confirmMessage.addExtra(confirmButton);
|
||||
confirmMessage.addExtra(" ");
|
||||
confirmMessage.addExtra(cancelButton);
|
||||
player.spigot().sendMessage(confirmMessage);
|
||||
|
||||
logger.info(player.getName() + " wurde zur Bestätigung aufgefordert, " + friendName + " aus der Freundesliste zu entfernen.");
|
||||
}
|
||||
|
||||
private void handleFriendConfirmDelete(Player player, String friendName) {
|
||||
UUID friendUUID = getUUIDFromName(friendName);
|
||||
if (friendUUID == null) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.player-not-found", "&cSpieler %s nicht gefunden!").replace("%s", friendName)));
|
||||
return;
|
||||
}
|
||||
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
List<String> playerFriends = friendsConfig.getStringList(playerUUID + ".friends");
|
||||
List<String> friendFriends = friendsConfig.getStringList(friendUUID + ".friends");
|
||||
|
||||
if (!playerFriends.contains(friendUUID.toString())) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.not-friends", "&c%s ist nicht in deiner Freundesliste!").replace("%s", friendName)));
|
||||
return;
|
||||
}
|
||||
|
||||
playerFriends.remove(friendUUID.toString());
|
||||
friendFriends.remove(playerUUID.toString());
|
||||
|
||||
friendsConfig.set(playerUUID + ".friends", playerFriends);
|
||||
friendsConfig.set(friendUUID + ".friends", friendFriends);
|
||||
saveFriendsConfig();
|
||||
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.del.success", "&a%s wurde aus deiner Freundesliste entfernt.").replace("%s", friendName)));
|
||||
Player friend = Bukkit.getPlayer(friendUUID);
|
||||
if (friend != null) {
|
||||
friend.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.del.notify", "&c%s hat dich aus seiner Freundesliste entfernt.").replace("%s", player.getName())));
|
||||
}
|
||||
logger.info(player.getName() + " hat " + friendName + " aus der Freundesliste entfernt.");
|
||||
}
|
||||
|
||||
private void handleFriendTeleport(Player player, String friendName) {
|
||||
Player friend = Bukkit.getPlayerExact(friendName);
|
||||
if (friend == null) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.player-not-found", "&cSpieler %s nicht gefunden!").replace("%s", friendName)));
|
||||
return;
|
||||
}
|
||||
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
UUID friendUUID = friend.getUniqueId();
|
||||
List<String> playerFriends = friendsConfig.getStringList(playerUUID + ".friends");
|
||||
|
||||
if (!playerFriends.contains(friendUUID.toString())) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.not-friends", "&c%s ist nicht in deiner Freundesliste!").replace("%s", friendName)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player.getWorld().equals(friend.getWorld())) {
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.error.different-world", "&cIhr müsst in derselben Welt sein, um zu teleportieren!")));
|
||||
return;
|
||||
}
|
||||
|
||||
player.teleport(friend.getLocation());
|
||||
player.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.tp.success", "&aDu wurdest zu %s teleportiert!").replace("%s", friendName)));
|
||||
friend.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.tp.notify", "&a%s hat sich zu dir teleportiert.").replace("%s", player.getName())));
|
||||
logger.info(player.getName() + " hat sich zu " + friendName + " teleportiert.");
|
||||
}
|
||||
|
||||
private UUID getUUIDFromName(String name) {
|
||||
Player target = Bukkit.getPlayerExact(name);
|
||||
if (target != null) {
|
||||
return target.getUniqueId();
|
||||
}
|
||||
for (String key : friendsConfig.getKeys(false)) {
|
||||
try {
|
||||
UUID uuid = UUID.fromString(key);
|
||||
String storedName = friendsConfig.getString(key + ".name");
|
||||
if (storedName != null && storedName.equalsIgnoreCase(name)) {
|
||||
return uuid;
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getNameFromUUID(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null) {
|
||||
return player.getName();
|
||||
}
|
||||
String storedName = friendsConfig.getString(uuid + ".name");
|
||||
if (storedName != null) {
|
||||
return storedName;
|
||||
}
|
||||
return uuid.toString();
|
||||
}
|
||||
|
||||
private void saveFriendsConfig() {
|
||||
try {
|
||||
friendsConfig.save(new File(plugin.getDataFolder(), "friends.yml"));
|
||||
logger.fine("friends.yml erfolgreich gespeichert.");
|
||||
} catch (IOException e) {
|
||||
logger.severe("Fehler beim Speichern der friends.yml: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyFriendsOfJoin(Player player) {
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
for (String friendUUIDStr : friendsConfig.getStringList(playerUUID + ".friends")) {
|
||||
Player friend = Bukkit.getPlayer(UUID.fromString(friendUUIDStr));
|
||||
if (friend != null) {
|
||||
friend.sendMessage(ChatColor.translateAlternateColorCodes('&', langConfig.getString("friend.join.notify", "&aDein Freund %s ist dem Server beigetreten.").replace("%s", player.getName())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLastOnline(Player player) {
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
friendsConfig.set(playerUUID + ".last-online", System.currentTimeMillis());
|
||||
saveFriendsConfig();
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class GamemodeCommand implements CommandExecutor {
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public GamemodeCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
|
||||
if (!sender.hasPermission("survivalplus.gamemode")) {
|
||||
sender.sendMessage(lang.getString("no-permission", "§cDu hast keine Berechtigung für diesen Befehl!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage(lang.getString("gamemode.usage", "§cVerwendung: /gm <0|1|2|3> [spieler]"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = (args.length > 1) ? plugin.getServer().getPlayer(args[1]) : (sender instanceof Player ? (Player) sender : null);
|
||||
|
||||
if (args.length > 1 && !sender.hasPermission("survivalplus.gamemode.others")) {
|
||||
sender.sendMessage(lang.getString("no-permission-others", "§cDu hast keine Berechtigung, den Spielmodus anderer zu ändern!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target == null) {
|
||||
sender.sendMessage(lang.getString("player-not-found", "§cSpieler nicht gefunden!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
GameMode gameMode;
|
||||
String modeName;
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "0":
|
||||
case "survival":
|
||||
gameMode = GameMode.SURVIVAL;
|
||||
modeName = lang.getString("gamemode.survival", "Überleben");
|
||||
break;
|
||||
case "1":
|
||||
case "creative":
|
||||
gameMode = GameMode.CREATIVE;
|
||||
modeName = lang.getString("gamemode.creative", "Kreativ");
|
||||
break;
|
||||
case "2":
|
||||
case "adventure":
|
||||
gameMode = GameMode.ADVENTURE;
|
||||
modeName = lang.getString("gamemode.adventure", "Abenteuer");
|
||||
break;
|
||||
case "3":
|
||||
case "spectator":
|
||||
gameMode = GameMode.SPECTATOR;
|
||||
modeName = lang.getString("gamemode.spectator", "Zuschauer");
|
||||
break;
|
||||
default:
|
||||
sender.sendMessage(lang.getString("invalid-gamemode", "§cUngültiger Spielmodus! Verwende 0, 1, 2 oder 3"));
|
||||
return true;
|
||||
}
|
||||
|
||||
target.setGameMode(gameMode);
|
||||
String message = sender == target ?
|
||||
lang.getString("gamemode.changed-self", "§aDein Spielmodus wurde zu %mode% geändert!")
|
||||
.replace("%mode%", modeName) :
|
||||
lang.getString("gamemode.changed-other", "§aSpielmodus von %player% zu %mode% geändert!")
|
||||
.replace("%player%", target.getName())
|
||||
.replace("%mode%", modeName);
|
||||
|
||||
sender.sendMessage(message);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class HealCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public HealCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("§cDieser Befehl kann nur von Spielern verwendet werden!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// /heal ohne Argument → eigener Spieler
|
||||
if (args.length == 0) {
|
||||
if (!player.hasPermission("survivalplus.heal")) {
|
||||
player.sendMessage("§cDu hast keine Berechtigung, dich zu heilen!");
|
||||
return true;
|
||||
}
|
||||
player.setHealth(player.getMaxHealth());
|
||||
player.setFoodLevel(20);
|
||||
player.sendMessage("§aDu wurdest vollständig geheilt!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// /heal <Spieler> → anderen Spieler heilen
|
||||
if (args.length == 1) {
|
||||
if (!player.hasPermission("survivalplus.heal.others")) {
|
||||
player.sendMessage("§cDu hast keine Berechtigung, andere Spieler zu heilen!");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayerExact(args[0]);
|
||||
if (target == null || !target.isOnline()) {
|
||||
player.sendMessage("§cDieser Spieler ist nicht online!");
|
||||
return true;
|
||||
}
|
||||
|
||||
target.setHealth(target.getMaxHealth());
|
||||
target.setFoodLevel(20);
|
||||
target.sendMessage("§aDu wurdest von §e" + player.getName() + " §ageheilt!");
|
||||
player.sendMessage("§aDu hast §e" + target.getName() + " §ageheilt!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Falsche Benutzung
|
||||
player.sendMessage("§eBenutzung: /heal [Spieler]");
|
||||
return true;
|
||||
}
|
||||
}
|
146
src/main/java/de/viper/survivalplus/commands/HomeCommand.java
Normal file
146
src/main/java/de/viper/survivalplus/commands/HomeCommand.java
Normal file
@@ -0,0 +1,146 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
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 org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class HomeCommand implements CommandExecutor {
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public HomeCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("player-only", "§cDieser Befehl ist nur für Spieler!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
FileConfiguration homes = plugin.getHomesConfig();
|
||||
String commandName = command.getName().toLowerCase();
|
||||
|
||||
if (commandName.equals("sethome")) {
|
||||
if (!player.hasPermission("survivalplus.homes.set")) {
|
||||
player.sendMessage(lang.getString("no-permission", "§cDu hast keine Berechtigung für diesen Befehl!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
player.sendMessage(lang.getString("sethome.usage", "§cVerwendung: /sethome <name>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String homeName = args[0].toLowerCase();
|
||||
if (!homeName.matches("[a-z0-9_]+")) {
|
||||
player.sendMessage(lang.getString("sethome.invalid-name", "§cDer Home-Name darf nur Buchstaben, Zahlen und Unterstriche enthalten!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String path = "homes." + player.getUniqueId() + "." + homeName;
|
||||
if (homes.contains(path)) {
|
||||
player.sendMessage(lang.getString("sethome.already-exists", "§cEin Home mit diesem Namen existiert bereits!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
int maxHomes = player.hasPermission("survivalplus.homes.unlimited") ? Integer.MAX_VALUE : plugin.getConfig().getInt("max-homes", 3);
|
||||
int currentHomes = homes.getConfigurationSection("homes." + player.getUniqueId()) != null ?
|
||||
homes.getConfigurationSection("homes." + player.getUniqueId()).getKeys(false).size() : 0;
|
||||
|
||||
if (currentHomes >= maxHomes) {
|
||||
player.sendMessage(lang.getString("sethome.limit-reached", "§cDu hast die maximale Anzahl an Homes erreicht!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Location loc = player.getLocation();
|
||||
homes.set(path + ".world", loc.getWorld().getName());
|
||||
homes.set(path + ".x", loc.getX());
|
||||
homes.set(path + ".y", loc.getY());
|
||||
homes.set(path + ".z", loc.getZ());
|
||||
homes.set(path + ".yaw", loc.getYaw());
|
||||
homes.set(path + ".pitch", loc.getPitch());
|
||||
plugin.saveHomesConfig();
|
||||
|
||||
player.sendMessage(lang.getString("sethome.success", "§aHome %name% wurde gesetzt!")
|
||||
.replace("%name%", homeName));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (commandName.equals("delhome")) {
|
||||
if (!player.hasPermission("survivalplus.homes.delete")) {
|
||||
player.sendMessage(lang.getString("no-permission", "§cDu hast keine Berechtigung für diesen Befehl!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
player.sendMessage(lang.getString("delhome.usage", "§cVerwendung: /delhome <name>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String homeName = args[0].toLowerCase();
|
||||
String path = "homes." + player.getUniqueId() + "." + homeName;
|
||||
if (!homes.contains(path)) {
|
||||
player.sendMessage(lang.getString("delhome.not-found", "§cDieses Home existiert nicht!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
homes.set(path, null);
|
||||
plugin.saveHomesConfig();
|
||||
player.sendMessage(lang.getString("delhome.success", "§aHome %name% wurde gelöscht!")
|
||||
.replace("%name%", homeName));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (commandName.equals("homelist")) {
|
||||
if (!player.hasPermission("survivalplus.homes.list")) {
|
||||
player.sendMessage(lang.getString("no-permission", "§cDu hast keine Berechtigung für diesen Befehl!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String path = "homes." + player.getUniqueId();
|
||||
if (!homes.contains(path) || homes.getConfigurationSection(path).getKeys(false).isEmpty()) {
|
||||
player.sendMessage(lang.getString("homelist.no-homes", "§cDu hast keine Homes gesetzt!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Inventory gui = Bukkit.createInventory(null, 27, lang.getString("homelist.gui-title", "Deine Homes"));
|
||||
List<String> homeNames = new ArrayList<>(homes.getConfigurationSection(path).getKeys(false));
|
||||
|
||||
for (int i = 0; i < Math.min(homeNames.size(), 27); i++) {
|
||||
String homeName = homeNames.get(i);
|
||||
String homePath = path + "." + homeName;
|
||||
ItemStack item = new ItemStack(Material.RED_BED);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName("§a" + homeName);
|
||||
List<String> lore = new ArrayList<>();
|
||||
lore.add("§7Welt: " + homes.getString(homePath + ".world"));
|
||||
lore.add("§7X: " + String.format("%.2f", homes.getDouble(homePath + ".x")));
|
||||
lore.add("§7Y: " + String.format("%.2f", homes.getDouble(homePath + ".y")));
|
||||
lore.add("§7Z: " + String.format("%.2f", homes.getDouble(homePath + ".z")));
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
gui.setItem(i, item);
|
||||
}
|
||||
|
||||
player.openInventory(gui);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,140 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class InventoryCommand implements CommandExecutor, Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public InventoryCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
public static class SnapshotHolder implements InventoryHolder {
|
||||
private final UUID targetUuid;
|
||||
private final boolean readOnly;
|
||||
|
||||
public SnapshotHolder(UUID targetUuid, boolean readOnly) {
|
||||
this.targetUuid = targetUuid;
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
public UUID getTargetUuid() {
|
||||
return targetUuid;
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(lang.getString("player-only"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
|
||||
if (!player.hasPermission("survivalplus.inventory.own")) {
|
||||
player.sendMessage(lang.getString("no-permission"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
player.sendMessage(lang.getString("inventory.usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String targetName = args[0];
|
||||
OfflinePlayer target = Bukkit.getOfflinePlayer(targetName);
|
||||
|
||||
Player onlineTarget = Bukkit.getPlayerExact(targetName);
|
||||
if (onlineTarget != null && onlineTarget.isOnline()) {
|
||||
if (!player.getName().equalsIgnoreCase(targetName) && !player.hasPermission("survivalplus.inventory.others")) {
|
||||
player.sendMessage(lang.getString("no-permission-others-inv"));
|
||||
return true;
|
||||
}
|
||||
|
||||
PlayerInventory targetInv = onlineTarget.getInventory();
|
||||
player.openInventory(targetInv);
|
||||
player.sendMessage(lang.getString("inventory.opened").replace("%player%", targetName));
|
||||
plugin.getLogger().log(Level.INFO, "Inventar von " + targetName + " (online) wurde von " + player.getName() + " geöffnet.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target.getName() == null || !target.hasPlayedBefore()) {
|
||||
player.sendMessage(lang.getString("player-not-found"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.getName().equalsIgnoreCase(targetName) && !player.hasPermission("survivalplus.inventory.others")) {
|
||||
player.sendMessage(lang.getString("no-permission-others-inv"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Offline-Inventare nicht editierbar
|
||||
player.sendMessage(lang.getString("inventory.offline-not-editable"));
|
||||
plugin.getLogger().log(Level.INFO, "Inventar von " + targetName + " ist offline — Live-Bearbeitung nicht möglich.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
InventoryHolder holder = event.getInventory().getHolder();
|
||||
if (holder instanceof SnapshotHolder) {
|
||||
SnapshotHolder sh = (SnapshotHolder) holder;
|
||||
if (sh.isReadOnly()) {
|
||||
if (event.getWhoClicked() instanceof Player) {
|
||||
Player p = (Player) event.getWhoClicked();
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
p.sendMessage(lang.getString("inventory.read-only"));
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryDrag(InventoryDragEvent event) {
|
||||
InventoryHolder holder = event.getInventory().getHolder();
|
||||
if (holder instanceof SnapshotHolder) {
|
||||
SnapshotHolder sh = (SnapshotHolder) holder;
|
||||
if (sh.isReadOnly()) {
|
||||
if (event.getWhoClicked() instanceof Player) {
|
||||
Player p = (Player) event.getWhoClicked();
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
p.sendMessage(lang.getString("inventory.read-only"));
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
public class ItemRenameCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public ItemRenameCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(ChatColor.RED + plugin.getMessage("ir.only-player"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("survivalplus.itemrename")) {
|
||||
player.sendMessage(ChatColor.RED + plugin.getMessage("ir.no-permission"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
player.sendMessage(ChatColor.RED + plugin.getMessage("ir.no-name"));
|
||||
player.sendMessage(ChatColor.YELLOW + plugin.getMessage("ir.usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemStack item = player.getInventory().getItemInMainHand();
|
||||
if (item == null || item.getType().isAir()) {
|
||||
player.sendMessage(ChatColor.RED + plugin.getMessage("ir.no-item"));
|
||||
return true;
|
||||
}
|
||||
|
||||
StringBuilder newNameBuilder = new StringBuilder();
|
||||
for (String arg : args) {
|
||||
newNameBuilder.append(arg).append(" ");
|
||||
}
|
||||
String newName = newNameBuilder.toString().trim();
|
||||
newName = ChatColor.translateAlternateColorCodes('&', newName);
|
||||
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (meta == null) {
|
||||
player.sendMessage(ChatColor.RED + plugin.getMessage("ir.cant-rename"));
|
||||
return true;
|
||||
}
|
||||
|
||||
meta.setDisplayName(newName);
|
||||
item.setItemMeta(meta);
|
||||
|
||||
player.sendMessage(ChatColor.GREEN + plugin.getMessage("ir.success").replace("{name}", newName));
|
||||
return true;
|
||||
}
|
||||
}
|
65
src/main/java/de/viper/survivalplus/commands/KitCommand.java
Normal file
65
src/main/java/de/viper/survivalplus/commands/KitCommand.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KitCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public KitCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (sender instanceof Player) {
|
||||
Player player = (Player) sender;
|
||||
|
||||
// Hole die Konfiguration
|
||||
FileConfiguration config = plugin.getConfig();
|
||||
|
||||
// Hole die Items aus der Konfiguration
|
||||
List<String> items = config.getStringList("first-join-kit.items");
|
||||
|
||||
for (String itemString : items) {
|
||||
// Teile den Item-String auf
|
||||
String[] itemParts = itemString.split(",");
|
||||
String materialName = itemParts[0].toUpperCase();
|
||||
int amount = Integer.parseInt(itemParts[1]);
|
||||
String displayName = itemParts.length > 2 ? itemParts[2] : "";
|
||||
|
||||
// Erstelle das Item
|
||||
Material material = Material.getMaterial(materialName);
|
||||
if (material == null) {
|
||||
player.sendMessage("Unbekanntes Item: " + materialName);
|
||||
continue; // Falls das Item ungültig ist, überspringe es
|
||||
}
|
||||
|
||||
ItemStack item = new ItemStack(material, amount);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
// Setze den Display-Namen (falls vorhanden)
|
||||
if (meta != null && !displayName.isEmpty()) {
|
||||
meta.setDisplayName(displayName);
|
||||
}
|
||||
|
||||
item.setItemMeta(meta);
|
||||
player.getInventory().addItem(item); // Gib das Item an den Spieler
|
||||
|
||||
}
|
||||
player.sendMessage("Du hast dein Kit erhalten!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import de.viper.survivalplus.listeners.MobLeashLimitListener;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class LeashCountCommand implements CommandExecutor {
|
||||
private final SurvivalPlus plugin;
|
||||
private final MobLeashLimitListener listener;
|
||||
|
||||
public LeashCountCommand(SurvivalPlus plugin, MobLeashLimitListener listener) {
|
||||
this.plugin = plugin;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getMessage("player-only"));
|
||||
return true;
|
||||
}
|
||||
Player player = (Player) sender;
|
||||
int count = listener.getLeashCount(player);
|
||||
player.sendMessage(plugin.getMessage("leashcount.message").replace("%count%", String.valueOf(count)));
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class NickCommand implements CommandExecutor {
|
||||
|
||||
private static final Pattern HEX_PATTERN = Pattern.compile("#[a-fA-F0-9]{6}");
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public NickCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("§cDieser Befehl ist nur für Spieler!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("survivalplus.nick")) {
|
||||
player.sendMessage("§cDu hast keine Berechtigung für diesen Befehl!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
player.sendMessage("§eBenutzung: /nick <Name>");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Name zusammensetzen
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String arg : args) {
|
||||
sb.append(arg).append(" ");
|
||||
}
|
||||
String rawNick = sb.toString().trim();
|
||||
|
||||
// Verbotene Nicks prüfen
|
||||
List<String> forbidden = plugin.getConfig().getStringList("forbidden-nicks");
|
||||
for (String word : forbidden) {
|
||||
if (rawNick.toLowerCase().contains(word.toLowerCase())) {
|
||||
player.sendMessage("§cDieser Nickname ist nicht erlaubt!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Farben anwenden
|
||||
String coloredNick = translateColors(rawNick);
|
||||
|
||||
// Format: [Nickname] (Klammern weiß, Nickname farbig)
|
||||
String finalNick = "§f[" + coloredNick + "§f]";
|
||||
|
||||
// Anwenden
|
||||
player.setDisplayName(finalNick);
|
||||
player.setPlayerListName(finalNick);
|
||||
|
||||
// Speichern (ungefärbten Namen)
|
||||
plugin.getNicknamesConfig().set(player.getUniqueId().toString(), rawNick);
|
||||
plugin.saveNicknamesConfig();
|
||||
|
||||
player.sendMessage("§aDein Nickname wurde zu " + finalNick + " geändert.");
|
||||
return true;
|
||||
}
|
||||
|
||||
private String translateColors(String input) {
|
||||
String withLegacy = org.bukkit.ChatColor.translateAlternateColorCodes('&', input);
|
||||
return replaceHexColors(withLegacy);
|
||||
}
|
||||
|
||||
private String replaceHexColors(String input) {
|
||||
Matcher matcher = HEX_PATTERN.matcher(input);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while (matcher.find()) {
|
||||
String hexCode = matcher.group();
|
||||
String replacement = ChatColor.of(hexCode).toString();
|
||||
matcher.appendReplacement(sb, replacement);
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class NightCommand implements CommandExecutor {
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public NightCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("§cNur Spieler können diesen Befehl ausführen!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("survivalplus.night")) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("no-permission", "§cDu hast keine Berechtigung!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
player.getWorld().setTime(13000); // Nacht setzen
|
||||
player.sendMessage("§aEs ist jetzt Nacht!");
|
||||
return true;
|
||||
}
|
||||
}
|
248
src/main/java/de/viper/survivalplus/commands/PluginCommand.java
Normal file
248
src/main/java/de/viper/survivalplus/commands/PluginCommand.java
Normal file
@@ -0,0 +1,248 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PluginCommand implements CommandExecutor {
|
||||
private final SurvivalPlus plugin;
|
||||
private static final int COMMANDS_PER_PAGE = 5;
|
||||
|
||||
public PluginCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
|
||||
// /sp oder /sp help
|
||||
if (args.length == 0 || args[0].equalsIgnoreCase("help")) {
|
||||
int page = 1;
|
||||
if (args.length > 1 && args[0].equalsIgnoreCase("help")) {
|
||||
try {
|
||||
page = Integer.parseInt(args[1]);
|
||||
if (page < 1) page = 1;
|
||||
} catch (NumberFormatException e) {
|
||||
sender.sendMessage(color(lang.getString(
|
||||
"sp.invalid-subcommand",
|
||||
"§cUngültiger Unterbefehl! Verwendung: /sp [reload|help|info|share]"
|
||||
)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
showHelp(sender, page);
|
||||
return true;
|
||||
}
|
||||
|
||||
// /sp reload
|
||||
if (args[0].equalsIgnoreCase("reload")) {
|
||||
if (!sender.hasPermission("survivalplus.reload")) {
|
||||
sender.sendMessage(color(lang.getString("sp.no-permission", "§cDu hast keine Berechtigung für diesen Befehl!")));
|
||||
return true;
|
||||
}
|
||||
plugin.reloadPlugin();
|
||||
sender.sendMessage(color(lang.getString("sp.plugin.reloaded", "§aSurvivalPlus wurde erfolgreich neu geladen!")));
|
||||
return true;
|
||||
}
|
||||
|
||||
// /sp info
|
||||
if (args[0].equalsIgnoreCase("info")) {
|
||||
sender.sendMessage(color(lang.getString("sp.info.header", "&7===== SurvivalPlus Info =====")));
|
||||
sender.sendMessage(color(lang.getString("sp.info.name", "&ePlugin-Name: &f") + plugin.getDescription().getName()));
|
||||
sender.sendMessage(color(lang.getString("sp.info.version", "&eVersion: &f") + plugin.getDescription().getVersion()));
|
||||
sender.sendMessage(color(lang.getString("sp.info.author", "&eErsteller: &f") + "M_Viper"));
|
||||
sender.sendMessage(color(lang.getString("sp.info.description", "&eBeschreibung:\n&f") + plugin.getDescription().getDescription()));
|
||||
|
||||
if (sender instanceof Player player) {
|
||||
// Überschrift über die Links
|
||||
player.sendMessage(ChatColor.GOLD + "Links:");
|
||||
|
||||
// Button: Spigot-Seite
|
||||
TextComponent spigotLink = new TextComponent(ChatColor.GREEN + "[Spigot-Seite]");
|
||||
spigotLink.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL,
|
||||
"https://www.spigotmc.org/resources/authors/m-lukas-17.618600/"));
|
||||
spigotLink.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
new ComponentBuilder(ChatColor.YELLOW + "Klicke, um die Spigot-Seite zu öffnen").create()
|
||||
));
|
||||
|
||||
// Button: Bugs melden (Git)
|
||||
TextComponent gitLink = new TextComponent(ChatColor.GREEN + " [Bugs melden]");
|
||||
gitLink.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL,
|
||||
"https://git.viper.ipv64.net/M_Viper/Survival-Plus/issues"));
|
||||
gitLink.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
new ComponentBuilder(ChatColor.YELLOW + "Klicke, um den Bug-Tracker zu öffnen").create()
|
||||
));
|
||||
|
||||
// Beide nebeneinander
|
||||
spigotLink.addExtra(gitLink);
|
||||
player.spigot().sendMessage(spigotLink);
|
||||
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.GOLD + "Links:");
|
||||
sender.sendMessage(ChatColor.GREEN + "[Spigot-Seite] "
|
||||
+ "https://www.spigotmc.org/resources/authors/m-lukas-17.618600/"
|
||||
+ ChatColor.GREEN + " [Bugs melden] "
|
||||
+ "https://git.viper.ipv64.net/M_Viper/Survival-Plus/issues");
|
||||
}
|
||||
|
||||
sender.sendMessage(color(lang.getString("sp.info.footer", "&7==========================")));
|
||||
return true;
|
||||
}
|
||||
|
||||
// /sp share → Vorschau mit Buttons
|
||||
if (args[0].equalsIgnoreCase("share")) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(color(lang.getString("player-only", "§cDieser Befehl ist nur für Spieler!")));
|
||||
return true;
|
||||
}
|
||||
|
||||
org.bukkit.Location loc = player.getLocation();
|
||||
String coordsMsg = color(lang.getString("sp.share.preview-format", "")
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%x%", String.valueOf(loc.getBlockX()))
|
||||
.replace("%y%", String.valueOf(loc.getBlockY()))
|
||||
.replace("%z%", String.valueOf(loc.getBlockZ()))
|
||||
.replace("%world%", loc.getWorld().getName())
|
||||
);
|
||||
|
||||
player.sendMessage(color(lang.getString("sp.share.preview-title", "§aDeine aktuellen Koordinaten wären:")));
|
||||
player.sendMessage(coordsMsg);
|
||||
|
||||
TextComponent sendBtn = new TextComponent(color(lang.getString("sp.share.send-button", "§a[✅ Senden]")));
|
||||
sendBtn.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/sp shareconfirm"));
|
||||
sendBtn.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
new ComponentBuilder(color(lang.getString("sp.share.send-hover",
|
||||
"§aKlicke, um deine Koordinaten an alle zu senden."))).create()
|
||||
));
|
||||
|
||||
TextComponent cancelBtn = new TextComponent(color(lang.getString("sp.share.cancel-button", "§c [❌ Abbrechen]")));
|
||||
cancelBtn.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/sp sharecancel"));
|
||||
cancelBtn.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
new ComponentBuilder(color(lang.getString("sp.share.cancel-hover",
|
||||
"§cKlicke, um das Senden abzubrechen."))).create()
|
||||
));
|
||||
|
||||
sendBtn.addExtra(cancelBtn);
|
||||
player.spigot().sendMessage(sendBtn);
|
||||
return true;
|
||||
}
|
||||
|
||||
// /sp shareconfirm → bestätigt und sendet
|
||||
if (args[0].equalsIgnoreCase("shareconfirm")) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(color(lang.getString("player-only", "§cDieser Befehl ist nur für Spieler!")));
|
||||
return true;
|
||||
}
|
||||
org.bukkit.Location loc = player.getLocation();
|
||||
String message = color(lang.getString("sp.share.preview-format", "")
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%x%", String.valueOf(loc.getBlockX()))
|
||||
.replace("%y%", String.valueOf(loc.getBlockY()))
|
||||
.replace("%z%", String.valueOf(loc.getBlockZ()))
|
||||
.replace("%world%", loc.getWorld().getName())
|
||||
);
|
||||
Bukkit.broadcastMessage(message);
|
||||
player.sendMessage(color(lang.getString("sp.share.sent", "§aKoordinaten gesendet.")));
|
||||
return true;
|
||||
}
|
||||
|
||||
// /sp sharecancel → bricht ab
|
||||
if (args[0].equalsIgnoreCase("sharecancel")) {
|
||||
if (sender instanceof Player p) {
|
||||
p.sendMessage(color(lang.getString("sp.share.cancelled", "§eSenden der Koordinaten abgebrochen.")));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ungültiger Unterbefehl
|
||||
sender.sendMessage(color(lang.getString(
|
||||
"sp.invalid-subcommand",
|
||||
"§cUngültiger Unterbefehl! Verwendung: /sp [reload|help|info|share]"
|
||||
)));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showHelp(CommandSender sender, int page) {
|
||||
FileConfiguration help = plugin.getHelpConfig();
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
|
||||
if (help == null || help.getConfigurationSection("commands") == null) {
|
||||
sender.sendMessage(color(lang.getString("sp.help-not-found", "&cHilfedatei (help.yml) konnte nicht geladen werden!")));
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> commands = new ArrayList<>(help.getConfigurationSection("commands").getKeys(false));
|
||||
if (commands.isEmpty()) {
|
||||
sender.sendMessage(color(lang.getString("sp.help-not-found", "&cKeine Befehle verfügbar.")));
|
||||
return;
|
||||
}
|
||||
|
||||
int totalPages = (int) Math.ceil((double) commands.size() / COMMANDS_PER_PAGE);
|
||||
if (page > totalPages) page = totalPages;
|
||||
if (page < 1) page = 1;
|
||||
|
||||
sender.sendMessage(color(help.getString("header", "&7===== &eSurvivalPlus Hilfe &7=====")));
|
||||
|
||||
int startIndex = (page - 1) * COMMANDS_PER_PAGE;
|
||||
int endIndex = Math.min(startIndex + COMMANDS_PER_PAGE, commands.size());
|
||||
|
||||
for (int i = startIndex; i < endIndex; i++) {
|
||||
String cmd = commands.get(i);
|
||||
String usage = help.getString("commands." + cmd + ".usage", "");
|
||||
String description = help.getString("commands." + cmd + ".description", "");
|
||||
sender.sendMessage(color(usage + " §7- " + description));
|
||||
}
|
||||
|
||||
if (sender instanceof Player player) {
|
||||
TextComponent navigation = new TextComponent();
|
||||
|
||||
if (page > 1) {
|
||||
TextComponent prev = new TextComponent(color(help.getString("navigation.prev", "« Vorherige ")));
|
||||
prev.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/sp help " + (page - 1)));
|
||||
navigation.addExtra(prev);
|
||||
} else {
|
||||
navigation.addExtra(color(help.getString("navigation.prev-disabled", "« ")));
|
||||
}
|
||||
|
||||
TextComponent pageInfo = new TextComponent(color(help.getString("navigation.page", " §fSeite {current} von {total} "))
|
||||
.replace("{current}", String.valueOf(page))
|
||||
.replace("{total}", String.valueOf(totalPages)));
|
||||
navigation.addExtra(pageInfo);
|
||||
|
||||
if (page < totalPages) {
|
||||
TextComponent next = new TextComponent(color(help.getString("navigation.next", " Nächste »")));
|
||||
next.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/sp help " + (page + 1)));
|
||||
navigation.addExtra(next);
|
||||
} else {
|
||||
navigation.addExtra(color(help.getString("navigation.next-disabled", " »")));
|
||||
}
|
||||
|
||||
player.spigot().sendMessage(navigation);
|
||||
} else {
|
||||
for (String cmd : commands) {
|
||||
String usage = help.getString("commands." + cmd + ".usage", "");
|
||||
String description = help.getString("commands." + cmd + ".description", "");
|
||||
sender.sendMessage(color(usage + " §7- " + description));
|
||||
}
|
||||
}
|
||||
|
||||
sender.sendMessage(color(help.getString("footer", "&7==========================")));
|
||||
}
|
||||
|
||||
private String color(String input) {
|
||||
return ChatColor.translateAlternateColorCodes('&', input == null ? "" : input);
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import de.viper.survivalplus.report.ReportManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class ReportCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final ReportManager reportManager;
|
||||
|
||||
public ReportCommand(SurvivalPlus plugin, ReportManager reportManager) {
|
||||
this.plugin = plugin;
|
||||
this.reportManager = reportManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("report.only-players", "§cNur Spieler können diesen Befehl ausführen!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("report.usage", "§cVerwendung: /report <Spieler> [Grund]"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String targetName = args[0];
|
||||
String reason = "Kein Grund angegeben";
|
||||
if (args.length > 1) {
|
||||
reason = String.join(" ", java.util.Arrays.copyOfRange(args, 1, args.length));
|
||||
}
|
||||
|
||||
if (Bukkit.getPlayer(targetName) == null) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("report.player-not-online", "§cDieser Spieler ist nicht online!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
reportManager.addReport(targetName, player.getName(), reason, time);
|
||||
|
||||
player.sendMessage(plugin.getLangConfig().getString("report.success", "§aDein Report wurde erfolgreich gesendet."));
|
||||
|
||||
// Nachricht an Admins
|
||||
String msg = plugin.getLangConfig().getString("report.notify-admin",
|
||||
"§cREPORT§r: %reporter% hat %target% gemeldet. Grund: %reason%")
|
||||
.replace("%reporter%", player.getName())
|
||||
.replace("%target%", targetName)
|
||||
.replace("%reason%", reason);
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p.hasPermission("survivalplus.report.receive"))
|
||||
.forEach(p -> p.sendMessage(msg));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
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 de.viper.survivalplus.SurvivalPlus;
|
||||
|
||||
public class SetSpawnCommand implements CommandExecutor {
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public SetSpawnCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("Nur Spieler können diesen Befehl verwenden!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("survivalplus.setspawn")) {
|
||||
player.sendMessage("§cDu hast keine Rechte für diesen Befehl.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Location loc = player.getLocation();
|
||||
plugin.getConfig().set("spawn.world", loc.getWorld().getName());
|
||||
plugin.getConfig().set("spawn.x", loc.getX());
|
||||
plugin.getConfig().set("spawn.y", loc.getY());
|
||||
plugin.getConfig().set("spawn.z", loc.getZ());
|
||||
plugin.getConfig().set("spawn.yaw", loc.getYaw());
|
||||
plugin.getConfig().set("spawn.pitch", loc.getPitch());
|
||||
plugin.saveConfig();
|
||||
|
||||
player.sendMessage("§aSpawnpunkt erfolgreich gesetzt!");
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.Manager.Warp;
|
||||
import de.viper.survivalplus.Manager.WarpManager;
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.ChatColor;
|
||||
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 org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class SetWarpCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final WarpManager warpManager;
|
||||
|
||||
public SetWarpCommand(SurvivalPlus plugin, WarpManager warpManager) {
|
||||
this.plugin = plugin;
|
||||
this.warpManager = warpManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getMessage("warp.only_players"));
|
||||
return true;
|
||||
}
|
||||
Player player = (Player) sender;
|
||||
|
||||
if (args.length < 1) {
|
||||
player.sendMessage(ChatColor.RED + "Benutze: /setwarp <name>");
|
||||
return true;
|
||||
}
|
||||
|
||||
String warpName = args[0];
|
||||
|
||||
int maxWarps = plugin.getConfig().getInt("maxWarpsPerPlayer", 5);
|
||||
int currentWarpCount = warpManager.getWarpCountForPlayer(player.getName());
|
||||
|
||||
Warp existingWarp = warpManager.getWarp(player.getName(), warpName);
|
||||
|
||||
// Limit prüfen - Falls Warp mit dem Namen schon existiert, Update erlaubt
|
||||
if (currentWarpCount >= maxWarps && existingWarp == null) {
|
||||
player.sendMessage(ChatColor.RED + "Du hast das maximale Warp-Limit von " + maxWarps + " erreicht.");
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemStack item = player.getInventory().getItemInMainHand();
|
||||
|
||||
// Default Item wenn leer (aus config oder Schild)
|
||||
if (item == null || item.getType().isAir()) {
|
||||
String defaultItemName = plugin.getConfig().getString("defaultWarpItem", "OAK_SIGN");
|
||||
try {
|
||||
item = new org.bukkit.inventory.ItemStack(org.bukkit.Material.valueOf(defaultItemName));
|
||||
} catch (IllegalArgumentException e) {
|
||||
item = new org.bukkit.inventory.ItemStack(org.bukkit.Material.OAK_SIGN);
|
||||
}
|
||||
}
|
||||
|
||||
Location loc = player.getLocation();
|
||||
Warp warp = new Warp(player.getName(), warpName, item, loc.getWorld().getName(), loc.getX(), loc.getY(), loc.getZ());
|
||||
warpManager.addWarp(warp);
|
||||
player.sendMessage(plugin.getMessage("warp.set_success").replace("%warp%", warpName));
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SetWorldSpawnCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public SetWorldSpawnCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(ChatColor.RED + "Dieser Befehl kann nur von einem Spieler verwendet werden.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("survivalplus.setworldspawn")) {
|
||||
player.sendMessage(ChatColor.RED + "Du hast keine Rechte für diesen Befehl.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Location loc = player.getLocation();
|
||||
World world = player.getWorld();
|
||||
world.setSpawnLocation(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
player.sendMessage(ChatColor.GREEN + "Spawnpunkt gesetzt bei §e" +
|
||||
loc.getBlockX() + " " + loc.getBlockY() + " " + loc.getBlockZ());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.Manager.ShopManager;
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import de.viper.survivalplus.gui.ShopGui;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ShopCommand implements CommandExecutor {
|
||||
|
||||
private final ShopManager shopManager;
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public ShopCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
this.shopManager = new ShopManager(plugin);
|
||||
}
|
||||
|
||||
private String getMessage(String key) {
|
||||
return plugin.getMessage("shop." + key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(getMessage("only-players"));
|
||||
return true;
|
||||
}
|
||||
Player player = (Player) sender;
|
||||
|
||||
// Shop-GUI öffnen, wenn kein Argument oder "gui"
|
||||
if (args.length == 0 || (args.length > 0 && args[0].toLowerCase().equals("gui"))) {
|
||||
ShopGui shopGui = new ShopGui(plugin, player, shopManager);
|
||||
Bukkit.getPluginManager().registerEvents(shopGui, plugin);
|
||||
player.openInventory(shopGui.getInventory());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 3) {
|
||||
sender.sendMessage(getMessage("usage-add"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!args[0].toLowerCase().equals("add")) {
|
||||
sender.sendMessage(getMessage("unknown-subcommand"));
|
||||
return false;
|
||||
}
|
||||
|
||||
ItemStack itemInHand = player.getInventory().getItemInMainHand();
|
||||
if (itemInHand == null || itemInHand.getType() == Material.AIR) {
|
||||
sender.sendMessage(ChatColor.RED + "Du musst das Item, das du hinzufügen willst, in der Hand halten!");
|
||||
return true;
|
||||
}
|
||||
|
||||
String itemKey = itemInHand.getType().name().toLowerCase();
|
||||
|
||||
double basePrice;
|
||||
int stock;
|
||||
|
||||
try {
|
||||
basePrice = Double.parseDouble(args[1]);
|
||||
stock = Integer.parseInt(args[2]);
|
||||
} catch (NumberFormatException e) {
|
||||
sender.sendMessage(getMessage("number-error"));
|
||||
return false;
|
||||
}
|
||||
|
||||
shopManager.addOrUpdateItem(itemKey, basePrice, stock);
|
||||
|
||||
String msg = getMessage("item-added")
|
||||
.replace("{item}", itemKey)
|
||||
.replace("{price}", args[1])
|
||||
.replace("{stock}", args[2]);
|
||||
sender.sendMessage(msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class ShowArmorStandsCommand implements CommandExecutor {
|
||||
|
||||
private final JavaPlugin plugin;
|
||||
|
||||
public ShowArmorStandsCommand(JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!sender.hasPermission("survivalplus.showarmorstands")) {
|
||||
sender.sendMessage("§cDu hast keine Rechte für diesen Befehl.");
|
||||
return true;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
for (Entity entity : world.getEntities()) {
|
||||
if (entity instanceof ArmorStand) {
|
||||
ArmorStand armorStand = (ArmorStand) entity;
|
||||
if (!armorStand.isVisible()) {
|
||||
armorStand.setVisible(true);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sender.sendMessage("§a" + count + " unsichtbare Armor Stands wurden sichtbar gemacht.");
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import de.viper.survivalplus.report.ReportManager;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ShowReportCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final ReportManager reportManager;
|
||||
|
||||
public ShowReportCommand(SurvivalPlus plugin, ReportManager reportManager) {
|
||||
this.plugin = plugin;
|
||||
this.reportManager = reportManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("showreport.only-players", "§cNur Spieler können diesen Befehl ausführen!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("survivalplus.report.show")) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("no-permission", "§cDu hast keine Berechtigung!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("showreport.usage", "§cVerwendung: /showreport <Spieler>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String targetName = args[0];
|
||||
List<String> reports = reportManager.getReports(targetName);
|
||||
|
||||
if (reports.isEmpty()) {
|
||||
player.sendMessage(plugin.getLangConfig().getString("showreport.no-reports", "§aEs wurden keine Reports für diesen Spieler gefunden."));
|
||||
return true;
|
||||
}
|
||||
|
||||
player.sendMessage("§6--- Reports für Spieler " + targetName + " ---");
|
||||
reports.forEach(r -> player.sendMessage("§7" + r));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
57
src/main/java/de/viper/survivalplus/commands/SitCommand.java
Normal file
57
src/main/java/de/viper/survivalplus/commands/SitCommand.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import de.viper.survivalplus.listeners.SitListener;
|
||||
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 org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class SitCommand implements CommandExecutor {
|
||||
private final SurvivalPlus plugin;
|
||||
private final SitListener sitListener;
|
||||
|
||||
public SitCommand(SurvivalPlus plugin, SitListener sitListener) {
|
||||
this.plugin = plugin;
|
||||
this.sitListener = sitListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("player-only", "§cDieser Befehl ist nur für Spieler!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
|
||||
if (!player.hasPermission("survivalplus.sit")) {
|
||||
player.sendMessage(lang.getString("no-permission", "§cDu hast keine Berechtigung für diesen Befehl!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 0) {
|
||||
player.sendMessage(lang.getString("sit.usage", "§cVerwendung: /sit"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Prüfe, ob der Spieler bereits sitzt
|
||||
if (sitListener.isSitting(player)) {
|
||||
sitListener.standUp(player);
|
||||
player.sendMessage(lang.getString("sit.stand-up", "§aDu bist aufgestanden!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Setze den Spieler mittig auf den Block und leicht oberhalb (Fix)
|
||||
Location location = player.getLocation();
|
||||
location.setX(location.getBlockX() + 0.5);
|
||||
location.setY(location.getBlockY() + 0.25);
|
||||
location.setZ(location.getBlockZ() + 0.5);
|
||||
|
||||
sitListener.sitPlayer(player, location);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class SpawnCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public SpawnCommand(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getMessage("spawn.only_player"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
World world = player.getWorld();
|
||||
Location spawnLocation = world.getSpawnLocation();
|
||||
|
||||
if (spawnLocation == null) {
|
||||
player.sendMessage(plugin.getMessage("spawn.no_spawn_found"));
|
||||
return true;
|
||||
}
|
||||
|
||||
player.teleport(spawnLocation);
|
||||
player.sendMessage(plugin.getMessage("spawn.teleported"));
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.fun.FunChallenge;
|
||||
import de.viper.survivalplus.fun.FunChallengeManager;
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class StartFunChallengeCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final FunChallengeManager challengeManager;
|
||||
|
||||
public StartFunChallengeCommand(SurvivalPlus plugin, FunChallengeManager challengeManager) {
|
||||
this.plugin = plugin;
|
||||
this.challengeManager = challengeManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("challenge.only_players"));
|
||||
return true;
|
||||
}
|
||||
if (args.length < 1) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("challenge.usage"));
|
||||
return true;
|
||||
}
|
||||
String challengeName = args[0];
|
||||
for (FunChallenge fc : challengeManager.getChallenges()) {
|
||||
if (fc.getName().equalsIgnoreCase(challengeName)) {
|
||||
fc.setActive(true);
|
||||
String msg = plugin.getLangConfig()
|
||||
.getString("challenge.start_success")
|
||||
.replace("%challenge%", fc.getDescription());
|
||||
sender.sendMessage(msg);
|
||||
// Hier ggf. Timer und Tracking starten!
|
||||
plugin.saveConfig();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
String failMsg = plugin.getLangConfig()
|
||||
.getString("challenge.start_fail")
|
||||
.replace("%challenge%", challengeName);
|
||||
sender.sendMessage(failMsg);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.Manager.StatsManager;
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class StatsCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final StatsManager statsManager;
|
||||
|
||||
public StatsCommand(SurvivalPlus plugin, StatsManager statsManager) {
|
||||
this.plugin = plugin;
|
||||
this.statsManager = statsManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getMessage("stats.only_player"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
|
||||
long time = statsManager.getPlayTime(player.getUniqueId());
|
||||
int kills = statsManager.getKills(player.getUniqueId());
|
||||
int deaths = statsManager.getDeaths(player.getUniqueId());
|
||||
int placed = statsManager.getBlocksPlaced(player.getUniqueId());
|
||||
int broken = statsManager.getBlocksBroken(player.getUniqueId());
|
||||
|
||||
if (time == 0 && kills == 0 && deaths == 0 && placed == 0 && broken == 0) {
|
||||
player.sendMessage(plugin.getMessage("stats.no_stats"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// K/D Ratio berechnen (vermeide Division durch 0)
|
||||
String kdRatio = deaths > 0 ? String.format("%.2f", (double) kills / deaths) : "∞";
|
||||
|
||||
// Zusätzliche Minecraft Statistik
|
||||
int jumps = player.getStatistic(org.bukkit.Statistic.JUMP);
|
||||
double walkKm = player.getStatistic(org.bukkit.Statistic.WALK_ONE_CM) / 100_000.0; // cm zu km
|
||||
|
||||
player.sendMessage(plugin.getMessage("stats.header").replace("{player}", player.getName()));
|
||||
player.sendMessage(plugin.getMessage("stats.playtime").replace("{time}", formatPlayTime(time)));
|
||||
player.sendMessage(plugin.getMessage("stats.kills").replace("{kills}", String.valueOf(kills)));
|
||||
player.sendMessage(plugin.getMessage("stats.deaths").replace("{deaths}", String.valueOf(deaths)));
|
||||
player.sendMessage(plugin.getMessage("stats.kd_ratio").replace("{kd}", kdRatio));
|
||||
player.sendMessage(plugin.getMessage("stats.blocks_placed").replace("{placed}", String.valueOf(placed)));
|
||||
player.sendMessage(plugin.getMessage("stats.blocks_broken").replace("{broken}", String.valueOf(broken)));
|
||||
player.sendMessage(plugin.getMessage("stats.jumps").replace("{jumps}", String.valueOf(jumps)));
|
||||
player.sendMessage(plugin.getMessage("stats.walked").replace("{walked}", String.format("%.2f", walkKm)));
|
||||
player.sendMessage(plugin.getMessage("stats.footer"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private String formatPlayTime(long seconds) {
|
||||
long hours = seconds / 3600;
|
||||
long minutes = (seconds % 3600) / 60;
|
||||
long secs = seconds % 60;
|
||||
|
||||
return String.format("%02dh %02dm %02ds", hours, minutes, secs);
|
||||
}
|
||||
}
|
@@ -0,0 +1,157 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TeleportCommands implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final Map<UUID, UUID> teleportRequests = new HashMap<>();
|
||||
|
||||
public TeleportCommands(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getMessage("only-players"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
String cmd = label.toLowerCase();
|
||||
|
||||
switch (cmd) {
|
||||
case "tp":
|
||||
return handleTp(player, args);
|
||||
case "tphere":
|
||||
return handleTphere(player, args);
|
||||
case "tpa":
|
||||
return handleTpa(player, args);
|
||||
case "tpaccept":
|
||||
return handleTpAccept(player);
|
||||
case "tpdeny":
|
||||
return handleTpDeny(player);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleTp(Player sender, String[] args) {
|
||||
if (!sender.hasPermission("survivalplus.tp")) {
|
||||
sender.sendMessage(plugin.getMessage("no-permission"));
|
||||
return true;
|
||||
}
|
||||
if (args.length != 1) {
|
||||
sender.sendMessage(plugin.getMessage("teleport-usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayer(args[0]);
|
||||
if (target == null) {
|
||||
sender.sendMessage(plugin.getMessage("player-not-found").replace("%player%", args[0]));
|
||||
return true;
|
||||
}
|
||||
|
||||
sender.teleport(target);
|
||||
sender.sendMessage(plugin.getMessage("teleport-success").replace("%player%", target.getName()));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleTphere(Player sender, String[] args) {
|
||||
if (!sender.hasPermission("survivalplus.tphere")) {
|
||||
sender.sendMessage(plugin.getMessage("no-permission"));
|
||||
return true;
|
||||
}
|
||||
if (args.length != 1) {
|
||||
sender.sendMessage(plugin.getMessage("tphere-usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayer(args[0]);
|
||||
if (target == null) {
|
||||
sender.sendMessage(plugin.getMessage("player-not-found").replace("%player%", args[0]));
|
||||
return true;
|
||||
}
|
||||
|
||||
target.teleport(sender);
|
||||
sender.sendMessage(plugin.getMessage("tphere-success").replace("%player%", target.getName()));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleTpa(Player sender, String[] args) {
|
||||
if (!sender.hasPermission("survivalplus.tpa")) {
|
||||
sender.sendMessage(plugin.getMessage("no-permission"));
|
||||
return true;
|
||||
}
|
||||
if (args.length != 1) {
|
||||
sender.sendMessage(plugin.getMessage("tpa-usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayer(args[0]);
|
||||
if (target == null) {
|
||||
sender.sendMessage(plugin.getMessage("player-not-found").replace("%player%", args[0]));
|
||||
return true;
|
||||
}
|
||||
|
||||
teleportRequests.put(target.getUniqueId(), sender.getUniqueId());
|
||||
sender.sendMessage(plugin.getMessage("tpa-sent").replace("%player%", target.getName()));
|
||||
target.sendMessage(plugin.getMessage("tpa-received").replace("%player%", sender.getName()));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleTpAccept(Player target) {
|
||||
if (!target.hasPermission("survivalplus.tpaccept")) {
|
||||
target.sendMessage(plugin.getMessage("no-permission"));
|
||||
return true;
|
||||
}
|
||||
|
||||
UUID senderId = teleportRequests.remove(target.getUniqueId());
|
||||
if (senderId == null) {
|
||||
target.sendMessage(plugin.getMessage("no-tpa-request"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player sender = Bukkit.getPlayer(senderId);
|
||||
if (sender == null) {
|
||||
target.sendMessage(plugin.getMessage("player-not-found"));
|
||||
return true;
|
||||
}
|
||||
|
||||
sender.teleport(target);
|
||||
sender.sendMessage(plugin.getMessage("tpa-accepted").replace("%player%", target.getName()));
|
||||
target.sendMessage(plugin.getMessage("tpaccept-success").replace("%player%", sender.getName()));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleTpDeny(Player target) {
|
||||
if (!target.hasPermission("survivalplus.tpdeny")) {
|
||||
target.sendMessage(plugin.getMessage("no-permission"));
|
||||
return true;
|
||||
}
|
||||
|
||||
UUID senderId = teleportRequests.remove(target.getUniqueId());
|
||||
if (senderId == null) {
|
||||
target.sendMessage(plugin.getMessage("no-tpa-request"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player sender = Bukkit.getPlayer(senderId);
|
||||
if (sender != null) {
|
||||
sender.sendMessage(plugin.getMessage("tpa-denied").replace("%player%", target.getName()));
|
||||
}
|
||||
|
||||
target.sendMessage(plugin.getMessage("tpdeny-success"));
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import de.viper.survivalplus.trade.TradeManager;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class TradeAcceptCommand implements CommandExecutor {
|
||||
|
||||
private final TradeManager tradeManager;
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public TradeAcceptCommand(SurvivalPlus plugin, TradeManager tradeManager) {
|
||||
this.plugin = plugin;
|
||||
this.tradeManager = tradeManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender senderS, Command command, String label, String[] args) {
|
||||
if (!(senderS instanceof Player target)) {
|
||||
senderS.sendMessage(plugin.getLangConfig().getString("only-players", "§cNur Spieler können diesen Befehl ausführen!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
target.sendMessage(plugin.getLangConfig().getString("trade.accept.usage", "§cVerwendung: /tradeaccept <Spieler>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
tradeManager.acceptTrade(target, args[0]);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import de.viper.survivalplus.trade.TradeManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class TradeCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final TradeManager tradeManager;
|
||||
|
||||
public TradeCommand(SurvivalPlus plugin, TradeManager tradeManager) {
|
||||
this.plugin = plugin;
|
||||
this.tradeManager = tradeManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender senderS, Command command, String label, String[] args) {
|
||||
if (!(senderS instanceof Player sender)) {
|
||||
senderS.sendMessage(plugin.getLangConfig().getString("only-players", "§cNur Spieler können diesen Befehl ausführen!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("trade.usage", "§cVerwendung: /trade <Spieler>"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayerExact(args[0]);
|
||||
if (target == null || !target.isOnline()) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("trade.player-not-online", "§cDieser Spieler ist nicht online!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
tradeManager.requestTrade(sender, target);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
public class TrashCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("Nur Spieler können diesen Befehl ausführen.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Inventory trash = Bukkit.createInventory(player, 9 * 3, "Trash");
|
||||
player.openInventory(trash);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.Manager.BlockManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class UnblockCommand implements CommandExecutor {
|
||||
|
||||
private final BlockManager blockManager;
|
||||
private final FileConfiguration config;
|
||||
|
||||
public UnblockCommand(BlockManager blockManager, FileConfiguration config) {
|
||||
this.blockManager = blockManager;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(config.getString("messages.general.only_players"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length != 1) {
|
||||
player.sendMessage(config.getString("messages.unblock.usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayerExact(args[0]);
|
||||
if (target == null || target == player) {
|
||||
player.sendMessage(config.getString("messages.unblock.invalid_player"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (blockManager.hasBlocked(player, target)) {
|
||||
blockManager.unblockPlayer(player, target);
|
||||
player.sendMessage(config.getString("messages.unblock.unblocked").replace("%player%", target.getName()));
|
||||
target.sendMessage(config.getString("messages.unblock.unblocked_by").replace("%player%", player.getName()));
|
||||
} else {
|
||||
player.sendMessage(config.getString("messages.unblock.not_blocked").replace("%player%", target.getName()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import de.viper.survivalplus.Manager.Warp;
|
||||
import de.viper.survivalplus.Manager.WarpManager;
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WarpsCommand implements CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final WarpManager warpManager;
|
||||
|
||||
public WarpsCommand(SurvivalPlus plugin, WarpManager warpManager) {
|
||||
this.plugin = plugin;
|
||||
this.warpManager = warpManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getMessage("warp.only_players"));
|
||||
return true;
|
||||
}
|
||||
Player player = (Player) sender;
|
||||
|
||||
Map<String, List<Warp>> warpsByOwner = warpManager.getWarps().values().stream()
|
||||
.collect(Collectors.groupingBy(Warp::getOwner));
|
||||
|
||||
List<String> ownersSorted = new ArrayList<>(warpsByOwner.keySet());
|
||||
Collections.sort(ownersSorted);
|
||||
|
||||
int totalWarps = warpManager.getWarps().size();
|
||||
int size = ((totalWarps + 8) / 9) * 9;
|
||||
if (size < 27) size = 27; // mindestens 27 Slots
|
||||
|
||||
Inventory inv = Bukkit.createInventory(null, size, ChatColor.GOLD + "Player Warps");
|
||||
|
||||
int slot = 0;
|
||||
for (String owner : ownersSorted) {
|
||||
for (Warp warp : warpsByOwner.get(owner)) {
|
||||
if (slot >= size) break;
|
||||
|
||||
ItemStack item = warp.getItem().clone();
|
||||
item.setAmount(1);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (meta != null) {
|
||||
meta.setDisplayName(ChatColor.YELLOW + warp.getName());
|
||||
List<String> lore = new ArrayList<>();
|
||||
lore.add(ChatColor.GRAY + "Owner: " + warp.getOwner());
|
||||
lore.add(ChatColor.GRAY + "World: " + warp.getWorldName());
|
||||
meta.setLore(lore);
|
||||
meta.setUnbreakable(true);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
inv.setItem(slot++, item);
|
||||
}
|
||||
if (slot >= size) break;
|
||||
}
|
||||
|
||||
player.openInventory(inv);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package de.viper.survivalplus.commands;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class WorkbenchCommand implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("Nur Spieler können diesen Befehl ausführen.");
|
||||
return true;
|
||||
}
|
||||
|
||||
player.openWorkbench(null, true); // Öffnet die Werkbank-GUI für den Spieler
|
||||
return true;
|
||||
}
|
||||
}
|
39
src/main/java/de/viper/survivalplus/fun/FunChallenge.java
Normal file
39
src/main/java/de/viper/survivalplus/fun/FunChallenge.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package de.viper.survivalplus.fun;
|
||||
|
||||
public class FunChallenge {
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
private String type;
|
||||
private String item;
|
||||
private int amount;
|
||||
private int timeLimitMinutes;
|
||||
private boolean active;
|
||||
private String reward;
|
||||
|
||||
public FunChallenge() {}
|
||||
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getItem() { return item; }
|
||||
public void setItem(String item) { this.item = item; }
|
||||
|
||||
public int getAmount() { return amount; }
|
||||
public void setAmount(int amount) { this.amount = amount; }
|
||||
|
||||
public int getTimeLimitMinutes() { return timeLimitMinutes; }
|
||||
public void setTimeLimitMinutes(int timeLimitMinutes) { this.timeLimitMinutes = timeLimitMinutes; }
|
||||
|
||||
public boolean isActive() { return active; }
|
||||
public void setActive(boolean active) { this.active = active; }
|
||||
|
||||
public String getReward() { return reward; }
|
||||
public void setReward(String reward) { this.reward = reward; }
|
||||
}
|
122
src/main/java/de/viper/survivalplus/fun/FunChallengeManager.java
Normal file
122
src/main/java/de/viper/survivalplus/fun/FunChallengeManager.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package de.viper.survivalplus.fun;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.boss.BarStyle;
|
||||
import org.bukkit.boss.BossBar;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FunChallengeManager {
|
||||
|
||||
private final List<FunChallenge> challenges = new ArrayList<>();
|
||||
private final Map<String, Integer> globalProgress = new HashMap<>(); // Fortschritt global für alle Spieler
|
||||
private final Map<Player, BossBar> playerBossBars = new HashMap<>();
|
||||
private BukkitRunnable bossBarTask;
|
||||
|
||||
public void load(FileConfiguration config) {
|
||||
challenges.clear();
|
||||
globalProgress.clear();
|
||||
if (config.contains("funChallenges")) {
|
||||
for (Map<?, ?> entry : config.getMapList("funChallenges")) {
|
||||
FunChallenge fc = new FunChallenge();
|
||||
fc.setName((String) entry.get("name"));
|
||||
fc.setDescription((String) entry.get("description"));
|
||||
fc.setType((String) entry.get("type"));
|
||||
fc.setItem((String) entry.get("item"));
|
||||
fc.setAmount((Integer) entry.get("amount"));
|
||||
fc.setTimeLimitMinutes((Integer) entry.get("timeLimitMinutes"));
|
||||
fc.setActive(Boolean.parseBoolean(entry.get("active").toString()));
|
||||
fc.setReward((String) entry.get("reward"));
|
||||
challenges.add(fc);
|
||||
globalProgress.put(fc.getName(), 0);
|
||||
}
|
||||
}
|
||||
startBossBar(); // automatisch BossBar starten, falls eine Challenge aktiv ist
|
||||
}
|
||||
|
||||
public List<FunChallenge> getChallenges() { return challenges; }
|
||||
|
||||
public FunChallenge getActiveChallenge() {
|
||||
for (FunChallenge c : challenges) {
|
||||
if (c.isActive()) return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getGlobalProgress(String challengeName) {
|
||||
return globalProgress.getOrDefault(challengeName, 0);
|
||||
}
|
||||
|
||||
public void setGlobalProgress(String challengeName, int amount) {
|
||||
globalProgress.put(challengeName, amount);
|
||||
}
|
||||
|
||||
public void resetProgress(String challengeName) {
|
||||
globalProgress.put(challengeName, 0);
|
||||
}
|
||||
|
||||
// ====================== BossBar-Funktion ======================
|
||||
|
||||
public void startBossBar() {
|
||||
FunChallenge active = getActiveChallenge();
|
||||
if (active == null) return;
|
||||
|
||||
stopBossBar(); // alte Bars entfernen, falls vorhanden
|
||||
|
||||
int totalTime = active.getTimeLimitMinutes() * 60; // Gesamtzeit in Sekunden
|
||||
final int[] timeLeft = {totalTime};
|
||||
|
||||
bossBarTask = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (timeLeft[0] <= 0 || getActiveChallenge() == null) {
|
||||
stopBossBar();
|
||||
return;
|
||||
}
|
||||
|
||||
double progress = (double) timeLeft[0] / totalTime;
|
||||
String formattedTime = formatTime(timeLeft[0]);
|
||||
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
BossBar bar = playerBossBars.computeIfAbsent(player, p -> {
|
||||
BossBar newBar = Bukkit.createBossBar(
|
||||
active.getName() + " (" + formattedTime + ")",
|
||||
BarColor.BLUE,
|
||||
BarStyle.SOLID
|
||||
);
|
||||
newBar.addPlayer(p);
|
||||
return newBar;
|
||||
});
|
||||
|
||||
bar.setProgress(progress);
|
||||
bar.setTitle(active.getName() + " (" + formattedTime + ")");
|
||||
}
|
||||
|
||||
timeLeft[0]--;
|
||||
}
|
||||
};
|
||||
|
||||
bossBarTask.runTaskTimer(Bukkit.getPluginManager().getPlugin("SurvivalPlus"), 0L, 20L);
|
||||
}
|
||||
|
||||
public void stopBossBar() {
|
||||
if (bossBarTask != null) bossBarTask.cancel();
|
||||
for (BossBar bar : playerBossBars.values()) {
|
||||
bar.removeAll();
|
||||
}
|
||||
playerBossBars.clear();
|
||||
}
|
||||
|
||||
private String formatTime(int seconds) {
|
||||
int minutes = seconds / 60;
|
||||
int sec = seconds % 60;
|
||||
return String.format("%02d:%02d", minutes, sec);
|
||||
}
|
||||
}
|
129
src/main/java/de/viper/survivalplus/gui/ShopGui.java
Normal file
129
src/main/java/de/viper/survivalplus/gui/ShopGui.java
Normal file
@@ -0,0 +1,129 @@
|
||||
package de.viper.survivalplus.gui;
|
||||
|
||||
import de.viper.survivalplus.Manager.ShopManager;
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ShopGui implements Listener {
|
||||
|
||||
private final ShopManager shopManager;
|
||||
private final Player player;
|
||||
private Inventory inv;
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public ShopGui(SurvivalPlus plugin, Player player, ShopManager shopManager) {
|
||||
this.plugin = plugin;
|
||||
this.player = player;
|
||||
this.shopManager = shopManager;
|
||||
createInventory();
|
||||
}
|
||||
|
||||
private void createInventory() {
|
||||
inv = Bukkit.createInventory(null, 27, "Shop");
|
||||
|
||||
if (shopManager.getShopConfig().getConfigurationSection("items") == null) {
|
||||
player.sendMessage(ChatColor.RED + "Der Shop ist momentan leer.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Alle Items aus shop.yml einlesen
|
||||
for (String itemKey : shopManager.getShopConfig().getConfigurationSection("items").getKeys(false)) {
|
||||
Material mat = getMaterialFromKey(itemKey);
|
||||
if (mat == null) {
|
||||
player.sendMessage(ChatColor.RED + "Material für '" + itemKey + "' konnte nicht gefunden werden.");
|
||||
continue;
|
||||
}
|
||||
|
||||
addShopItem(itemKey, mat, 64);
|
||||
addShopItem(itemKey, mat, 16);
|
||||
addShopItem(itemKey, mat, 1);
|
||||
}
|
||||
|
||||
player.openInventory(inv);
|
||||
}
|
||||
|
||||
private Material getMaterialFromKey(String key) {
|
||||
try {
|
||||
return Material.valueOf(key.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void addShopItem(String itemKey, Material material, int amount) {
|
||||
double pricePerUnit = shopManager.getCurrentPrice(itemKey);
|
||||
double totalPrice = pricePerUnit * amount;
|
||||
|
||||
ItemStack item = new ItemStack(material, amount);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (meta != null) {
|
||||
meta.setDisplayName(ChatColor.GREEN.toString() + amount + "x " + material.name());
|
||||
meta.setLore(Arrays.asList(
|
||||
ChatColor.YELLOW + "Preis pro Stück: " + pricePerUnit,
|
||||
ChatColor.YELLOW + "Gesamtpreis: " + totalPrice,
|
||||
ChatColor.GRAY + "Klicke, um zu kaufen"
|
||||
));
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
for (int i = 0; i < inv.getSize(); i++) {
|
||||
if (inv.getItem(i) == null) {
|
||||
inv.setItem(i, item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent e) {
|
||||
if (!e.getView().getTitle().equals("Shop")) return;
|
||||
if (e.getClickedInventory() == null) return;
|
||||
if (!e.getWhoClicked().equals(player)) return;
|
||||
|
||||
e.setCancelled(true);
|
||||
|
||||
ItemStack clicked = e.getCurrentItem();
|
||||
if (clicked == null || clicked.getType() == Material.AIR) return;
|
||||
|
||||
int amount = clicked.getAmount();
|
||||
Material mat = clicked.getType();
|
||||
String itemKey = mat.name().toLowerCase();
|
||||
|
||||
if (!shopManager.buyItem(itemKey, amount)) {
|
||||
player.sendMessage(ChatColor.RED + "Nicht genügend Bestand im Shop.");
|
||||
return;
|
||||
}
|
||||
|
||||
double totalPrice = shopManager.getCurrentPrice(itemKey) * amount;
|
||||
|
||||
// TODO: Economy Abzug einfügen
|
||||
|
||||
player.getInventory().addItem(new ItemStack(mat, amount));
|
||||
player.sendMessage(ChatColor.GREEN + "Du hast " + amount + "x " + mat.name() + " für " + totalPrice + " Coins gekauft.");
|
||||
|
||||
player.closeInventory();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent e) {
|
||||
if (e.getView().getTitle().equals("Shop") && e.getPlayer().equals(player)) {
|
||||
// Optional: Listener entfernen oder Aufräumarbeiten hier
|
||||
}
|
||||
}
|
||||
|
||||
public Inventory getInventory() {
|
||||
return inv;
|
||||
}
|
||||
}
|
115
src/main/java/de/viper/survivalplus/listeners/AFKListener.java
Normal file
115
src/main/java/de/viper/survivalplus/listeners/AFKListener.java
Normal file
@@ -0,0 +1,115 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import de.viper.survivalplus.tasks.AFKManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.*;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class AFKListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private AFKManager afkManager;
|
||||
private boolean afkEnabled;
|
||||
private FileConfiguration config;
|
||||
|
||||
private BukkitRunnable afkTask;
|
||||
|
||||
public AFKListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
this.config = plugin.getConfig();
|
||||
loadSettings();
|
||||
if (afkEnabled) {
|
||||
startTask();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadSettings() {
|
||||
this.afkEnabled = config.getBoolean("afk.enabled", true);
|
||||
long afkAfter = config.getLong("afk.afk-after-seconds", 300);
|
||||
long kickAfter = config.getLong("afk.kick-after-seconds", 0);
|
||||
this.afkManager = new AFKManager(plugin, afkAfter, kickAfter);
|
||||
}
|
||||
|
||||
private void startTask() {
|
||||
if (afkTask != null) {
|
||||
afkTask.cancel();
|
||||
}
|
||||
afkTask = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
afkManager.checkAFKStatus(player);
|
||||
}
|
||||
}
|
||||
};
|
||||
afkTask.runTaskTimer(plugin, 60L, 100L);
|
||||
}
|
||||
|
||||
private void handleActivity(Player player) {
|
||||
if (!afkEnabled) return;
|
||||
afkManager.updateActivity(player);
|
||||
}
|
||||
|
||||
@org.bukkit.event.EventHandler
|
||||
public void onMove(PlayerMoveEvent event) {
|
||||
if (!event.getFrom().toVector().equals(event.getTo().toVector())) {
|
||||
handleActivity(event.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
@org.bukkit.event.EventHandler
|
||||
public void onChat(AsyncPlayerChatEvent event) {
|
||||
handleActivity(event.getPlayer());
|
||||
}
|
||||
|
||||
@org.bukkit.event.EventHandler
|
||||
public void onInteract(PlayerInteractEvent event) {
|
||||
handleActivity(event.getPlayer());
|
||||
}
|
||||
|
||||
@org.bukkit.event.EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (event.getWhoClicked() instanceof Player player) {
|
||||
handleActivity(player);
|
||||
}
|
||||
}
|
||||
|
||||
@org.bukkit.event.EventHandler
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
handleActivity(event.getPlayer());
|
||||
}
|
||||
|
||||
@org.bukkit.event.EventHandler
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
handleActivity(event.getPlayer());
|
||||
}
|
||||
|
||||
@org.bukkit.event.EventHandler
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
afkManager.updateActivity(event.getPlayer());
|
||||
}
|
||||
|
||||
@org.bukkit.event.EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
afkManager.reset(event.getPlayer());
|
||||
}
|
||||
|
||||
public void reloadConfig(FileConfiguration config) {
|
||||
this.config = config;
|
||||
loadSettings();
|
||||
if (afkTask != null) {
|
||||
afkTask.cancel();
|
||||
afkTask = null;
|
||||
}
|
||||
if (afkEnabled) {
|
||||
startTask();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
|
||||
public class ArmorStandDestroyListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onArmorStandInteract(PlayerInteractAtEntityEvent event) {
|
||||
if (!(event.getRightClicked() instanceof ArmorStand armorStand)) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (!player.hasPermission("survivalplus.armorstand.destroy")) {
|
||||
player.sendMessage(ChatColor.RED + "Du hast keine Berechtigung, diesen ArmorStand zu entfernen.");
|
||||
return;
|
||||
}
|
||||
|
||||
armorStand.remove();
|
||||
player.sendMessage(ChatColor.YELLOW + "ArmorStand wurde erfolgreich entfernt.");
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
@@ -0,0 +1,111 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class BackpackListener implements Listener {
|
||||
|
||||
private final FileConfiguration backpackConfig;
|
||||
private final FileConfiguration langConfig;
|
||||
private final Logger logger;
|
||||
private final File backpackFile;
|
||||
|
||||
public BackpackListener(FileConfiguration backpackConfig, FileConfiguration langConfig, Logger logger, File backpackFile) {
|
||||
this.backpackConfig = backpackConfig;
|
||||
this.langConfig = langConfig;
|
||||
this.logger = logger;
|
||||
this.backpackFile = backpackFile;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onRightClick(PlayerInteractEvent event) {
|
||||
if (!event.hasItem() || !event.getAction().toString().contains("RIGHT")) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
ItemStack item = event.getItem();
|
||||
|
||||
if (item == null || item.getType() != Material.CHEST) {
|
||||
logger.fine("Kein Rucksack-Item: " + (item != null ? item.getType() : "null"));
|
||||
return;
|
||||
}
|
||||
if (!item.hasItemMeta()) {
|
||||
logger.fine("Item hat kein ItemMeta: " + item.getType());
|
||||
return;
|
||||
}
|
||||
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (!meta.hasDisplayName()) {
|
||||
logger.fine("Item hat keinen Display-Namen: " + item.getType());
|
||||
return;
|
||||
}
|
||||
|
||||
String expectedName = ChatColor.translateAlternateColorCodes('&', langConfig.getString("backpack.name", "&eRucksack"));
|
||||
if (!meta.getDisplayName().equals(expectedName)) {
|
||||
logger.fine("Item hat falschen Namen: " + meta.getDisplayName() + ", erwartet: " + expectedName);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
UUID uuid = player.getUniqueId();
|
||||
String inventoryTitle = ChatColor.translateAlternateColorCodes('&', langConfig.getString("backpack.inventory-title", "&eDein Rucksack"));
|
||||
|
||||
Inventory backpackInv = Bukkit.createInventory(null, 27, inventoryTitle);
|
||||
logger.info("Öffne Rucksack-Inventar für Spieler " + player.getName() + " (" + uuid + ")");
|
||||
|
||||
for (int i = 0; i < 27; i++) {
|
||||
String path = uuid + ".slot" + i;
|
||||
if (backpackConfig.contains(path)) {
|
||||
backpackInv.setItem(i, backpackConfig.getItemStack(path));
|
||||
}
|
||||
}
|
||||
|
||||
player.openInventory(backpackInv);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClose(InventoryCloseEvent event) {
|
||||
String expectedTitle = ChatColor.translateAlternateColorCodes('&', langConfig.getString("backpack.inventory-title", "&eDein Rucksack"));
|
||||
if (!event.getView().getTitle().equals(expectedTitle)) return;
|
||||
|
||||
Player player = (Player) event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
Inventory inv = event.getInventory();
|
||||
|
||||
logger.info("Speichere Rucksack-Inventar für Spieler " + player.getName() + " (" + uuid + ")");
|
||||
|
||||
for (int i = 0; i < inv.getSize(); i++) {
|
||||
String path = uuid + ".slot" + i;
|
||||
ItemStack item = inv.getItem(i);
|
||||
backpackConfig.set(path, item);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!backpackFile.exists()) {
|
||||
backpackFile.createNewFile();
|
||||
logger.info("backpacks.yml wurde erstellt.");
|
||||
}
|
||||
backpackConfig.save(backpackFile);
|
||||
logger.info("Rucksack-Inventar gespeichert für " + player.getName());
|
||||
} catch (IOException e) {
|
||||
player.sendMessage(ChatColor.RED + "Fehler beim Speichern deines Rucksacks.");
|
||||
logger.severe("Fehler beim Speichern der backpacks.yml: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class BlockDetectionListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public BlockDetectionListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
scanAndHandle(player, false);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPickUp(EntityPickupItemEvent event) {
|
||||
if (!(event.getEntity() instanceof Player)) return;
|
||||
Player player = (Player) event.getEntity();
|
||||
scanAndHandle(player, true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (!(event.getWhoClicked() instanceof Player)) return;
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
scanAndHandle(player, true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (player.hasPermission("survivalplus.notify")) {
|
||||
return; // Admins dürfen Blöcke platzieren
|
||||
}
|
||||
Material material = event.getBlock().getType();
|
||||
boolean cmdAllowed = plugin.getConfig().getBoolean("blocks.command-blocks.enabled", true);
|
||||
boolean structAllowed = plugin.getConfig().getBoolean("blocks.structure-blocks.enabled", true);
|
||||
|
||||
if ((!cmdAllowed && material == Material.COMMAND_BLOCK) ||
|
||||
(!structAllowed && material == Material.STRUCTURE_BLOCK)) {
|
||||
event.setCancelled(true);
|
||||
player.sendMessage(ChatColor.RED + "[SurvivalPlus] Du darfst diesen Block hier nicht platzieren!");
|
||||
}
|
||||
}
|
||||
|
||||
private void scanAndHandle(Player player, boolean notifyPlayer) {
|
||||
if (player.hasPermission("survivalplus.notify")) {
|
||||
return; // Admins dürfen Blöcke behalten
|
||||
}
|
||||
Inventory inventory = player.getInventory();
|
||||
boolean hasCommandBlock = false;
|
||||
boolean hasStructureBlock = false;
|
||||
boolean cmdAllowed = plugin.getConfig().getBoolean("blocks.command-blocks.enabled", true);
|
||||
boolean structAllowed = plugin.getConfig().getBoolean("blocks.structure-blocks.enabled", true);
|
||||
boolean notifyAdmins = plugin.getConfig().getBoolean("blocks.notify-admins-on-possession", true);
|
||||
|
||||
for (ItemStack item : inventory.getContents()) {
|
||||
if (item == null) continue;
|
||||
Material material = item.getType();
|
||||
if (material == Material.COMMAND_BLOCK) hasCommandBlock = true;
|
||||
if (material == Material.STRUCTURE_BLOCK) hasStructureBlock = true;
|
||||
}
|
||||
|
||||
if (!cmdAllowed && hasCommandBlock) {
|
||||
inventory.remove(Material.COMMAND_BLOCK);
|
||||
if (notifyPlayer) {
|
||||
player.sendMessage(ChatColor.RED + "[SurvivalPlus] Command-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
|
||||
}
|
||||
}
|
||||
if (!structAllowed && hasStructureBlock) {
|
||||
inventory.remove(Material.STRUCTURE_BLOCK);
|
||||
if (notifyPlayer) {
|
||||
player.sendMessage(ChatColor.RED + "[SurvivalPlus] Structure-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
|
||||
}
|
||||
}
|
||||
|
||||
if (notifyAdmins && (hasCommandBlock || hasStructureBlock)) {
|
||||
notifyOnlineAdmins(player.getName(), hasCommandBlock, hasStructureBlock, cmdAllowed, structAllowed);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyOnlineAdmins(String playerName, boolean hadCommandBlock, boolean hadStructureBlock, boolean cmdAllowed, boolean structAllowed) {
|
||||
String baseTag = ChatColor.GRAY + "[" + ChatColor.GREEN + "SurvivalPlus" + ChatColor.GRAY + "] ";
|
||||
for (Player admin : Bukkit.getOnlinePlayers()) {
|
||||
if (admin.hasPermission("survivalplus.notify")) {
|
||||
if (hadCommandBlock && !cmdAllowed) {
|
||||
String message = baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
|
||||
ChatColor.RED + " hatte einen Command-Block im Inventar, der entfernt wurde.";
|
||||
admin.sendMessage(message);
|
||||
}
|
||||
if (hadStructureBlock && !structAllowed) {
|
||||
String message = baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
|
||||
ChatColor.RED + " hatte einen Structure-Block im Inventar, der entfernt wurde.";
|
||||
admin.sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.fun.FunChallenge;
|
||||
import de.viper.survivalplus.fun.FunChallengeManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerPickupItemEvent;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
public class ChallengeCollectListener implements Listener {
|
||||
|
||||
private final FunChallengeManager challengeManager;
|
||||
private final NamespacedKey droppedKey;
|
||||
|
||||
public ChallengeCollectListener(FunChallengeManager challengeManager, NamespacedKey droppedKey) {
|
||||
this.challengeManager = challengeManager;
|
||||
this.droppedKey = droppedKey;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onItemDrop(PlayerDropItemEvent event) {
|
||||
ItemStack dropped = event.getItemDrop().getItemStack();
|
||||
ItemMeta meta = dropped.getItemMeta();
|
||||
if (meta != null) {
|
||||
meta.getPersistentDataContainer().set(droppedKey, PersistentDataType.INTEGER, 1);
|
||||
dropped.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerPickup(PlayerPickupItemEvent event) {
|
||||
FunChallenge challenge = challengeManager.getActiveChallenge();
|
||||
if (challenge == null) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
ItemStack item = event.getItem().getItemStack();
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
if (meta != null && meta.getPersistentDataContainer().has(droppedKey, PersistentDataType.INTEGER)) {
|
||||
return; // Item aus Inventar gedroppt, nicht zählen
|
||||
}
|
||||
|
||||
if (item.getType().name().equalsIgnoreCase(challenge.getItem())) {
|
||||
int current = challengeManager.getGlobalProgress(challenge.getName());
|
||||
current += item.getAmount();
|
||||
challengeManager.setGlobalProgress(challenge.getName(), current);
|
||||
|
||||
if (current >= challenge.getAmount()) {
|
||||
player.getServer().broadcastMessage("§aChallenge \"" + challenge.getName() + "\" geschafft!");
|
||||
giveReward(player, challenge.getReward());
|
||||
challenge.setActive(false);
|
||||
challengeManager.resetProgress(challenge.getName());
|
||||
} else {
|
||||
player.sendMessage("§eFortschritt: " + current + "/" + challenge.getAmount() + " " + challenge.getItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void giveReward(Player player, String reward) {
|
||||
if (reward == null || reward.isEmpty()) return;
|
||||
|
||||
String[] parts = reward.split(",");
|
||||
if (parts.length != 2) return;
|
||||
|
||||
String itemName = parts[0];
|
||||
int amount;
|
||||
try {
|
||||
amount = Integer.parseInt(parts[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material material = Material.matchMaterial(itemName);
|
||||
if (material == null) return;
|
||||
|
||||
ItemStack rewardItem = new ItemStack(material, amount);
|
||||
player.getInventory().addItem(rewardItem);
|
||||
player.sendMessage("§aDu hast deine Belohnung erhalten: " + amount + "x " + itemName);
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.fun.FunChallenge;
|
||||
import de.viper.survivalplus.fun.FunChallengeManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.FurnaceExtractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ChallengeSmeltListener implements Listener {
|
||||
|
||||
private final FunChallengeManager challengeManager;
|
||||
|
||||
public ChallengeSmeltListener(FunChallengeManager challengeManager) {
|
||||
this.challengeManager = challengeManager;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onFurnaceExtract(FurnaceExtractEvent event) {
|
||||
Player player = (Player) event.getPlayer();
|
||||
|
||||
FunChallenge active = challengeManager.getActiveChallenge();
|
||||
if (active == null) return;
|
||||
|
||||
if (!"COLLECT".equalsIgnoreCase(active.getType())) return;
|
||||
|
||||
String requiredItem = active.getItem();
|
||||
int requiredAmount = active.getAmount();
|
||||
|
||||
String smeltedItem = event.getItemType().name();
|
||||
if (!smeltedItem.equalsIgnoreCase(requiredItem)) return;
|
||||
|
||||
int current = challengeManager.getGlobalProgress(active.getName());
|
||||
current += event.getItemAmount();
|
||||
challengeManager.setGlobalProgress(active.getName(), current);
|
||||
|
||||
if (current >= requiredAmount) {
|
||||
player.getServer().broadcastMessage("§aChallenge \"" + active.getName() + "\" geschafft!");
|
||||
giveReward(player, active.getReward());
|
||||
active.setActive(false);
|
||||
challengeManager.resetProgress(active.getName());
|
||||
} else {
|
||||
player.sendMessage("§eFortschritt: " + current + "/" + requiredAmount + " " + requiredItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void giveReward(Player player, String reward) {
|
||||
if (reward == null || reward.isEmpty()) return;
|
||||
|
||||
String[] parts = reward.split(",");
|
||||
if (parts.length != 2) return;
|
||||
|
||||
String itemName = parts[0];
|
||||
int amount;
|
||||
try {
|
||||
amount = Integer.parseInt(parts[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material material = Material.matchMaterial(itemName);
|
||||
if (material == null) return;
|
||||
|
||||
ItemStack rewardItem = new ItemStack(material, amount);
|
||||
player.getInventory().addItem(rewardItem);
|
||||
player.sendMessage("§aDu hast deine Belohnung erhalten: " + amount + "x " + itemName);
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.Manager.BlockManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
|
||||
public class ChatBlockListener implements Listener {
|
||||
|
||||
private final BlockManager blockManager;
|
||||
|
||||
public ChatBlockListener(BlockManager blockManager) {
|
||||
this.blockManager = blockManager;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChat(AsyncPlayerChatEvent event) {
|
||||
Player sender = event.getPlayer();
|
||||
|
||||
event.getRecipients().removeIf(recipient ->
|
||||
blockManager.hasBlocked(recipient, sender) || blockManager.hasBlocked(sender, recipient)
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
|
||||
public class DebugArmorStandListener implements Listener {
|
||||
|
||||
private static final double MAX_DISTANCE = 3.0;
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
|
||||
if (event.getRightClicked() instanceof ArmorStand armorStand) {
|
||||
Player player = event.getPlayer();
|
||||
if (armorStand.getScoreboardTags().contains("debugArmorStand")) {
|
||||
if (armorStand.getLocation().distance(player.getLocation()) <= MAX_DISTANCE) {
|
||||
armorStand.remove();
|
||||
player.sendMessage("§aDebug-ArmorStand wurde entfernt.");
|
||||
event.setCancelled(true);
|
||||
} else {
|
||||
player.sendMessage("§cDieser Debug-ArmorStand ist zu weit entfernt.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
|
||||
if (event.getEntity() instanceof ArmorStand armorStand) {
|
||||
if (armorStand.getScoreboardTags().contains("debugArmorStand")) {
|
||||
if (event.getDamager() instanceof Player player) {
|
||||
if (armorStand.getLocation().distance(player.getLocation()) <= MAX_DISTANCE) {
|
||||
armorStand.remove();
|
||||
player.sendMessage("§aDebug-ArmorStand wurde zerstört.");
|
||||
event.setCancelled(true);
|
||||
} else {
|
||||
player.sendMessage("§cDieser Debug-ArmorStand ist zu weit entfernt.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
public class FirstJoinListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerFirstJoin(PlayerJoinEvent event) {
|
||||
if (event.getPlayer().hasPlayedBefore()) {
|
||||
return; // Nur für den ersten Join
|
||||
}
|
||||
|
||||
// Erstelle ein ItemStack für einen Trank (z.B. Heiltrank)
|
||||
ItemStack potion = new ItemStack(Material.POTION, 1);
|
||||
|
||||
if (potion.getItemMeta() instanceof PotionMeta) {
|
||||
PotionMeta potionMeta = (PotionMeta) potion.getItemMeta();
|
||||
PotionEffect effect = new PotionEffect(PotionEffectType.REGENERATION, 600, 1);
|
||||
potionMeta.addCustomEffect(effect, true);
|
||||
potion.setItemMeta(potionMeta);
|
||||
}
|
||||
|
||||
// Füge das Trank-Item zum Inventar des Spielers hinzu
|
||||
PlayerInventory inventory = event.getPlayer().getInventory();
|
||||
inventory.addItem(potion);
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package de.viper.survivalplus;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
public class ForceSurvivalListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public ForceSurvivalListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
// Spieler in Survival setzen
|
||||
if (player.getGameMode() != GameMode.SURVIVAL) {
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
player.sendMessage(plugin.getMessage("force-survival.join-message"));
|
||||
}
|
||||
}
|
||||
}
|
186
src/main/java/de/viper/survivalplus/listeners/GraveListener.java
Normal file
186
src/main/java/de/viper/survivalplus/listeners/GraveListener.java
Normal file
@@ -0,0 +1,186 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GraveListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final HashMap<Location, UUID> graveOwners = new HashMap<>();
|
||||
private final HashMap<Location, UUID> graveArmorStands = new HashMap<>();
|
||||
private long despawnTime;
|
||||
|
||||
public GraveListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
reloadConfig(plugin.getConfig());
|
||||
}
|
||||
|
||||
public void reloadConfig(FileConfiguration config) {
|
||||
this.despawnTime = config.getLong("graves.despawn-time", 1800);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||
if (event.getKeepInventory()) return;
|
||||
|
||||
Player player = event.getEntity();
|
||||
UUID playerId = player.getUniqueId();
|
||||
FileConfiguration gravesConfig = plugin.getGravesConfig();
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
|
||||
Location deathLocation = player.getLocation().clone();
|
||||
Block block = deathLocation.getBlock();
|
||||
|
||||
// Save to graves.yml
|
||||
gravesConfig.set("graves." + playerId + ".world", deathLocation.getWorld().getName());
|
||||
gravesConfig.set("graves." + playerId + ".x", deathLocation.getX());
|
||||
gravesConfig.set("graves." + playerId + ".y", deathLocation.getY());
|
||||
gravesConfig.set("graves." + playerId + ".z", deathLocation.getZ());
|
||||
plugin.saveGravesConfig();
|
||||
|
||||
// Suche Platz für Truhe
|
||||
if (block.isEmpty() || block.getType().isAir()) {
|
||||
block.setType(Material.CHEST);
|
||||
} else {
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
Block above = block.getRelative(0, i, 0);
|
||||
if (above.isEmpty() || above.getType().isAir()) {
|
||||
above.setType(Material.CHEST);
|
||||
block = above;
|
||||
deathLocation = block.getLocation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block.getType() == Material.CHEST) {
|
||||
Chest chest = (Chest) block.getState();
|
||||
for (ItemStack item : event.getDrops()) {
|
||||
if (item != null && item.getType() != Material.AIR) {
|
||||
chest.getInventory().addItem(item);
|
||||
}
|
||||
}
|
||||
event.getDrops().clear();
|
||||
|
||||
graveOwners.put(block.getLocation(), playerId);
|
||||
|
||||
// Nachricht an Spieler
|
||||
player.sendMessage(String.format(
|
||||
lang.getString("graves.created", "§aDein Grab wurde bei x=%.2f, y=%.2f, z=%.2f erstellt!"),
|
||||
deathLocation.getX(),
|
||||
deathLocation.getY(),
|
||||
deathLocation.getZ()
|
||||
));
|
||||
|
||||
// ArmorStand mit "Grab von <Name>"
|
||||
Location standLocation = deathLocation.clone().add(0.5, 1.2, 0.5);
|
||||
ArmorStand stand = deathLocation.getWorld().spawn(standLocation, ArmorStand.class);
|
||||
stand.setVisible(false);
|
||||
stand.setCustomName("§cGrab von " + player.getName());
|
||||
stand.setCustomNameVisible(true);
|
||||
stand.setMarker(true);
|
||||
stand.setGravity(false);
|
||||
stand.setInvulnerable(true);
|
||||
stand.setSilent(true);
|
||||
stand.setSmall(true);
|
||||
|
||||
// Speichere ArmorStand UUID
|
||||
graveArmorStands.put(block.getLocation(), stand.getUniqueId());
|
||||
|
||||
// Entfernen nach Zeit
|
||||
if (despawnTime >= 0) {
|
||||
final Block graveBlock = block;
|
||||
final Location graveLocation = graveBlock.getLocation();
|
||||
final Player deadPlayer = player;
|
||||
final FileConfiguration langConfigFinal = lang;
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (graveBlock.getType() == Material.CHEST) {
|
||||
graveBlock.setType(Material.AIR);
|
||||
graveOwners.remove(graveLocation);
|
||||
removeArmorStand(graveLocation);
|
||||
|
||||
deadPlayer.sendMessage(String.format(
|
||||
langConfigFinal.getString("graves.despawned", "§cDein Grab bei x=%.2f, y=%.2f, z=%.2f ist verschwunden!"),
|
||||
graveLocation.getX(),
|
||||
graveLocation.getY(),
|
||||
graveLocation.getZ()
|
||||
));
|
||||
}
|
||||
}
|
||||
}.runTaskLater(plugin, despawnTime * 20L);
|
||||
}
|
||||
|
||||
// Überwache, ob Truhe geleert wurde
|
||||
final Block chestBlockFinal = block;
|
||||
final Player playerFinal = player;
|
||||
final FileConfiguration langFinal = lang;
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (chestBlockFinal.getType() != Material.CHEST) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
Chest c = (Chest) chestBlockFinal.getState();
|
||||
boolean empty = true;
|
||||
for (ItemStack item : c.getInventory().getContents()) {
|
||||
if (item != null && item.getType() != Material.AIR) {
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
c.getBlock().setType(Material.AIR);
|
||||
graveOwners.remove(c.getLocation());
|
||||
removeArmorStand(c.getLocation());
|
||||
|
||||
playerFinal.sendMessage(String.format(
|
||||
langFinal.getString("graves.emptied", "§7Dein Grab bei x=%.2f, y=%.2f, z=%.2f wurde geleert."),
|
||||
(double)c.getX(),
|
||||
(double)c.getY(),
|
||||
(double)c.getZ()
|
||||
));
|
||||
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(plugin, 20L, 60L);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeArmorStand(Location chestLocation) {
|
||||
UUID standId = graveArmorStands.remove(chestLocation);
|
||||
if (standId == null) return;
|
||||
|
||||
Entity entity = Bukkit.getEntity(standId);
|
||||
if (entity != null && entity instanceof ArmorStand) {
|
||||
entity.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOwner(Player player, Location location) {
|
||||
return graveOwners.getOrDefault(location, null) != null &&
|
||||
graveOwners.get(location).equals(player.getUniqueId());
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class InventoryClickListener implements Listener {
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public InventoryClickListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
String guiTitle = event.getView().getTitle();
|
||||
String homeGuiTitle = lang.getString("homelist.gui-title", "Deine Homes");
|
||||
if (!guiTitle.equals(homeGuiTitle)) {
|
||||
plugin.getLogger().log(Level.FINE, "Ignoriere Klick in GUI mit Titel: " + guiTitle);
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.getLogger().log(Level.FINE, "Verarbeite Klick in Home-Liste GUI für Spieler: " + event.getWhoClicked().getName());
|
||||
event.setCancelled(true);
|
||||
if (!(event.getWhoClicked() instanceof Player) || event.getCurrentItem() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
String homeName = event.getCurrentItem().getItemMeta().getDisplayName().replace("§a", "");
|
||||
String path = "homes." + player.getUniqueId() + "." + homeName.toLowerCase();
|
||||
|
||||
FileConfiguration homes = plugin.getHomesConfig();
|
||||
if (!homes.contains(path)) {
|
||||
player.sendMessage(lang.getString("homelist.home-deleted", "§cDieses Home existiert nicht mehr!"));
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
String worldName = homes.getString(path + ".world");
|
||||
World world = plugin.getServer().getWorld(worldName);
|
||||
if (world == null) {
|
||||
player.sendMessage(lang.getString("homelist.world-not-found", "§cDie Welt dieses Homes existiert nicht!"));
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
Location loc = new Location(
|
||||
world,
|
||||
homes.getDouble(path + ".x"),
|
||||
homes.getDouble(path + ".y"),
|
||||
homes.getDouble(path + ".z"),
|
||||
(float) homes.getDouble(path + ".yaw"),
|
||||
(float) homes.getDouble(path + ".pitch")
|
||||
);
|
||||
|
||||
player.teleport(loc);
|
||||
player.sendMessage(lang.getString("homelist.teleported", "§aZum Home %name% teleportiert!")
|
||||
.replace("%name%", homeName));
|
||||
player.closeInventory();
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
public class LoginListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public LoginListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (!player.hasPlayedBefore()) {
|
||||
// Erster Login
|
||||
sendWelcomeMessage(player, true);
|
||||
} else {
|
||||
// Wiederkehrer
|
||||
sendWelcomeMessage(player, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendWelcomeMessage(Player player, boolean firstJoin) {
|
||||
String messageKey = firstJoin ? "welcome.first-join-message" : "welcome.return-message";
|
||||
String soundKey = firstJoin ? "welcome.first-join-sound" : "welcome.return-sound";
|
||||
String volumeKey = firstJoin ? "welcome.first-join-sound-volume" : "welcome.return-sound-volume";
|
||||
String pitchKey = firstJoin ? "welcome.first-join-sound-pitch" : "welcome.return-sound-pitch";
|
||||
|
||||
String rawMessage = plugin.getLangConfig().getString(messageKey, "&6Willkommen, &e{player}&6!");
|
||||
String message = ChatColor.translateAlternateColorCodes('&', rawMessage.replace("{player}", player.getName()));
|
||||
player.sendMessage(message);
|
||||
|
||||
String soundName = plugin.getLangConfig().getString(soundKey, "ENTITY_PLAYER_LEVELUP");
|
||||
float volume = (float) plugin.getLangConfig().getDouble(volumeKey, 1.0);
|
||||
float pitch = (float) plugin.getLangConfig().getDouble(pitchKey, 1.0);
|
||||
|
||||
try {
|
||||
Sound sound = Sound.valueOf(soundName);
|
||||
player.playSound(player.getLocation(), sound, volume, pitch);
|
||||
} catch (IllegalArgumentException e) {
|
||||
plugin.getLogger().warning("Ungültiger Sound-Name in lang.yml: " + soundName);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,181 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Animals;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MobCapListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private boolean enabled;
|
||||
private int maxAnimalsPerChunk;
|
||||
private final Map<String, Map<UUID, UUID>> chunkAnimalMap = new HashMap<>(); // Chunk -> Tier-UUID -> Spieler-UUID
|
||||
|
||||
public MobCapListener(SurvivalPlus plugin, FileConfiguration config) {
|
||||
this.plugin = plugin;
|
||||
reloadConfig(config);
|
||||
}
|
||||
|
||||
public void reloadConfig(FileConfiguration config) {
|
||||
this.enabled = config.getBoolean("mob-cap.enabled", true);
|
||||
this.maxAnimalsPerChunk = config.getInt("mob-cap.max-animals-per-chunk", 10);
|
||||
plugin.getLogger().info("MobCapListener: enabled=" + enabled + ", maxAnimalsPerChunk=" + maxAnimalsPerChunk);
|
||||
|
||||
// Bereinige bestehende Daten
|
||||
chunkAnimalMap.clear();
|
||||
|
||||
if (!enabled) {
|
||||
plugin.getMobCapConfig().set("mobcap", null); // Bereinige mobcap.yml
|
||||
plugin.saveMobCapConfig();
|
||||
plugin.getLogger().info("MobCapListener: Daten bereinigt, da enabled=false");
|
||||
return;
|
||||
}
|
||||
|
||||
// Lade Zuordnungen aus mobcap.yml
|
||||
FileConfiguration mobCapConfig = plugin.getMobCapConfig();
|
||||
if (mobCapConfig.contains("mobcap")) {
|
||||
for (String chunkKey : mobCapConfig.getConfigurationSection("mobcap").getKeys(false)) {
|
||||
Map<UUID, UUID> animalToPlayer = new HashMap<>();
|
||||
for (String animalIdStr : mobCapConfig.getConfigurationSection("mobcap." + chunkKey).getKeys(false)) {
|
||||
try {
|
||||
UUID animalId = UUID.fromString(animalIdStr);
|
||||
String playerIdStr = mobCapConfig.getString("mobcap." + chunkKey + "." + animalIdStr);
|
||||
if (playerIdStr != null) {
|
||||
UUID playerId = UUID.fromString(playerIdStr);
|
||||
Entity entity = plugin.getServer().getEntity(animalId);
|
||||
if (entity instanceof Animals) {
|
||||
animalToPlayer.put(animalId, playerId);
|
||||
} else {
|
||||
// Entferne ungültige Einträge
|
||||
mobCapConfig.set("mobcap." + chunkKey + "." + animalIdStr, null);
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
plugin.getLogger().warning("Ungültige UUID in mobcap.yml: " + animalIdStr);
|
||||
}
|
||||
}
|
||||
chunkAnimalMap.put(chunkKey, animalToPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
// Scanne alle Welten nach Tieren
|
||||
for (org.bukkit.World world : plugin.getServer().getWorlds()) {
|
||||
for (Chunk chunk : world.getLoadedChunks()) {
|
||||
String chunkKey = getChunkKey(chunk);
|
||||
Map<UUID, UUID> animalToPlayer = chunkAnimalMap.computeIfAbsent(chunkKey, k -> new HashMap<>());
|
||||
for (Entity entity : chunk.getEntities()) {
|
||||
if (entity instanceof Animals) {
|
||||
UUID id = entity.getUniqueId();
|
||||
if (!animalToPlayer.containsKey(id)) {
|
||||
animalToPlayer.put(id, null); // Kein Spieler zugeordnet
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Speichere aktualisierte mobcap.yml
|
||||
saveChunkAnimalMap();
|
||||
plugin.getLogger().info("MobCapListener: Nach Reload " + chunkAnimalMap.size() + " Chunks mit Tieren gefunden.");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onCreatureSpawn(CreatureSpawnEvent event) {
|
||||
if (!enabled) return;
|
||||
|
||||
LivingEntity entity = event.getEntity();
|
||||
if (!(entity instanceof Animals)) return;
|
||||
|
||||
Chunk chunk = entity.getLocation().getChunk();
|
||||
String chunkKey = getChunkKey(chunk);
|
||||
Map<UUID, UUID> animalToPlayer = chunkAnimalMap.computeIfAbsent(chunkKey, k -> new HashMap<>());
|
||||
|
||||
int animalCount = animalToPlayer.size();
|
||||
if (animalCount >= maxAnimalsPerChunk) {
|
||||
event.setCancelled(true);
|
||||
plugin.getLogger().info("Spawn von " + entity.getType() + " in Chunk " + chunkKey + " verhindert: Limit von " + maxAnimalsPerChunk + " erreicht.");
|
||||
|
||||
// HINWEIS: Wenn du dem Züchter eine Nachricht schicken willst, nutze EntityBreedEvent
|
||||
// Hier ist das nicht möglich, weil man beim Spawn keinen Spielerzugriff hat
|
||||
} else {
|
||||
animalToPlayer.put(entity.getUniqueId(), null); // Kein Spieler zugeordnet
|
||||
saveChunkAnimalMap();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
||||
if (!enabled) return;
|
||||
|
||||
if (!(event.getRightClicked() instanceof Animals)) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
Entity entity = event.getRightClicked();
|
||||
Chunk chunk = entity.getLocation().getChunk();
|
||||
String chunkKey = getChunkKey(chunk);
|
||||
Map<UUID, UUID> animalToPlayer = chunkAnimalMap.computeIfAbsent(chunkKey, k -> new HashMap<>());
|
||||
|
||||
int animalCount = animalToPlayer.size();
|
||||
if (animalCount >= maxAnimalsPerChunk) {
|
||||
event.setCancelled(true);
|
||||
player.sendMessage(plugin.getMessage("mob-cap.limit-reached").replace("%max%", String.valueOf(maxAnimalsPerChunk)));
|
||||
plugin.getLogger().info("Interaktion mit " + entity.getType() + " in Chunk " + chunkKey + " verhindert: Limit von " + maxAnimalsPerChunk + " erreicht.");
|
||||
} else {
|
||||
animalToPlayer.put(entity.getUniqueId(), player.getUniqueId());
|
||||
saveChunkAnimalMap();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityDeath(EntityDeathEvent event) {
|
||||
if (!enabled) return;
|
||||
|
||||
if (!(event.getEntity() instanceof Animals)) return;
|
||||
|
||||
LivingEntity entity = event.getEntity();
|
||||
Chunk chunk = entity.getLocation().getChunk();
|
||||
String chunkKey = getChunkKey(chunk);
|
||||
Map<UUID, UUID> animalToPlayer = chunkAnimalMap.get(chunkKey);
|
||||
|
||||
if (animalToPlayer != null) {
|
||||
UUID animalId = entity.getUniqueId();
|
||||
animalToPlayer.remove(animalId);
|
||||
if (animalToPlayer.isEmpty()) {
|
||||
chunkAnimalMap.remove(chunkKey);
|
||||
}
|
||||
saveChunkAnimalMap();
|
||||
plugin.getLogger().info("Tier " + entity.getType() + " in Chunk " + chunkKey + " gestorben. Verbleibende Tiere: " + animalToPlayer.size());
|
||||
}
|
||||
}
|
||||
|
||||
private String getChunkKey(Chunk chunk) {
|
||||
return chunk.getWorld().getName() + "," + chunk.getX() + "," + chunk.getZ();
|
||||
}
|
||||
|
||||
private void saveChunkAnimalMap() {
|
||||
FileConfiguration mobCapConfig = plugin.getMobCapConfig();
|
||||
mobCapConfig.set("mobcap", null); // Bereinige vorherige Daten
|
||||
for (Map.Entry<String, Map<UUID, UUID>> entry : chunkAnimalMap.entrySet()) {
|
||||
String chunkKey = entry.getKey();
|
||||
Map<UUID, UUID> animalToPlayer = entry.getValue();
|
||||
for (Map.Entry<UUID, UUID> animalEntry : animalToPlayer.entrySet()) {
|
||||
mobCapConfig.set("mobcap." + chunkKey + "." + animalEntry.getKey().toString(),
|
||||
animalEntry.getValue() != null ? animalEntry.getValue().toString() : null);
|
||||
}
|
||||
}
|
||||
plugin.saveMobCapConfig();
|
||||
}
|
||||
}
|
@@ -0,0 +1,253 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MobLeashLimitListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private boolean enabled;
|
||||
private int maxLeashCount;
|
||||
private final Map<UUID, Set<UUID>> leashedEntities = new HashMap<>();
|
||||
private final Map<UUID, Integer> leashCounts = new HashMap<>();
|
||||
private final Map<UUID, UUID> entityToPlayer = new HashMap<>();
|
||||
|
||||
public MobLeashLimitListener(SurvivalPlus plugin, FileConfiguration config) {
|
||||
this.plugin = plugin;
|
||||
reloadConfig(config);
|
||||
}
|
||||
|
||||
public void reloadConfig(FileConfiguration config) {
|
||||
this.enabled = config.getBoolean("mob-leash-limit.enabled", true);
|
||||
this.maxLeashCount = config.getInt("mob-leash-limit.max-leash-count", 5);
|
||||
plugin.getLogger().info("MobLeashLimitListener: enabled=" + enabled + ", maxLeashCount=" + maxLeashCount);
|
||||
|
||||
// Bereinige bestehende Daten
|
||||
leashedEntities.clear();
|
||||
leashCounts.clear();
|
||||
entityToPlayer.clear();
|
||||
|
||||
if (!enabled) {
|
||||
plugin.getLeashesConfig().set("leashes", null); // Bereinige leashes.yml
|
||||
plugin.saveLeashesConfig();
|
||||
plugin.getLogger().info("MobLeashLimitListener: Daten bereinigt, da enabled=false");
|
||||
return;
|
||||
}
|
||||
|
||||
// Lade Zuordnungen aus leashes.yml
|
||||
FileConfiguration leashesConfig = plugin.getLeashesConfig();
|
||||
if (leashesConfig.contains("leashes")) {
|
||||
for (String entityIdStr : leashesConfig.getConfigurationSection("leashes").getKeys(false)) {
|
||||
UUID entityId;
|
||||
try {
|
||||
entityId = UUID.fromString(entityIdStr);
|
||||
} catch (IllegalArgumentException e) {
|
||||
plugin.getLogger().warning("Ungültige UUID in leashes.yml: " + entityIdStr);
|
||||
continue;
|
||||
}
|
||||
String playerIdStr = leashesConfig.getString("leashes." + entityIdStr);
|
||||
if (playerIdStr != null) {
|
||||
try {
|
||||
UUID playerId = UUID.fromString(playerIdStr);
|
||||
LivingEntity entity = (LivingEntity) plugin.getServer().getEntity(entityId);
|
||||
if (entity != null && entity.isLeashed()) {
|
||||
Set<UUID> playerLeashedEntities = leashedEntities.computeIfAbsent(playerId, k -> new HashSet<>());
|
||||
playerLeashedEntities.add(entityId);
|
||||
leashCounts.put(playerId, playerLeashedEntities.size());
|
||||
entityToPlayer.put(entityId, playerId);
|
||||
} else {
|
||||
// Entferne ungültige Einträge aus leashes.yml
|
||||
leashesConfig.set("leashes." + entityIdStr, null);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
plugin.getLogger().warning("Ungültige Spieler-UUID in leashes.yml für Entity " + entityIdStr + ": " + playerIdStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scanne alle Welten nach angeleinten Tieren, die noch nicht in leashes.yml sind
|
||||
for (org.bukkit.World world : plugin.getServer().getWorlds()) {
|
||||
for (LivingEntity entity : world.getLivingEntities()) {
|
||||
if (entity.isLeashed() && !entityToPlayer.containsKey(entity.getUniqueId())) {
|
||||
// Nur Tiere zählen, die von einem Spieler gehalten werden (für neue Leashes)
|
||||
if (entity.getLeashHolder() instanceof Player) {
|
||||
Player player = (Player) entity.getLeashHolder();
|
||||
UUID playerId = player.getUniqueId();
|
||||
UUID entityId = entity.getUniqueId();
|
||||
|
||||
Set<UUID> playerLeashedEntities = leashedEntities.computeIfAbsent(playerId, k -> new HashSet<>());
|
||||
playerLeashedEntities.add(entityId);
|
||||
leashCounts.put(playerId, playerLeashedEntities.size());
|
||||
entityToPlayer.put(entityId, playerId);
|
||||
|
||||
// Speichere in leashes.yml
|
||||
leashesConfig.set("leashes." + entityId.toString(), playerId.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prüfe, ob das neue Limit überschritten wird
|
||||
for (Map.Entry<UUID, Set<UUID>> entry : leashedEntities.entrySet()) {
|
||||
UUID playerId = entry.getKey();
|
||||
Set<UUID> playerLeashedEntities = entry.getValue();
|
||||
if (playerLeashedEntities.size() > maxLeashCount) {
|
||||
Player player = plugin.getServer().getPlayer(playerId);
|
||||
if (player != null && player.isOnline()) {
|
||||
player.sendMessage(plugin.getMessage("mob-leash-limit.limit-adjusted")
|
||||
.replace("%count%", String.valueOf(playerLeashedEntities.size()))
|
||||
.replace("%max%", String.valueOf(maxLeashCount)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Entferne leere Einträge
|
||||
leashedEntities.entrySet().removeIf(entry -> entry.getValue().isEmpty());
|
||||
leashCounts.entrySet().removeIf(entry -> entry.getValue() == 0);
|
||||
|
||||
// Speichere aktualisierte leashes.yml
|
||||
plugin.saveLeashesConfig();
|
||||
|
||||
plugin.getLogger().info("MobLeashLimitListener: Nach Reload " + leashedEntities.size() + " Spieler mit angeleinten Tieren gefunden.");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
||||
if (!enabled) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
ItemStack itemInHand = player.getInventory().getItemInMainHand();
|
||||
UUID playerId = player.getUniqueId();
|
||||
LivingEntity entity = (LivingEntity) event.getRightClicked();
|
||||
UUID entityId = entity.getUniqueId();
|
||||
|
||||
if (itemInHand != null && itemInHand.getType() == Material.LEAD) {
|
||||
Set<UUID> playerLeashedEntities = leashedEntities.computeIfAbsent(playerId, k -> new HashSet<>());
|
||||
int currentCount = playerLeashedEntities.size();
|
||||
plugin.getLogger().info("PlayerInteractEntity: player=" + player.getName() + ", currentCount=" + currentCount + ", maxLeashCount=" + maxLeashCount);
|
||||
|
||||
if (playerLeashedEntities.contains(entityId)) {
|
||||
// Ableinen
|
||||
playerLeashedEntities.remove(entityId);
|
||||
leashCounts.put(playerId, currentCount - 1);
|
||||
entityToPlayer.remove(entityId);
|
||||
plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
|
||||
plugin.saveLeashesConfig();
|
||||
player.sendMessage(plugin.getMessage("mob-leash-limit.unleashed")
|
||||
.replace("%count%", String.valueOf(currentCount - 1)));
|
||||
|
||||
// Entferne leere Einträge
|
||||
if (playerLeashedEntities.isEmpty()) {
|
||||
leashedEntities.remove(playerId);
|
||||
leashCounts.remove(playerId);
|
||||
}
|
||||
} else {
|
||||
// Anleinen
|
||||
if (currentCount >= maxLeashCount) {
|
||||
player.sendMessage(plugin.getMessage("mob-leash-limit.max-reached")
|
||||
.replace("%count%", String.valueOf(maxLeashCount)));
|
||||
event.setCancelled(true);
|
||||
} else {
|
||||
playerLeashedEntities.add(entityId);
|
||||
leashCounts.put(playerId, currentCount + 1);
|
||||
entityToPlayer.put(entityId, playerId);
|
||||
plugin.getLeashesConfig().set("leashes." + entityId.toString(), playerId.toString());
|
||||
plugin.saveLeashesConfig();
|
||||
player.sendMessage(plugin.getMessage("mob-leash-limit.leashed")
|
||||
.replace("%count%", String.valueOf(currentCount + 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityDeath(EntityDeathEvent event) {
|
||||
if (!enabled) {
|
||||
UUID entityId = event.getEntity().getUniqueId();
|
||||
entityToPlayer.remove(entityId);
|
||||
plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
|
||||
plugin.saveLeashesConfig();
|
||||
return;
|
||||
}
|
||||
|
||||
LivingEntity entity = event.getEntity();
|
||||
UUID entityId = entity.getUniqueId();
|
||||
UUID playerId = entityToPlayer.remove(entityId);
|
||||
|
||||
if (playerId != null) {
|
||||
Set<UUID> playerLeashedEntities = leashedEntities.getOrDefault(playerId, new HashSet<>());
|
||||
playerLeashedEntities.remove(entityId);
|
||||
int newCount = playerLeashedEntities.size();
|
||||
leashCounts.put(playerId, newCount);
|
||||
|
||||
// Entferne aus leashes.yml
|
||||
plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
|
||||
plugin.saveLeashesConfig();
|
||||
|
||||
// Entferne leere Einträge
|
||||
if (playerLeashedEntities.isEmpty()) {
|
||||
leashedEntities.remove(playerId);
|
||||
leashCounts.remove(playerId);
|
||||
}
|
||||
|
||||
Player player = plugin.getServer().getPlayer(playerId);
|
||||
if (player != null && player.isOnline()) {
|
||||
player.sendMessage(plugin.getMessage("mob-leash-limit.entity-died")
|
||||
.replace("%count%", String.valueOf(newCount)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLeashCount(Player player) {
|
||||
UUID playerId = player.getUniqueId();
|
||||
Set<UUID> playerLeashedEntities = leashedEntities.getOrDefault(playerId, new HashSet<>());
|
||||
// Entferne nicht existierende oder nicht angeleinte Entities
|
||||
playerLeashedEntities.removeIf(entityId -> {
|
||||
LivingEntity entity = (LivingEntity) plugin.getServer().getEntity(entityId);
|
||||
if (entity == null || !entity.isLeashed()) {
|
||||
plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
int currentCount = playerLeashedEntities.size();
|
||||
leashCounts.put(playerId, currentCount);
|
||||
|
||||
// Aktualisiere entityToPlayer-Map
|
||||
entityToPlayer.entrySet().removeIf(entry -> entry.getValue().equals(playerId) && !playerLeashedEntities.contains(entry.getKey()));
|
||||
|
||||
// Entferne leere Einträge
|
||||
if (playerLeashedEntities.isEmpty()) {
|
||||
leashedEntities.remove(playerId);
|
||||
leashCounts.remove(playerId);
|
||||
}
|
||||
|
||||
// Falls disabled, bereinige die Daten für diesen Spieler
|
||||
if (!enabled) {
|
||||
playerLeashedEntities.clear();
|
||||
leashedEntities.remove(playerId);
|
||||
leashCounts.remove(playerId);
|
||||
entityToPlayer.entrySet().removeIf(entry -> entry.getValue().equals(playerId));
|
||||
plugin.getLeashesConfig().set("leashes", null);
|
||||
plugin.saveLeashesConfig();
|
||||
}
|
||||
|
||||
plugin.getLogger().info("updateLeashCount: player=" + player.getName() + ", currentCount=" + currentCount);
|
||||
}
|
||||
|
||||
public int getLeashCount(Player player) {
|
||||
updateLeashCount(player);
|
||||
return leashCounts.getOrDefault(player.getUniqueId(), 0);
|
||||
}
|
||||
}
|
@@ -0,0 +1,179 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.boss.BarStyle;
|
||||
import org.bukkit.boss.BossBar;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class NewbieProtectionListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final boolean enabled;
|
||||
private final int durationMinutes;
|
||||
|
||||
// Maps für Zeiten und BossBars
|
||||
private final Map<UUID, Integer> remainingSeconds = new HashMap<>();
|
||||
private final Map<UUID, BossBar> bossBars = new HashMap<>();
|
||||
|
||||
// YAML Datei
|
||||
private File dataFile;
|
||||
private FileConfiguration dataConfig;
|
||||
|
||||
public NewbieProtectionListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
this.enabled = plugin.getConfig().getBoolean("newbie-protection.enabled", true);
|
||||
this.durationMinutes = plugin.getConfig().getInt("newbie-protection.duration-minutes", 30);
|
||||
|
||||
if (!plugin.getDataFolder().exists()) {
|
||||
plugin.getDataFolder().mkdirs();
|
||||
}
|
||||
loadData();
|
||||
|
||||
if (enabled) {
|
||||
startTimer();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
if (!enabled) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
|
||||
// Falls nicht gespeichert, neue Zeit einstellen
|
||||
remainingSeconds.putIfAbsent(uuid, durationMinutes * 60);
|
||||
|
||||
// Bossbar erstellen/anzeigen
|
||||
BossBar bar = Bukkit.createBossBar(
|
||||
ChatColor.GREEN + "Neulingsschutz: " + formatTime(remainingSeconds.get(uuid)),
|
||||
BarColor.GREEN,
|
||||
BarStyle.SOLID
|
||||
);
|
||||
bar.addPlayer(player);
|
||||
bossBars.put(uuid, bar);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
if (!enabled) return;
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
// Bossbar entfernen, aber Zeit bleibt in Map bestehen
|
||||
BossBar bar = bossBars.remove(uuid);
|
||||
if (bar != null) {
|
||||
bar.removeAll();
|
||||
}
|
||||
saveData(); // Beim Verlassen direkt speichern
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
|
||||
if (!enabled) return;
|
||||
if (!(event.getEntity() instanceof Player)) return;
|
||||
|
||||
Player victim = (Player) event.getEntity();
|
||||
UUID vid = victim.getUniqueId();
|
||||
Integer timeLeft = remainingSeconds.get(vid);
|
||||
|
||||
if (timeLeft != null && timeLeft > 0) {
|
||||
event.setCancelled(true);
|
||||
victim.sendMessage(ChatColor.GREEN + "Du bist noch im Neulingsschutz!");
|
||||
if (event.getDamager() instanceof Player) {
|
||||
((Player) event.getDamager()).sendMessage(ChatColor.RED + victim.getName() + " ist noch geschützt!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startTimer() {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (UUID uuid : new HashSet<>(remainingSeconds.keySet())) {
|
||||
Player p = Bukkit.getPlayer(uuid);
|
||||
|
||||
if (p == null || !p.isOnline()) {
|
||||
// Spieler offline → Zeit pausiert
|
||||
continue;
|
||||
}
|
||||
|
||||
int timeLeft = remainingSeconds.getOrDefault(uuid, 0);
|
||||
if (timeLeft <= 0) {
|
||||
// Ablauf: Bossbar weg + Map clean
|
||||
BossBar bar = bossBars.remove(uuid);
|
||||
if (bar != null) bar.removeAll();
|
||||
remainingSeconds.remove(uuid);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Zeit runterzählen
|
||||
timeLeft--;
|
||||
remainingSeconds.put(uuid, timeLeft);
|
||||
|
||||
// Bossbar updaten
|
||||
BossBar bar = bossBars.get(uuid);
|
||||
if (bar != null) {
|
||||
bar.setTitle(ChatColor.GREEN + "Neulingsschutz: " + formatTime(timeLeft));
|
||||
bar.setProgress(Math.max(0, timeLeft / (float) (durationMinutes * 60)));
|
||||
}
|
||||
}
|
||||
saveData(); // zyklisch speichern
|
||||
}
|
||||
}.runTaskTimer(plugin, 20L, 20L);
|
||||
}
|
||||
|
||||
// ---------- Datei Handling ----------
|
||||
private void loadData() {
|
||||
dataFile = new File(plugin.getDataFolder(), "newbieprotection.yml");
|
||||
if (!dataFile.exists()) {
|
||||
try {
|
||||
dataFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
dataConfig = YamlConfiguration.loadConfiguration(dataFile);
|
||||
for (String key : dataConfig.getKeys(false)) {
|
||||
try {
|
||||
UUID uuid = UUID.fromString(key);
|
||||
int sec = dataConfig.getInt(key);
|
||||
remainingSeconds.put(uuid, sec);
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
// WICHTIG: Public gemacht, damit von SurvivalPlus.java aufrufbar
|
||||
public void saveData() {
|
||||
if (dataConfig == null) return;
|
||||
for (Map.Entry<UUID, Integer> entry : remainingSeconds.entrySet()) {
|
||||
dataConfig.set(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
try {
|
||||
dataConfig.save(dataFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private String formatTime(int totalSec) {
|
||||
int min = totalSec / 60;
|
||||
int sec = totalSec % 60;
|
||||
return String.format("%02d:%02d", min, sec);
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class NickLoadListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private static final Pattern HEX_PATTERN = Pattern.compile("#[a-fA-F0-9]{6}");
|
||||
|
||||
public NickLoadListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
String rawNick = plugin.getNicknamesConfig().getString(player.getUniqueId().toString());
|
||||
|
||||
if (rawNick != null && !rawNick.isEmpty()) {
|
||||
String coloredNick = translateColors(rawNick);
|
||||
String finalNick = "§f[" + coloredNick + "§f]";
|
||||
player.setDisplayName(finalNick);
|
||||
player.setPlayerListName(finalNick);
|
||||
}
|
||||
}
|
||||
|
||||
private String translateColors(String input) {
|
||||
String withLegacy = org.bukkit.ChatColor.translateAlternateColorCodes('&', input);
|
||||
return replaceHexColors(withLegacy);
|
||||
}
|
||||
|
||||
private String replaceHexColors(String input) {
|
||||
Matcher matcher = HEX_PATTERN.matcher(input);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while (matcher.find()) {
|
||||
String hexCode = matcher.group();
|
||||
String replacement = ChatColor.of(hexCode).toString();
|
||||
matcher.appendReplacement(sb, replacement);
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,139 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class OreAlarmListener implements Listener {
|
||||
|
||||
private static final long TIME_FRAME_MILLIS = 30 * 1000;
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
private final Map<UUID, Map<Material, OreData>> playerOreData = new HashMap<>();
|
||||
|
||||
private FileConfiguration config;
|
||||
|
||||
// Schwellenwert wird jetzt aus der Config geladen (Fallback DEFAULT_THRESHOLD)
|
||||
private int threshold;
|
||||
|
||||
public OreAlarmListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
this.config = plugin.getConfig();
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
private void loadSettings() {
|
||||
this.threshold = config.getInt("ore-alarm.threshold", 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloadet die Config, lädt die Einstellungen neu und leert gespeicherte Daten.
|
||||
*/
|
||||
public void reloadConfig(FileConfiguration newConfig) {
|
||||
this.config = newConfig;
|
||||
loadSettings();
|
||||
playerOreData.clear();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Material blockType = event.getBlock().getType();
|
||||
|
||||
if (!isMonitoredOre(blockType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UUID playerId = player.getUniqueId();
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
playerOreData.putIfAbsent(playerId, new HashMap<>());
|
||||
Map<Material, OreData> oreMap = playerOreData.get(playerId);
|
||||
|
||||
oreMap.putIfAbsent(blockType, new OreData(0, now));
|
||||
OreData data = oreMap.get(blockType);
|
||||
|
||||
if (now - data.startTime > TIME_FRAME_MILLIS) {
|
||||
data.count = 1;
|
||||
data.startTime = now;
|
||||
} else {
|
||||
data.count++;
|
||||
}
|
||||
|
||||
oreMap.put(blockType, data);
|
||||
|
||||
int threshold = calculateDynamicThreshold(playerId, blockType);
|
||||
if (data.count >= threshold) {
|
||||
String oreName = prettifyMaterialName(blockType);
|
||||
|
||||
String rawMessage = plugin.getLangConfig().getString("orealarm.message",
|
||||
"§c[Erz-Alarm] Spieler §e%player% §chat in %seconds% Sekunden ungewöhnlich viele %ore% abgebaut: §e%count%");
|
||||
|
||||
String message = rawMessage
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%ore%", oreName)
|
||||
.replace("%count%", Integer.toString(data.count))
|
||||
.replace("%seconds%", Long.toString(TIME_FRAME_MILLIS / 1000));
|
||||
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p.isOp() || p.hasPermission("survivalplus.orealarm"))
|
||||
.forEach(p -> p.sendMessage(message));
|
||||
|
||||
data.count = 0;
|
||||
data.startTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMonitoredOre(Material material) {
|
||||
switch (material) {
|
||||
case DIAMOND_ORE:
|
||||
case DEEPSLATE_DIAMOND_ORE:
|
||||
case REDSTONE_ORE:
|
||||
case DEEPSLATE_REDSTONE_ORE:
|
||||
case GOLD_ORE:
|
||||
case DEEPSLATE_GOLD_ORE:
|
||||
case IRON_ORE:
|
||||
case DEEPSLATE_IRON_ORE:
|
||||
case LAPIS_ORE:
|
||||
case DEEPSLATE_LAPIS_ORE:
|
||||
case EMERALD_ORE:
|
||||
case DEEPSLATE_EMERALD_ORE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private int calculateDynamicThreshold(UUID playerId, Material ore) {
|
||||
// Nutzt jetzt das geladene threshold, kann später erweitert werden
|
||||
return threshold;
|
||||
}
|
||||
|
||||
private String prettifyMaterialName(Material material) {
|
||||
String name = material.name().toLowerCase();
|
||||
name = name.replace("_ore", " Erz");
|
||||
name = name.replace("deepslate ", "Tiefgeschichtetes ");
|
||||
name = Character.toUpperCase(name.charAt(0)) + name.substring(1);
|
||||
return name;
|
||||
}
|
||||
|
||||
private static class OreData {
|
||||
int count;
|
||||
long startTime;
|
||||
|
||||
OreData(int count, long startTime) {
|
||||
this.count = count;
|
||||
this.startTime = startTime;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.commands.FriendCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
public class PlayerJoinListener implements Listener {
|
||||
private final FriendCommand friendCommand;
|
||||
|
||||
public PlayerJoinListener(FriendCommand friendCommand) {
|
||||
this.friendCommand = friendCommand;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
friendCommand.notifyFriendsOfJoin(player);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
friendCommand.updateLastOnline(player);
|
||||
}
|
||||
}
|
@@ -0,0 +1,157 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
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.SignChangeEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
|
||||
public class RepairSignListener implements Listener {
|
||||
|
||||
private final FileConfiguration config;
|
||||
private final FileConfiguration lang;
|
||||
|
||||
public RepairSignListener(FileConfiguration config, FileConfiguration lang) {
|
||||
this.config = config;
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
private String msg(String key) {
|
||||
String raw = lang.getString(key, "&c[Missing lang key: " + key + "]");
|
||||
return ChatColor.translateAlternateColorCodes('&', raw);
|
||||
}
|
||||
|
||||
private String msg(String key, String... replacements) {
|
||||
String raw = lang.getString(key, "&c[Missing lang key: " + key + "]");
|
||||
for (int i = 0; i < replacements.length - 1; i += 2) {
|
||||
raw = raw.replace(replacements[i], replacements[i + 1]);
|
||||
}
|
||||
return ChatColor.translateAlternateColorCodes('&', raw);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onSignCreate(SignChangeEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (event.getLine(0) != null && event.getLine(0).equalsIgnoreCase("[Repair]")) {
|
||||
if (player.hasPermission("survivalplus.createrepairsign")) {
|
||||
event.setLine(0, ChatColor.DARK_GREEN + "[Repair]");
|
||||
event.setLine(1, ChatColor.GRAY + config.getString("repair.currency"));
|
||||
event.setLine(2, ChatColor.GOLD + String.valueOf(config.getInt("repair.price")));
|
||||
player.sendMessage(msg("repair.sign_created"));
|
||||
} else {
|
||||
player.sendMessage(msg("repair.no_permission_create"));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verhindert Bearbeitung bestehender Repair-Schilder
|
||||
@EventHandler
|
||||
public void onSignEdit(SignChangeEvent event) {
|
||||
Block block = event.getBlock();
|
||||
if (block.getState() instanceof Sign) {
|
||||
Sign sign = (Sign) block.getState();
|
||||
String line0 = ChatColor.stripColor(sign.getLine(0));
|
||||
if (line0.equalsIgnoreCase("[Repair]") && !event.getPlayer().isOp()) {
|
||||
event.getPlayer().sendMessage(msg("repair.no_edit"));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nur OP darf Schild abbauen
|
||||
@EventHandler
|
||||
public void onSignBreak(BlockBreakEvent event) {
|
||||
if (event.getBlock().getState() instanceof Sign) {
|
||||
Sign sign = (Sign) event.getBlock().getState();
|
||||
String line0 = ChatColor.stripColor(sign.getLine(0));
|
||||
if (line0.equalsIgnoreCase("[Repair]") && !event.getPlayer().isOp()) {
|
||||
event.getPlayer().sendMessage(msg("repair.no_break"));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onSignClick(PlayerInteractEvent event) {
|
||||
if (event.getClickedBlock() == null) return;
|
||||
if (!(event.getClickedBlock().getState() instanceof Sign)) return;
|
||||
|
||||
Sign sign = (Sign) event.getClickedBlock().getState();
|
||||
String line0 = ChatColor.stripColor(sign.getLine(0));
|
||||
if (!line0.equalsIgnoreCase("[Repair]")) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
ItemStack item = player.getInventory().getItemInMainHand();
|
||||
|
||||
if (!(item.getItemMeta() instanceof Damageable)) {
|
||||
player.sendMessage(msg("repair.not_repairable"));
|
||||
return;
|
||||
}
|
||||
|
||||
Damageable meta = (Damageable) item.getItemMeta();
|
||||
int currentDamage = meta.getDamage();
|
||||
|
||||
// Prüfen ob bereits voll repariert
|
||||
if (currentDamage <= 0) {
|
||||
player.sendMessage(msg("repair.already_fully_repaired"));
|
||||
return;
|
||||
}
|
||||
|
||||
String currencyType = config.getString("repair.currency", "GOLD_INGOT");
|
||||
int price = config.getInt("repair.price", 5);
|
||||
|
||||
Material currencyMaterial;
|
||||
try {
|
||||
currencyMaterial = Material.valueOf(currencyType.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
player.sendMessage(msg("repair.invalid_currency"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Prüfung ob Währung erlaubt ist
|
||||
if (!isAllowedCurrency(currencyMaterial)) {
|
||||
player.sendMessage(msg("repair.invalid_currency"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player.getInventory().containsAtLeast(new ItemStack(currencyMaterial), price)) {
|
||||
player.sendMessage(msg("repair.not_enough_currency", "%currency%", currencyType));
|
||||
return;
|
||||
}
|
||||
|
||||
// Zahlung abbuchen
|
||||
player.getInventory().removeItem(new ItemStack(currencyMaterial, price));
|
||||
|
||||
// Item reparieren
|
||||
meta.setDamage(0);
|
||||
item.setItemMeta(meta);
|
||||
|
||||
player.sendMessage(msg("repair.success",
|
||||
"%price%", String.valueOf(price),
|
||||
"%currency%", currencyType));
|
||||
}
|
||||
|
||||
private boolean isAllowedCurrency(Material mat) {
|
||||
switch (mat) {
|
||||
case GOLD_INGOT:
|
||||
case IRON_INGOT:
|
||||
case DIAMOND:
|
||||
case NETHERITE_INGOT:
|
||||
case COPPER_INGOT:
|
||||
case EMERALD:
|
||||
case LAPIS_LAZULI:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,89 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.ChatColor; // Für &-Codes
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SignColorListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
// Muster für Hex-Farbcodes (#FFFFFF)
|
||||
private static final Pattern HEX_PATTERN = Pattern.compile("#[a-fA-F0-9]{6}");
|
||||
// Muster für RGB-Farben rgb(255,255,255)
|
||||
private static final Pattern RGB_PATTERN = Pattern.compile("rgb\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)");
|
||||
|
||||
public SignColorListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onSignChange(SignChangeEvent event) {
|
||||
// Optional: Permission-Check einfügen
|
||||
// if (!event.getPlayer().hasPermission("survivalplus.signcolor")) return;
|
||||
|
||||
for (int i = 0; i < event.getLines().length; i++) {
|
||||
String line = event.getLine(i);
|
||||
if (line != null && !line.isEmpty()) {
|
||||
|
||||
// 1. &-Codes übersetzen (z.B. &a -> §a)
|
||||
String translated = ChatColor.translateAlternateColorCodes('&', line);
|
||||
|
||||
// 2. Hex-Farben ersetzen ( #RRGGBB )
|
||||
translated = replaceHexColors(translated);
|
||||
|
||||
// 3. RGB-Farben ersetzen ( rgb(r,g,b) )
|
||||
translated = replaceRgbColors(translated);
|
||||
|
||||
// 4. Final auf dem Schild setzen
|
||||
event.setLine(i, translated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String replaceHexColors(String input) {
|
||||
Matcher matcher = HEX_PATTERN.matcher(input);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
while (matcher.find()) {
|
||||
String hexCode = matcher.group();
|
||||
// Mit Bungee ChatColor.of in §x-Format umwandeln
|
||||
String color = net.md_5.bungee.api.ChatColor.of(hexCode).toString();
|
||||
matcher.appendReplacement(sb, color);
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String replaceRgbColors(String input) {
|
||||
Matcher matcher = RGB_PATTERN.matcher(input);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
while (matcher.find()) {
|
||||
int r = clampColorValue(matcher.group(1));
|
||||
int g = clampColorValue(matcher.group(2));
|
||||
int b = clampColorValue(matcher.group(3));
|
||||
|
||||
String hex = String.format("#%02X%02X%02X", r, g, b);
|
||||
String color = net.md_5.bungee.api.ChatColor.of(hex).toString();
|
||||
|
||||
matcher.appendReplacement(sb, color);
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private int clampColorValue(String val) {
|
||||
try {
|
||||
int v = Integer.parseInt(val);
|
||||
return Math.min(255, Math.max(0, v));
|
||||
} catch (NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
128
src/main/java/de/viper/survivalplus/listeners/SitListener.java
Normal file
128
src/main/java/de/viper/survivalplus/listeners/SitListener.java
Normal file
@@ -0,0 +1,128 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.event.block.Action;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class SitListener implements Listener {
|
||||
private final SurvivalPlus plugin;
|
||||
private final Map<UUID, ArmorStand> sittingPlayers = new HashMap<>();
|
||||
|
||||
public SitListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public boolean isSitting(Player player) {
|
||||
return sittingPlayers.containsKey(player.getUniqueId());
|
||||
}
|
||||
|
||||
public void sitPlayer(Player player, Location location) {
|
||||
if (sittingPlayers.containsKey(player.getUniqueId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Erstelle einen unsichtbaren ArmorStand als Sitz
|
||||
ArmorStand armorStand = player.getWorld().spawn(location, ArmorStand.class);
|
||||
armorStand.setGravity(false);
|
||||
armorStand.setMarker(true);
|
||||
armorStand.setInvisible(true);
|
||||
armorStand.setInvulnerable(true);
|
||||
armorStand.addPassenger(player);
|
||||
|
||||
sittingPlayers.put(player.getUniqueId(), armorStand);
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
player.sendMessage(lang.getString("sit.success", "§aDu hast dich hingesetzt!"));
|
||||
plugin.getLogger().log(Level.FINE, "Spieler " + player.getName() + " sitzt bei " + locationToString(location));
|
||||
}
|
||||
|
||||
public void standUp(Player player) {
|
||||
UUID playerId = player.getUniqueId();
|
||||
ArmorStand armorStand = sittingPlayers.remove(playerId);
|
||||
if (armorStand != null) {
|
||||
armorStand.remove();
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
player.sendMessage(lang.getString("sit.stand-up", "§aDu bist aufgestanden!"));
|
||||
plugin.getLogger().log(Level.FINE, "Spieler " + player.getName() + " ist aufgestanden");
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
if (event.getHand() != EquipmentSlot.HAND || event.getAction() != Action.RIGHT_CLICK_BLOCK) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
|
||||
if (!player.hasPermission("survivalplus.sit")) {
|
||||
player.sendMessage(lang.getString("no-permission", "§cDu hast keine Berechtigung für diesen Befehl!"));
|
||||
return;
|
||||
}
|
||||
|
||||
Block block = event.getClickedBlock();
|
||||
if (block == null || !isStair(block.getType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wenn der Spieler bereits sitzt, stehe auf
|
||||
if (sittingPlayers.containsKey(player.getUniqueId())) {
|
||||
standUp(player);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Setze den Spieler genau auf der Treppenstufe
|
||||
Location location = block.getLocation();
|
||||
location.setX(location.getX() + 0.5);
|
||||
location.setY(location.getY() + 0.5); // Genau auf der Treppenstufe (halbe Blockhöhe)
|
||||
location.setZ(location.getZ() + 0.5);
|
||||
sitPlayer(player, location);
|
||||
event.setCancelled(true); // Verhindere andere Interaktionen mit der Treppe
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
UUID playerId = player.getUniqueId();
|
||||
if (!sittingPlayers.containsKey(playerId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prüfe, ob der Spieler sich bewegt hat (nur Positionsänderung, nicht Kopfbewegung)
|
||||
Location from = event.getFrom();
|
||||
Location to = event.getTo();
|
||||
if (from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ()) {
|
||||
standUp(player);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
standUp(player);
|
||||
}
|
||||
|
||||
private boolean isStair(Material material) {
|
||||
return material.name().endsWith("_STAIRS");
|
||||
}
|
||||
|
||||
private String locationToString(Location loc) {
|
||||
return String.format("x=%.2f, y=%.2f, z=%.2f, world=%s", loc.getX(), loc.getY(), loc.getZ(), loc.getWorld().getName());
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerBedEnterEvent;
|
||||
import org.bukkit.event.player.PlayerBedLeaveEvent;
|
||||
|
||||
public class SleepListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private double requiredPercentage;
|
||||
|
||||
public SleepListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
reloadConfig(plugin.getConfig());
|
||||
}
|
||||
|
||||
public void reloadConfig(FileConfiguration config) {
|
||||
this.requiredPercentage = config.getDouble("sleep.required-percentage", 50.0);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerBedEnter(PlayerBedEnterEvent event) {
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> checkSleepProgress(event.getPlayer().getWorld()), 1L);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerBedLeave(PlayerBedLeaveEvent event) {
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> checkSleepProgress(event.getPlayer().getWorld()), 1L);
|
||||
}
|
||||
|
||||
private void checkSleepProgress(World world) {
|
||||
long time = world.getTime();
|
||||
if (time < 12541 || time > 23458) return; // Nur bei Nacht prüfen
|
||||
|
||||
int sleeping = 0;
|
||||
int total = 0;
|
||||
|
||||
for (Player player : world.getPlayers()) {
|
||||
if (player.isSleepingIgnored()) continue;
|
||||
total++;
|
||||
if (player.isSleeping()) sleeping++;
|
||||
}
|
||||
|
||||
if (total == 0) return;
|
||||
|
||||
double percent = (sleeping * 100.0) / total;
|
||||
|
||||
if (percent >= requiredPercentage) {
|
||||
world.setTime(0);
|
||||
world.setStorm(false);
|
||||
world.setThundering(false);
|
||||
Bukkit.broadcastMessage(plugin.getMessage("sleep.skipped")
|
||||
.replace("%sleeping%", String.valueOf(sleeping))
|
||||
.replace("%total%", String.valueOf(total)));
|
||||
} else {
|
||||
Bukkit.broadcastMessage(plugin.getMessage("sleep.progress")
|
||||
.replace("%sleeping%", String.valueOf(sleeping))
|
||||
.replace("%total%", String.valueOf(total))
|
||||
.replace("%required%", String.valueOf(requiredPercentage)));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Location;
|
||||
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.entity.EntityDamageByEntityEvent;
|
||||
|
||||
public class SpawnProtectionListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final int radius;
|
||||
private final boolean protectBlockBreak;
|
||||
private final boolean protectBlockPlace;
|
||||
private final boolean protectPvP;
|
||||
private final String bypassPermission;
|
||||
|
||||
public SpawnProtectionListener(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
this.radius = plugin.getConfig().getInt("spawnprotection.radius", 20);
|
||||
this.protectBlockBreak = plugin.getConfig().getBoolean("spawnprotection.protect-block-break", true);
|
||||
this.protectBlockPlace = plugin.getConfig().getBoolean("spawnprotection.protect-block-place", true);
|
||||
this.protectPvP = plugin.getConfig().getBoolean("spawnprotection.protect-pvp", true);
|
||||
this.bypassPermission = plugin.getConfig().getString("spawnprotection.bypass-permission", "survivalplus.spawnprotection.bypass");
|
||||
}
|
||||
|
||||
private boolean isInSpawnProtection(Location loc) {
|
||||
if (loc == null) return false;
|
||||
Location spawn = loc.getWorld().getSpawnLocation();
|
||||
return spawn.distance(loc) <= radius;
|
||||
}
|
||||
|
||||
private boolean canBypass(Player player) {
|
||||
// Nur OPs oder Spieler mit spezieller Berechtigung dürfen bypassen
|
||||
return player.isOp() || player.hasPermission(bypassPermission);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
if (!protectBlockBreak) return;
|
||||
Player player = event.getPlayer();
|
||||
if (isInSpawnProtection(event.getBlock().getLocation()) && !canBypass(player)) {
|
||||
player.sendMessage(plugin.getMessage("spawnprotection.blockbreak-denied"));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
if (!protectBlockPlace) return;
|
||||
Player player = event.getPlayer();
|
||||
if (isInSpawnProtection(event.getBlock().getLocation()) && !canBypass(player)) {
|
||||
player.sendMessage(plugin.getMessage("spawnprotection.blockplace-denied"));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
|
||||
if (!protectPvP) return;
|
||||
if (!(event.getEntity() instanceof Player)) return;
|
||||
if (!(event.getDamager() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) event.getEntity();
|
||||
Player damager = (Player) event.getDamager();
|
||||
|
||||
if (isInSpawnProtection(damaged.getLocation()) && !canBypass(damager)) {
|
||||
damager.sendMessage(plugin.getMessage("spawnprotection.pvp-denied"));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.Manager.StatsManager;
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
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.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class StatsListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final StatsManager statsManager;
|
||||
|
||||
// Spielzeit-Tracking
|
||||
private final Map<UUID, Long> joinTimes = new HashMap<>();
|
||||
|
||||
public StatsListener(SurvivalPlus plugin, StatsManager statsManager) {
|
||||
this.plugin = plugin;
|
||||
this.statsManager = statsManager;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
joinTimes.put(event.getPlayer().getUniqueId(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
long joinTime = joinTimes.getOrDefault(uuid, System.currentTimeMillis());
|
||||
long now = System.currentTimeMillis();
|
||||
long secondsPlayed = (now - joinTime) / 1000;
|
||||
|
||||
statsManager.addPlayTime(uuid, secondsPlayed);
|
||||
statsManager.saveStats();
|
||||
|
||||
joinTimes.remove(uuid);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||
Player player = event.getEntity();
|
||||
UUID uuid = player.getUniqueId();
|
||||
statsManager.addDeaths(uuid, 1);
|
||||
statsManager.saveStats();
|
||||
|
||||
// Optional: Kill-Stat beim Killer erhöhen
|
||||
if (player.getKiller() != null) {
|
||||
Player killer = player.getKiller();
|
||||
statsManager.addKills(killer.getUniqueId(), 1);
|
||||
statsManager.saveStats();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
statsManager.addBlocksBroken(uuid, 1);
|
||||
statsManager.saveStats();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
statsManager.addBlocksPlaced(uuid, 1);
|
||||
statsManager.saveStats();
|
||||
}
|
||||
}
|
@@ -0,0 +1,250 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
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.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.PrepareItemCraftEvent;
|
||||
import org.bukkit.inventory.CraftingInventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ToolUpgradeListener implements Listener {
|
||||
|
||||
private final JavaPlugin plugin;
|
||||
private final NamespacedKey levelKey;
|
||||
private final int maxLevel;
|
||||
private final Map<Integer, Material> levelMaterials = new HashMap<>();
|
||||
private static final int REQUIRED_AMOUNT = 2; // immer 2 pro Slot
|
||||
|
||||
public ToolUpgradeListener(JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.levelKey = new NamespacedKey(plugin, "tool_level");
|
||||
this.maxLevel = plugin.getConfig().getInt("tool-upgrades.max-level", 5);
|
||||
|
||||
// Material aus Config laden
|
||||
for (int i = 1; i <= maxLevel; i++) {
|
||||
String matName = plugin.getConfig().getString("tool-upgrades.levels." + i + ".material");
|
||||
if (matName != null) {
|
||||
try {
|
||||
levelMaterials.put(i, Material.valueOf(matName.toUpperCase()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
plugin.getLogger().warning("Ungültiges Material für Level " + i + ": " + matName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Vorschau-Ergebnis setzen */
|
||||
@EventHandler
|
||||
public void onPrepareCraft(PrepareItemCraftEvent event) {
|
||||
if (!(event.getInventory() instanceof CraftingInventory)) return;
|
||||
CraftingInventory inv = (CraftingInventory) event.getInventory();
|
||||
ItemStack[] matrix = inv.getMatrix();
|
||||
if (matrix.length < 9) {
|
||||
inv.setResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack center = matrix[4];
|
||||
if (center == null || center.getType() == Material.AIR) {
|
||||
inv.setResult(null);
|
||||
return;
|
||||
}
|
||||
if (!isUpgradeableTool(center.getType()) || isWoodTool(center.getType())) {
|
||||
inv.setResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
int currentLevel = getToolLevel(center);
|
||||
if (currentLevel >= maxLevel || currentLevel >= getMaxAllowedLevel(center.getType())) {
|
||||
inv.setResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
Material requiredMat = levelMaterials.get(currentLevel + 1);
|
||||
if (requiredMat == null) {
|
||||
inv.setResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Prüfen ob alle Slots (außer Mitte) mind. 2 Stück vom richtigen Material haben
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
if (i == 4) continue;
|
||||
if (matrix[i] == null || matrix[i].getType() != requiredMat || matrix[i].getAmount() < REQUIRED_AMOUNT) {
|
||||
inv.setResult(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
inv.setResult(createUpgradedTool(center, currentLevel + 1));
|
||||
}
|
||||
|
||||
/** Klick auf Ergebnis-Slot handhaben + Items verbrauchen */
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (!(event.getWhoClicked() instanceof Player)) return;
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
if (!(event.getView().getTopInventory() instanceof CraftingInventory)) return;
|
||||
CraftingInventory inv = (CraftingInventory) event.getView().getTopInventory();
|
||||
if (event.getRawSlot() != 0) return; // Nur Ergebnis-Slot (Slot 0 in Werkbank)
|
||||
if (event.getCurrentItem() == null || event.getCurrentItem().getType() == Material.AIR) return;
|
||||
|
||||
ItemStack[] matrix = inv.getMatrix();
|
||||
ItemStack center = matrix[4];
|
||||
if (center == null || !isUpgradeableTool(center.getType()) || isWoodTool(center.getType())) return;
|
||||
|
||||
int currentLevel = getToolLevel(center);
|
||||
if (currentLevel >= maxLevel || currentLevel >= getMaxAllowedLevel(center.getType())) return;
|
||||
|
||||
Material requiredMat = levelMaterials.get(currentLevel + 1);
|
||||
if (requiredMat == null) return;
|
||||
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
if (i == 4) continue;
|
||||
if (matrix[i] == null || matrix[i].getType() != requiredMat || matrix[i].getAmount() < REQUIRED_AMOUNT) return;
|
||||
}
|
||||
|
||||
// Gültig: Event abbrechen, Upgrade geben, Items verbrauchen
|
||||
event.setCancelled(true);
|
||||
ItemStack result = createUpgradedTool(center, currentLevel + 1);
|
||||
|
||||
// Upgrade dem Spieler geben (Einzel- oder Shift-Klick)
|
||||
if (event.isShiftClick()) {
|
||||
player.getInventory().addItem(result);
|
||||
} else {
|
||||
if (event.getCursor() == null || event.getCursor().getType() == Material.AIR) {
|
||||
event.setCursor(result);
|
||||
} else {
|
||||
player.getInventory().addItem(result);
|
||||
}
|
||||
}
|
||||
|
||||
// Items verbrauchen: 2 pro Slot (außer Mitte), Mitte leeren
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
if (i == 4) {
|
||||
matrix[i] = null; // Mitte leeren
|
||||
} else if (matrix[i] != null) {
|
||||
int newAmount = matrix[i].getAmount() - REQUIRED_AMOUNT;
|
||||
if (newAmount <= 0) {
|
||||
matrix[i] = null;
|
||||
} else {
|
||||
matrix[i].setAmount(newAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
inv.setMatrix(matrix);
|
||||
inv.setResult(null); // Ergebnis-Slot leeren
|
||||
|
||||
// Inventar-Update verzögert senden
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
player.updateInventory();
|
||||
}
|
||||
}.runTaskLater(plugin, 2L); // 2 Ticks Verzögerung
|
||||
}
|
||||
|
||||
/** Effekte beim Benutzen */
|
||||
@EventHandler
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (player.getGameMode() == GameMode.CREATIVE) return;
|
||||
|
||||
ItemStack tool = player.getInventory().getItemInMainHand();
|
||||
if (tool == null || !isUpgradeableTool(tool.getType()) || isWoodTool(tool.getType())) return;
|
||||
|
||||
int level = getToolLevel(tool);
|
||||
if (level <= 0) return;
|
||||
|
||||
// Drop-Multiplikator
|
||||
int multiplier = getDropMultiplier(tool.getType());
|
||||
if (multiplier > 1) {
|
||||
event.setDropItems(false);
|
||||
for (ItemStack drop : event.getBlock().getDrops(tool, player)) {
|
||||
for (int i = 0; i < multiplier; i++) {
|
||||
event.getBlock().getWorld().dropItemNaturally(event.getBlock().getLocation(), drop.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Haste-Effekt
|
||||
int hasteLevel = Math.min(5, level);
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.HASTE, 40, hasteLevel - 1, true, false));
|
||||
|
||||
// Sound
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_USE, 0.4f, 1.6f);
|
||||
}
|
||||
|
||||
/** Upgrade-Item erstellen */
|
||||
private ItemStack createUpgradedTool(ItemStack baseTool, int newLevel) {
|
||||
ItemStack upgraded = baseTool.clone();
|
||||
ItemMeta meta = upgraded.getItemMeta();
|
||||
if (meta != null) {
|
||||
meta.getPersistentDataContainer().set(levelKey, PersistentDataType.INTEGER, newLevel);
|
||||
Enchantment eff = Enchantment.getByKey(NamespacedKey.minecraft("efficiency"));
|
||||
Enchantment fortune = Enchantment.getByKey(NamespacedKey.minecraft("fortune"));
|
||||
if (eff != null) meta.addEnchant(eff, Math.min(5, newLevel), true);
|
||||
int fLevel = getFortuneForMaterial(baseTool.getType());
|
||||
if (fLevel > 0 && fortune != null) meta.addEnchant(fortune, fLevel, true);
|
||||
meta.setLore(Collections.singletonList("§7Upgrade-Level: §e" + newLevel));
|
||||
upgraded.setItemMeta(meta);
|
||||
}
|
||||
return upgraded;
|
||||
}
|
||||
|
||||
/** Hilfsmethoden */
|
||||
private boolean isUpgradeableTool(Material mat) {
|
||||
String n = mat.name();
|
||||
return n.endsWith("_AXE") || n.endsWith("_PICKAXE") ||
|
||||
n.endsWith("_SHOVEL") || n.endsWith("_HOE") ||
|
||||
n.endsWith("_SWORD");
|
||||
}
|
||||
|
||||
private boolean isWoodTool(Material mat) { return mat.name().startsWith("WOODEN"); }
|
||||
|
||||
private int getMaxAllowedLevel(Material mat) {
|
||||
String s = mat.name();
|
||||
if (s.startsWith("IRON")) return 3;
|
||||
if (s.startsWith("GOLDEN")) return 3;
|
||||
if (s.startsWith("DIAMOND")) return maxLevel;
|
||||
if (s.startsWith("NETHERITE")) return maxLevel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int getFortuneForMaterial(Material mat) {
|
||||
String s = mat.name();
|
||||
if (s.startsWith("GOLDEN")) return 1;
|
||||
if (s.startsWith("DIAMOND")) return 2;
|
||||
if (s.startsWith("NETHERITE")) return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int getDropMultiplier(Material mat) {
|
||||
String s = mat.name();
|
||||
if (s.startsWith("GOLDEN")) return 2;
|
||||
if (s.startsWith("DIAMOND")) return 3;
|
||||
if (s.startsWith("NETHERITE")) return 6;
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int getToolLevel(ItemStack item) {
|
||||
if (item == null || !item.hasItemMeta()) return 0;
|
||||
Integer lvl = item.getItemMeta().getPersistentDataContainer().get(levelKey, PersistentDataType.INTEGER);
|
||||
return lvl != null ? lvl : 0;
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
package de.viper.survivalplus.listeners;
|
||||
|
||||
import de.viper.survivalplus.Manager.Warp;
|
||||
import de.viper.survivalplus.Manager.WarpManager;
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class WarpInventoryListener implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final WarpManager warpManager;
|
||||
private final String inventoryTitle;
|
||||
|
||||
public WarpInventoryListener(SurvivalPlus plugin, WarpManager warpManager) {
|
||||
this.plugin = plugin;
|
||||
this.warpManager = warpManager;
|
||||
this.inventoryTitle = ChatColor.GOLD + "Player Warps";
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (event.getView() == null) return;
|
||||
if (event.getView().getTitle() == null) return;
|
||||
if (!event.getView().getTitle().equalsIgnoreCase(inventoryTitle)) return;
|
||||
|
||||
// Verhindert Verschieben und Entnehmen
|
||||
event.setCancelled(true);
|
||||
|
||||
ItemStack clickedItem = event.getCurrentItem();
|
||||
if (clickedItem == null || clickedItem.getType().isAir()) return;
|
||||
if (!(event.getWhoClicked() instanceof Player)) return;
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
|
||||
if (!clickedItem.hasItemMeta() || !clickedItem.getItemMeta().hasDisplayName()) return;
|
||||
String warpName = ChatColor.stripColor(clickedItem.getItemMeta().getDisplayName());
|
||||
|
||||
Warp warpFound = null;
|
||||
for (Warp warp : warpManager.getWarps().values()) {
|
||||
if (warp.getName().equalsIgnoreCase(warpName)) {
|
||||
warpFound = warp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (warpFound == null) {
|
||||
player.sendMessage(ChatColor.RED + "Warp nicht gefunden.");
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Bukkit.getWorld(warpFound.getWorldName()) == null) {
|
||||
player.sendMessage(ChatColor.RED + "Die Welt dieses Warps existiert nicht.");
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
player.teleport(
|
||||
Bukkit.getWorld(warpFound.getWorldName())
|
||||
.getBlockAt((int) warpFound.getX(), (int) warpFound.getY(), (int) warpFound.getZ())
|
||||
.getLocation().add(0.5, 1.0, 0.5) // leicht über dem Block für sicheren Spawn
|
||||
);
|
||||
player.sendMessage(ChatColor.GREEN + "Teleportiert zu Warp: " + warpName);
|
||||
player.closeInventory();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryDrag(InventoryDragEvent event) {
|
||||
if (event.getView() == null) return;
|
||||
if (event.getView().getTitle() == null) return;
|
||||
if (!event.getView().getTitle().equalsIgnoreCase(inventoryTitle)) return;
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
package de.viper.survivalplus.recipe;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.ShapedRecipe;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class BackpackRecipe {
|
||||
|
||||
public static void register(JavaPlugin plugin, org.bukkit.configuration.file.FileConfiguration langConfig) {
|
||||
// Ergebnis-Item: Truhe mit Namen "Rucksack"
|
||||
ItemStack backpack = new ItemStack(Material.CHEST);
|
||||
ItemMeta meta = backpack.getItemMeta();
|
||||
if (meta != null) {
|
||||
meta.setDisplayName(ChatColor.translateAlternateColorCodes('&', langConfig.getString("backpack.name", "&eRucksack")));
|
||||
backpack.setItemMeta(meta);
|
||||
}
|
||||
|
||||
NamespacedKey key = new NamespacedKey(plugin, "backpack");
|
||||
|
||||
ShapedRecipe recipe = new ShapedRecipe(key, backpack);
|
||||
recipe.shape(
|
||||
"S L", // Faden, leer, Leder
|
||||
" C ", // leer, Truhe, leer
|
||||
"S L" // Faden, leer, Leder
|
||||
);
|
||||
recipe.setIngredient('S', Material.STRING); // Faden
|
||||
recipe.setIngredient('L', Material.LEATHER); // Leder
|
||||
recipe.setIngredient('C', Material.CHEST); // Truhe
|
||||
|
||||
Bukkit.addRecipe(recipe);
|
||||
plugin.getLogger().info("Backpack Rezept wurde registriert.");
|
||||
}
|
||||
}
|
45
src/main/java/de/viper/survivalplus/tasks/AutoClearTask.java
Normal file
45
src/main/java/de/viper/survivalplus/tasks/AutoClearTask.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package de.viper.survivalplus.tasks;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Item;
|
||||
|
||||
public class AutoClearTask implements Runnable {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
|
||||
public AutoClearTask(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
FileConfiguration lang = plugin.getLangConfig();
|
||||
|
||||
// Vorwarnung
|
||||
String warningMessage = ChatColor.translateAlternateColorCodes('&',
|
||||
lang.getString("autoclear.warning", "&e&lAchtung! &rIn 10 Sekunden werden alle Items gelöscht!"));
|
||||
Bukkit.broadcastMessage(warningMessage);
|
||||
|
||||
// Nach 10 Sekunden: Items löschen
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
int totalRemoved = 0;
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
for (Item item : world.getEntitiesByClass(Item.class)) {
|
||||
item.remove();
|
||||
totalRemoved++;
|
||||
}
|
||||
}
|
||||
|
||||
// Bestätigung
|
||||
String resultMessage = ChatColor.translateAlternateColorCodes('&',
|
||||
lang.getString("autoclear.cleared", "&c&l%count% Items wurden automatisch gelöscht."));
|
||||
resultMessage = resultMessage.replace("%count%", String.valueOf(totalRemoved));
|
||||
Bukkit.broadcastMessage(resultMessage);
|
||||
|
||||
}, 20L * 10); // 10 Sekunden Verzögerung
|
||||
}
|
||||
}
|
106
src/main/java/de/viper/survivalplus/trade/TradeManager.java
Normal file
106
src/main/java/de/viper/survivalplus/trade/TradeManager.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package de.viper.survivalplus.trade;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TradeManager {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final Map<UUID, TradeSession> activeTrades = new HashMap<>();
|
||||
private final Map<UUID, UUID> pendingRequests = new HashMap<>();
|
||||
|
||||
public TradeManager(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void requestTrade(Player sender, Player target) {
|
||||
if (sender == null || target == null) return;
|
||||
if (isTrading(sender) || isTrading(target)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("trade.already-trading", "§cEiner von euch ist bereits im Handel."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender.getUniqueId().equals(target.getUniqueId())) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("trade.with-yourself-not-allowed", "§cHandel mit dir selbst ist nicht erlaubt!"));
|
||||
return;
|
||||
}
|
||||
|
||||
pendingRequests.put(target.getUniqueId(), sender.getUniqueId());
|
||||
|
||||
String requestText = plugin.getLangConfig().getString("trade.request-text", "%player% möchte mit dir handeln. Klicke hier, um anzunehmen!")
|
||||
.replace("%player%", sender.getName());
|
||||
|
||||
try {
|
||||
net.md_5.bungee.api.chat.TextComponent message = new net.md_5.bungee.api.chat.TextComponent(requestText);
|
||||
message.setColor(net.md_5.bungee.api.ChatColor.GREEN);
|
||||
message.setClickEvent(new net.md_5.bungee.api.chat.ClickEvent(net.md_5.bungee.api.chat.ClickEvent.Action.RUN_COMMAND, "/tradeaccept " + sender.getName()));
|
||||
target.spigot().sendMessage(message);
|
||||
} catch (Throwable ex) {
|
||||
target.sendMessage(requestText + " (/tradeaccept " + sender.getName() + ")");
|
||||
}
|
||||
|
||||
sender.sendMessage(plugin.getLangConfig().getString("trade.request-sent", "§aHandelsanfrage an %player% gesendet.").replace("%player%", target.getName()));
|
||||
}
|
||||
|
||||
public void acceptTrade(Player target, String requesterName) {
|
||||
if (target == null || requesterName == null) return;
|
||||
|
||||
UUID pendingSenderUUID = pendingRequests.get(target.getUniqueId());
|
||||
if (pendingSenderUUID == null) {
|
||||
target.sendMessage(plugin.getLangConfig().getString("trade.no-pending-request", "§cKeine Handelsanfrage gefunden."));
|
||||
return;
|
||||
}
|
||||
|
||||
Player sender = Bukkit.getPlayer(pendingSenderUUID);
|
||||
if (sender == null || !sender.isOnline()) {
|
||||
target.sendMessage(plugin.getLangConfig().getString("trade.player-not-online", "§cDieser Spieler ist nicht online!"));
|
||||
pendingRequests.remove(target.getUniqueId());
|
||||
return;
|
||||
}
|
||||
|
||||
pendingRequests.remove(target.getUniqueId());
|
||||
startTrade(sender, target);
|
||||
}
|
||||
|
||||
public void startTrade(Player sender, Player receiver) {
|
||||
if (isTrading(sender) || isTrading(receiver)) {
|
||||
sender.sendMessage(plugin.getLangConfig().getString("trade.already-trading", "§cEiner von euch ist bereits im Handel."));
|
||||
return;
|
||||
}
|
||||
|
||||
TradeSession session = new TradeSession(plugin, sender, receiver);
|
||||
Bukkit.getPluginManager().registerEvents(session, plugin);
|
||||
|
||||
activeTrades.put(sender.getUniqueId(), session);
|
||||
activeTrades.put(receiver.getUniqueId(), session);
|
||||
|
||||
session.openInventories();
|
||||
|
||||
sender.sendMessage(plugin.getLangConfig().getString("trade.started-sender", "§aTrade gestartet mit %player%").replace("%player%", receiver.getName()));
|
||||
receiver.sendMessage(plugin.getLangConfig().getString("trade.started-receiver", "§a%player% hat dich zu einem Trade eingeladen.").replace("%player%", sender.getName()));
|
||||
}
|
||||
|
||||
public void endTrade(TradeSession session) {
|
||||
if (session == null) return;
|
||||
Player s = session.getSender();
|
||||
Player r = session.getReceiver();
|
||||
if (s != null) activeTrades.remove(s.getUniqueId());
|
||||
if (r != null) activeTrades.remove(r.getUniqueId());
|
||||
session.endSession();
|
||||
}
|
||||
|
||||
public TradeSession getTrade(Player player) {
|
||||
if (player == null) return null;
|
||||
return activeTrades.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
public boolean isTrading(Player player) {
|
||||
if (player == null) return false;
|
||||
return activeTrades.containsKey(player.getUniqueId());
|
||||
}
|
||||
}
|
165
src/main/java/de/viper/survivalplus/trade/TradeSession.java
Normal file
165
src/main/java/de/viper/survivalplus/trade/TradeSession.java
Normal file
@@ -0,0 +1,165 @@
|
||||
package de.viper.survivalplus.trade;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
public class TradeSession implements Listener {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final Player sender;
|
||||
private final Player receiver;
|
||||
|
||||
private final Inventory invSender;
|
||||
private final Inventory invReceiver;
|
||||
|
||||
private boolean senderConfirmed = false;
|
||||
private boolean receiverConfirmed = false;
|
||||
private boolean ended = false; // Flag gegen Rekursion
|
||||
|
||||
public TradeSession(SurvivalPlus plugin, Player sender, Player receiver) {
|
||||
this.plugin = plugin;
|
||||
this.sender = sender;
|
||||
this.receiver = receiver;
|
||||
|
||||
String titleForSender = plugin.getLangConfig().getString("trade.inventory-title", "Handel mit %player%")
|
||||
.replace("%player%", receiver.getName());
|
||||
String titleForReceiver = plugin.getLangConfig().getString("trade.inventory-title", "Handel mit %player%")
|
||||
.replace("%player%", sender.getName());
|
||||
|
||||
this.invSender = Bukkit.createInventory(sender, 27, titleForSender);
|
||||
this.invReceiver = Bukkit.createInventory(receiver, 27, titleForReceiver);
|
||||
|
||||
addConfirmButton(invSender);
|
||||
addConfirmButton(invReceiver);
|
||||
}
|
||||
|
||||
private void addConfirmButton(Inventory inv) {
|
||||
ItemStack confirm = new ItemStack(Material.LIME_CONCRETE);
|
||||
ItemMeta meta = confirm.getItemMeta();
|
||||
meta.setDisplayName(plugin.getLangConfig().getString("trade.confirm-button", "§aBestätigen"));
|
||||
confirm.setItemMeta(meta);
|
||||
inv.setItem(26, confirm);
|
||||
}
|
||||
|
||||
public Player getSender() { return sender; }
|
||||
public Player getReceiver() { return receiver; }
|
||||
|
||||
public void openInventories() {
|
||||
if (sender.isOnline()) sender.openInventory(invSender);
|
||||
if (receiver.isOnline()) receiver.openInventory(invReceiver);
|
||||
}
|
||||
|
||||
private void returnItems(Player player, Inventory inventory) {
|
||||
for (int i = 0; i < 26; i++) {
|
||||
ItemStack item = inventory.getItem(i);
|
||||
if (item != null) player.getInventory().addItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void endSession() {
|
||||
if (ended) return; // Rekursion verhindern
|
||||
ended = true;
|
||||
|
||||
// Items zurückgeben
|
||||
if (sender.isOnline()) returnItems(sender, invSender);
|
||||
if (receiver.isOnline()) returnItems(receiver, invReceiver);
|
||||
|
||||
// Inventories schließen
|
||||
if (sender.isOnline() && sender.getOpenInventory().getTopInventory() == invSender) {
|
||||
sender.closeInventory();
|
||||
}
|
||||
if (receiver.isOnline() && receiver.getOpenInventory().getTopInventory() == invReceiver) {
|
||||
receiver.closeInventory();
|
||||
}
|
||||
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
private Inventory getOwnInventory(Player p) {
|
||||
return p.getUniqueId().equals(sender.getUniqueId()) ? invSender : invReceiver;
|
||||
}
|
||||
|
||||
private Inventory getOtherInventory(Player p) {
|
||||
return p.getUniqueId().equals(sender.getUniqueId()) ? invReceiver : invSender;
|
||||
}
|
||||
|
||||
private void updateOtherView(Player p) {
|
||||
Inventory own = getOwnInventory(p);
|
||||
Inventory other = getOtherInventory(p);
|
||||
for (int i = 0; i < 26; i++) {
|
||||
other.setItem(i, own.getItem(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void executeTrade() {
|
||||
for (int i = 0; i < 26; i++) {
|
||||
ItemStack itemFromSender = invSender.getItem(i);
|
||||
ItemStack itemFromReceiver = invReceiver.getItem(i);
|
||||
|
||||
if (itemFromSender != null) sender.getInventory().addItem(itemFromSender);
|
||||
if (itemFromReceiver != null) receiver.getInventory().addItem(itemFromReceiver);
|
||||
}
|
||||
|
||||
String success = plugin.getLangConfig().getString("trade.success", "§aHandel erfolgreich abgeschlossen!");
|
||||
if (sender.isOnline()) sender.sendMessage(success);
|
||||
if (receiver.isOnline()) receiver.sendMessage(success);
|
||||
|
||||
endSession();
|
||||
}
|
||||
|
||||
private void resetConfirmations() {
|
||||
senderConfirmed = false;
|
||||
receiverConfirmed = false;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent e) {
|
||||
if (!(e.getWhoClicked() instanceof Player p)) return;
|
||||
if (!p.getUniqueId().equals(sender.getUniqueId()) && !p.getUniqueId().equals(receiver.getUniqueId())) return;
|
||||
|
||||
Inventory top = e.getView().getTopInventory();
|
||||
Inventory clicked = e.getClickedInventory();
|
||||
int slot = e.getSlot();
|
||||
|
||||
if (clicked == null) return;
|
||||
|
||||
// Bestätigen-Button
|
||||
if (slot == 26 && clicked.equals(top)) {
|
||||
e.setCancelled(true);
|
||||
if (p.getUniqueId().equals(sender.getUniqueId())) senderConfirmed = true;
|
||||
if (p.getUniqueId().equals(receiver.getUniqueId())) receiverConfirmed = true;
|
||||
|
||||
p.sendMessage(plugin.getLangConfig().getString("trade.confirmed", "§aDu hast den Handel bestätigt!"));
|
||||
|
||||
if (senderConfirmed && receiverConfirmed) executeTrade();
|
||||
return;
|
||||
}
|
||||
|
||||
// Nur das eigene Trade-Inventar editierbar
|
||||
if (clicked.equals(top)) {
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
updateOtherView(p);
|
||||
resetConfirmations();
|
||||
}, 1L);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent e) {
|
||||
if (!(e.getPlayer() instanceof Player p)) return;
|
||||
if (p.getUniqueId().equals(sender.getUniqueId()) || p.getUniqueId().equals(receiver.getUniqueId())) {
|
||||
// Kleine Verzögerung, um StackOverflow zu vermeiden
|
||||
Bukkit.getScheduler().runTaskLater(plugin, this::endSession, 1L);
|
||||
}
|
||||
}
|
||||
}
|
292
src/main/java/de/viper/survivalplus/util/LockSystem.java
Normal file
292
src/main/java/de/viper/survivalplus/util/LockSystem.java
Normal file
@@ -0,0 +1,292 @@
|
||||
package de.viper.survivalplus.util;
|
||||
|
||||
import de.viper.survivalplus.SurvivalPlus;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class LockSystem implements Listener, CommandExecutor {
|
||||
|
||||
private final SurvivalPlus plugin;
|
||||
private final Map<Location, LockData> lockedBlocks = new HashMap<>();
|
||||
private final Set<UUID> lockMode = new HashSet<>();
|
||||
private final Map<UUID, BukkitRunnable> lockTimeoutTasks = new HashMap<>();
|
||||
|
||||
private final File lockFile;
|
||||
private FileConfiguration lockConfig;
|
||||
|
||||
public LockSystem(SurvivalPlus plugin) {
|
||||
this.plugin = plugin;
|
||||
this.lockFile = new File(plugin.getDataFolder(), "locks.yml");
|
||||
this.lockConfig = YamlConfiguration.loadConfiguration(lockFile);
|
||||
loadLocks();
|
||||
}
|
||||
|
||||
public static class LockData {
|
||||
private final String ownerUUID;
|
||||
private final Set<String> friendsUUID;
|
||||
|
||||
public LockData(String ownerUUID) {
|
||||
this.ownerUUID = ownerUUID;
|
||||
this.friendsUUID = new HashSet<>();
|
||||
}
|
||||
|
||||
public String getOwnerUUID() {
|
||||
return ownerUUID;
|
||||
}
|
||||
|
||||
public Set<String> getFriendsUUID() {
|
||||
return friendsUUID;
|
||||
}
|
||||
|
||||
public void addFriend(String friendUUID) {
|
||||
friendsUUID.add(friendUUID);
|
||||
}
|
||||
|
||||
public void removeFriend(String friendUUID) {
|
||||
friendsUUID.remove(friendUUID);
|
||||
}
|
||||
|
||||
public boolean isFriend(String uuid) {
|
||||
return friendsUUID.contains(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadLocks() {
|
||||
lockedBlocks.clear();
|
||||
if (!lockFile.exists()) return;
|
||||
|
||||
for (String key : lockConfig.getKeys(false)) {
|
||||
String path = key + ".";
|
||||
String owner = lockConfig.getString(path + "owner");
|
||||
List<String> friends = lockConfig.getStringList(path + "friends");
|
||||
|
||||
String[] parts = key.split("_");
|
||||
if (parts.length != 4) continue;
|
||||
|
||||
String worldName = parts[0];
|
||||
double x = Double.parseDouble(parts[1]);
|
||||
double y = Double.parseDouble(parts[2]);
|
||||
double z = Double.parseDouble(parts[3]);
|
||||
|
||||
Location loc = new Location(plugin.getServer().getWorld(worldName), x, y, z);
|
||||
LockData lock = new LockData(owner);
|
||||
lock.getFriendsUUID().addAll(friends);
|
||||
|
||||
lockedBlocks.put(loc, lock);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveLocks() {
|
||||
lockConfig = new YamlConfiguration();
|
||||
|
||||
for (Map.Entry<Location, LockData> entry : lockedBlocks.entrySet()) {
|
||||
Location loc = entry.getKey();
|
||||
LockData lock = entry.getValue();
|
||||
String key = loc.getWorld().getName() + "_" + loc.getBlockX() + "_" + loc.getBlockY() + "_" + loc.getBlockZ();
|
||||
|
||||
lockConfig.set(key + ".owner", lock.getOwnerUUID());
|
||||
lockConfig.set(key + ".friends", new ArrayList<>(lock.getFriendsUUID()));
|
||||
}
|
||||
|
||||
try {
|
||||
lockConfig.save(lockFile);
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().severe("Konnte locks.yml nicht speichern!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
||||
|
||||
Block block = event.getClickedBlock();
|
||||
if (block == null) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
Location loc = block.getLocation();
|
||||
boolean isLockable = block.getState() instanceof InventoryHolder || block.getType().name().contains("DOOR");
|
||||
|
||||
if (lockMode.contains(uuid)) {
|
||||
lockMode.remove(uuid);
|
||||
|
||||
BukkitRunnable timeout = lockTimeoutTasks.remove(uuid);
|
||||
if (timeout != null) timeout.cancel();
|
||||
|
||||
if (!isLockable) {
|
||||
player.sendMessage(plugin.getMessage("lock.not-lockable"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (lockedBlocks.containsKey(loc)) {
|
||||
player.sendMessage(plugin.getMessage("lock.already-locked"));
|
||||
} else {
|
||||
lockedBlocks.put(loc, new LockData(uuid.toString()));
|
||||
saveLocks();
|
||||
player.sendMessage(plugin.getMessage("lock.locked"));
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isLockable) return;
|
||||
if (!lockedBlocks.containsKey(loc)) return;
|
||||
|
||||
LockData lock = lockedBlocks.get(loc);
|
||||
String playerUUID = uuid.toString();
|
||||
|
||||
if (lock.getOwnerUUID().equals(playerUUID) || lock.isFriend(playerUUID) || player.isOp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.sendMessage(plugin.getMessage("lock.block-denied"));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Block block = event.getBlock();
|
||||
Location loc = block.getLocation();
|
||||
|
||||
if (!lockedBlocks.containsKey(loc)) return;
|
||||
|
||||
LockData lock = lockedBlocks.get(loc);
|
||||
String playerUUID = player.getUniqueId().toString();
|
||||
|
||||
if (lock.getOwnerUUID().equals(playerUUID) || lock.isFriend(playerUUID) || player.isOp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.sendMessage(plugin.getMessage("lock.break-denied"));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(plugin.getMessage("lock.only-players"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
UUID uuid = player.getUniqueId();
|
||||
|
||||
// NEU: Lock als Subcommand von /sp
|
||||
if (args.length == 0 || args[0].equalsIgnoreCase("lock")) {
|
||||
if (lockMode.contains(uuid)) {
|
||||
player.sendMessage(plugin.getMessage("lock.mode-already"));
|
||||
return true;
|
||||
}
|
||||
|
||||
lockMode.add(uuid);
|
||||
player.sendMessage(plugin.getMessage("lock.mode-start"));
|
||||
|
||||
BukkitRunnable timeout = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (lockMode.remove(uuid)) {
|
||||
player.sendMessage(plugin.getMessage("lock.mode-timeout"));
|
||||
lockTimeoutTasks.remove(uuid);
|
||||
}
|
||||
}
|
||||
};
|
||||
timeout.runTaskLater(plugin, 20 * 30); // 30 Sekunden
|
||||
lockTimeoutTasks.put(uuid, timeout);
|
||||
return true;
|
||||
}
|
||||
|
||||
String sub = args[0].toLowerCase();
|
||||
Block targetBlock = player.getTargetBlockExact(5);
|
||||
if (targetBlock == null) {
|
||||
player.sendMessage(plugin.getMessage("lock.no-target-block"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Location loc = targetBlock.getLocation();
|
||||
|
||||
switch (sub) {
|
||||
case "unlock":
|
||||
LockData lock = lockedBlocks.get(loc);
|
||||
if (lock == null) {
|
||||
player.sendMessage(plugin.getMessage("lock.not-locked"));
|
||||
} else if (!lock.getOwnerUUID().equals(uuid.toString()) && !player.isOp()) {
|
||||
player.sendMessage(plugin.getMessage("lock.no-permission-unlock"));
|
||||
} else {
|
||||
lockedBlocks.remove(loc);
|
||||
saveLocks();
|
||||
player.sendMessage(plugin.getMessage("lock.unlocked"));
|
||||
}
|
||||
break;
|
||||
|
||||
case "friendadd":
|
||||
if (args.length < 2) {
|
||||
player.sendMessage(plugin.getMessage("lock.friendadd.usage"));
|
||||
return true;
|
||||
}
|
||||
lock = lockedBlocks.get(loc);
|
||||
if (lock == null) {
|
||||
player.sendMessage(plugin.getMessage("lock.not-locked"));
|
||||
} else if (!lock.getOwnerUUID().equals(uuid.toString()) && !player.isOp()) {
|
||||
player.sendMessage(plugin.getMessage("lock.no-permission-friends"));
|
||||
} else {
|
||||
Player friend = player.getServer().getPlayer(args[1]);
|
||||
if (friend == null) {
|
||||
player.sendMessage(plugin.getMessage("lock.friendadd.not-found"));
|
||||
} else {
|
||||
lock.addFriend(friend.getUniqueId().toString());
|
||||
saveLocks();
|
||||
player.sendMessage(plugin.getMessage("lock.friendadd.success").replace("{player}", friend.getName()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "friendremove":
|
||||
if (args.length < 2) {
|
||||
player.sendMessage(plugin.getMessage("lock.friendremove.usage"));
|
||||
return true;
|
||||
}
|
||||
lock = lockedBlocks.get(loc);
|
||||
if (lock == null) {
|
||||
player.sendMessage(plugin.getMessage("lock.not-locked"));
|
||||
} else if (!lock.getOwnerUUID().equals(uuid.toString()) && !player.isOp()) {
|
||||
player.sendMessage(plugin.getMessage("lock.no-permission-friends"));
|
||||
} else {
|
||||
Player friend = player.getServer().getPlayer(args[1]);
|
||||
if (friend == null) {
|
||||
player.sendMessage(plugin.getMessage("lock.friendremove.not-found"));
|
||||
} else {
|
||||
lock.removeFriend(friend.getUniqueId().toString());
|
||||
saveLocks();
|
||||
player.sendMessage(plugin.getMessage("lock.friendremove.success").replace("{player}", friend.getName()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
player.sendMessage(plugin.getMessage("lock.unknown-subcommand"));
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user