diff --git a/src/main/java/de/nexuslobby/modules/ScoreboardModule.java b/src/main/java/de/nexuslobby/modules/ScoreboardModule.java index 3510fe0..903a9b2 100644 --- a/src/main/java/de/nexuslobby/modules/ScoreboardModule.java +++ b/src/main/java/de/nexuslobby/modules/ScoreboardModule.java @@ -2,6 +2,7 @@ package de.nexuslobby.modules; import de.nexuslobby.NexusLobby; import de.nexuslobby.api.Module; +import io.papermc.paper.scoreboard.numbers.NumberFormat; import me.clip.placeholderapi.PlaceholderAPI; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -9,6 +10,7 @@ import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scoreboard.*; +import org.bukkit.scoreboard.Criteria; import java.util.HashMap; import java.util.HashSet; @@ -105,25 +107,56 @@ public class ScoreboardModule implements Module, Listener { player.setScoreboard(board); } - // Altes Objective entfernen, damit wir die Zeilen aktualisieren können - // Dasboard selbst bleibt bestehen (wichtig für Tablist-Teams!) + // Altes Objective entfernen Objective oldObj = board.getObjective("lobby"); - if (oldObj != null) { - oldObj.unregister(); + if (oldObj != null) oldObj.unregister(); + + // Alle alten Zeilen-Teams sicher entfernen (großzügige Obergrenze) + for (int i = 0; i < Math.max(lines.size() + 5, 32); i++) { + Team old = board.getTeam("line_" + i); + if (old != null) old.unregister(); } - Objective obj = board.registerNewObjective("lobby", "dummy", - translate(player, title)); + // Paper 1.21: Objective mit Component-Titel registrieren + String translatedTitle = translate(player, title); + Objective obj = board.registerNewObjective( + "lobby", + Criteria.DUMMY, + net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer + .legacySection() + .deserialize(translatedTitle) + ); obj.setDisplaySlot(DisplaySlot.SIDEBAR); - for (int i = 0; i < lines.size(); i++) { - String line = translate(player, lines.get(i)); + // Zahlen global für dieses Objective ausblenden (Paper 1.20.4+ API) + obj.numberFormat(NumberFormat.blank()); - if (line.isEmpty() || line.isBlank()) { - line = ChatColor.values()[i % ChatColor.values().length].toString(); + for (int i = 0; i < lines.size(); i++) { + String lineText = translate(player, lines.get(i)); + + // Eindeutiger unsichtbarer Entry pro Zeile via Farb-Code + String entry = ChatColor.values()[i % ChatColor.values().length].toString() + + ChatColor.RESET; + + // getTeam statt registerNewTeam — verhindert "already in use" Fehler + Team team = board.getTeam("line_" + i); + if (team == null) team = board.registerNewTeam("line_" + i); + team.getEntries().forEach(team::removeEntry); + team.addEntry(entry); + + // Text aufteilen falls länger als 64 Zeichen + if (lineText.length() > 64) { + team.setPrefix(lineText.substring(0, 64)); + team.setSuffix(lineText.substring(64, Math.min(lineText.length(), 128))); + } else { + team.setPrefix(lineText); + team.setSuffix(""); } - obj.getScore(line).setScore(lines.size() - i); + // Score setzen + Zahl pro Eintrag zusätzlich ausblenden + org.bukkit.scoreboard.Score score = obj.getScore(entry); + score.setScore(lines.size() - i); + score.numberFormat(NumberFormat.blank()); } // Kein player.setScoreboard(board) nötig, da wir das Objekt 'board' diff --git a/src/main/java/de/nexuslobby/modules/armorstandtools/ASTListener.java b/src/main/java/de/nexuslobby/modules/armorstandtools/ASTListener.java index cb41831..d58bb09 100644 --- a/src/main/java/de/nexuslobby/modules/armorstandtools/ASTListener.java +++ b/src/main/java/de/nexuslobby/modules/armorstandtools/ASTListener.java @@ -158,6 +158,9 @@ public class ASTListener implements Listener { if (!title.equals("Nexus ArmorStand Editor") && !title.equals("Pose: Körperteil wählen") && !title.startsWith("Achsen:")) return; + + // Amboss-GUI wird von AnvilRenameGUI selbst verwaltet — hier nicht anfassen + if (title.equals("§6Name ändern")) return; event.setCancelled(true); if (!(event.getWhoClicked() instanceof Player p)) return; @@ -175,8 +178,11 @@ public class ASTListener implements Listener { ArmorStandTool tool = ArmorStandTool.get(item); if (tool != null) { tool.execute(as, p); - // Menü aktualisieren, falls wir noch im selben Editor sind - if (p.getOpenInventory().getTitle().equals(title)) { + // Editor nur neu öffnen wenn kein Chat-Input-Modus aktiv ist + // und wir wirklich noch im Editor-Inventar sind + String newTitle = p.getOpenInventory().getTitle(); + if (newTitle.equals("Nexus ArmorStand Editor") + && !AST.chatInputMode.containsKey(p.getUniqueId())) { new ArmorStandGUI(as, p); } } diff --git a/src/main/java/de/nexuslobby/modules/armorstandtools/AnvilRenameGUI.java b/src/main/java/de/nexuslobby/modules/armorstandtools/AnvilRenameGUI.java new file mode 100644 index 0000000..a7f3326 --- /dev/null +++ b/src/main/java/de/nexuslobby/modules/armorstandtools/AnvilRenameGUI.java @@ -0,0 +1,95 @@ +package de.nexuslobby.modules.armorstandtools; + +import de.nexuslobby.NexusLobby; +import io.papermc.paper.event.player.AsyncChatEvent; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; + +/** + * Chat-basierte Namenseingabe für ArmorStands. + * Der Spieler tippt den neuen Namen in den Chat. + * Unterstützt & Farb-Codes. + */ +public class AnvilRenameGUI implements Listener { + + private final Player player; + private final ArmorStand armorStand; + + public AnvilRenameGUI(Player player, ArmorStand armorStand) { + this.player = player; + this.armorStand = armorStand; + + // Listener registrieren + Bukkit.getPluginManager().registerEvents(this, NexusLobby.getInstance()); + + // Inventar schließen + Anweisung anzeigen + player.closeInventory(); + + // Title als UI-Feedback (wie AFK-Anzeige) + player.sendTitle( + "§6§lName eingeben", + "§7Schreibe den neuen Namen in den §eChat§7. §8(&-Codes erlaubt)", + 10, 80, 20 + ); + player.sendMessage("§8[§6Nexus§8] §7Gib den neuen §eNamen §7in den Chat ein. §8(&-Farb-Codes erlaubt)"); + player.sendMessage("§8[§6Nexus§8] §c'abbrechen' §7eingeben zum Abbrechen."); + } + + // ───────────────────────────────────────────────────────────────────────── + // Chat-Event — Paper 1.21 AsyncChatEvent + // ───────────────────────────────────────────────────────────────────────── + + @EventHandler(priority = EventPriority.LOWEST) + public void onChat(AsyncChatEvent event) { + if (!event.getPlayer().equals(player)) return; + + // Chat-Nachricht abfangen + event.setCancelled(true); + + // Plain-Text aus Adventure Component extrahieren + String input = PlainTextComponentSerializer.plainText().serialize(event.message()).trim(); + + // Zurück auf Haupt-Thread wechseln für Bukkit-API Aufrufe + Bukkit.getScheduler().runTask(NexusLobby.getInstance(), () -> { + HandlerList.unregisterAll(this); + AST.chatInputMode.remove(player.getUniqueId()); + + if (input.equalsIgnoreCase("abbrechen")) { + player.sendTitle("§c§lAbgebrochen", "", 5, 30, 10); + player.sendMessage("§8[§6Nexus§8] §cNamensänderung abgebrochen."); + } else { + // & → § Farb-Codes + String newName = ChatColor.translateAlternateColorCodes('&', input); + armorStand.setCustomName(newName); + armorStand.setCustomNameVisible(!ChatColor.stripColor(newName).isEmpty()); + + player.sendTitle("§a§lName gesetzt!", "§r" + newName, 5, 40, 10); + player.sendMessage("§8[§6Nexus§8] §aName gesetzt: " + newName); + } + + // Zurück zum ArmorStand-Editor + if (armorStand.isValid()) { + new ArmorStandGUI(armorStand, player); + } + }); + } + + // ───────────────────────────────────────────────────────────────────────── + // Logout — Listener sauber abmelden + // ───────────────────────────────────────────────────────────────────────── + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + if (!event.getPlayer().equals(player)) return; + HandlerList.unregisterAll(this); + AST.chatInputMode.remove(player.getUniqueId()); + } +} \ No newline at end of file diff --git a/src/main/java/de/nexuslobby/modules/armorstandtools/ArmorStandTool.java b/src/main/java/de/nexuslobby/modules/armorstandtools/ArmorStandTool.java index 41c5eac..088b997 100644 --- a/src/main/java/de/nexuslobby/modules/armorstandtools/ArmorStandTool.java +++ b/src/main/java/de/nexuslobby/modules/armorstandtools/ArmorStandTool.java @@ -51,9 +51,9 @@ public enum ArmorStandTool { case GRAV -> as.setGravity(!as.hasGravity()); case INVUL -> as.setInvulnerable(!as.isInvulnerable()); case SET_NAME -> { - p.closeInventory(); - p.sendMessage("§8[§6Nexus§8] §7Nutze §e/nexuscmd name "); AST.selectedArmorStand.put(p.getUniqueId(), as); + AST.chatInputMode.put(p.getUniqueId(), as); + new AnvilRenameGUI(p, as); // schließt Inventar intern } case CONV_SETUP -> { // Automatisches Markieren via GUI diff --git a/src/main/java/de/nexuslobby/modules/gadgets/Balloon.java b/src/main/java/de/nexuslobby/modules/gadgets/Balloon.java index 9d7d18d..5cfc3fe 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/Balloon.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/Balloon.java @@ -1,79 +1,70 @@ package de.nexuslobby.modules.gadgets; +import java.util.UUID; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; -import java.util.UUID; - public class Balloon { + private final UUID playerUUID; + private final LivingEntity balloonEntity; + private final ArmorStand headStand; - private final UUID playerUUID; - private final LivingEntity balloonEntity; - private final ArmorStand headStand; + public Balloon(Player player, Material balloonMaterial) { + this.playerUUID = player.getUniqueId(); + Location loc = player.getLocation().add((double)0.0F, (double)2.0F, (double)0.0F); + this.balloonEntity = (LivingEntity)loc.getWorld().spawnEntity(loc, EntityType.PIG); + this.balloonEntity.setInvisible(true); + this.balloonEntity.setSilent(true); + this.balloonEntity.setInvulnerable(true); + this.balloonEntity.setGravity(false); + this.balloonEntity.setLeashHolder(player); + this.balloonEntity.addScoreboardTag("nexus_balloon"); + this.headStand = (ArmorStand)loc.getWorld().spawnEntity(loc, EntityType.ARMOR_STAND); + this.headStand.setVisible(false); + this.headStand.setGravity(false); + this.headStand.setMarker(true); + this.headStand.setHelmet(new ItemStack(balloonMaterial)); + } - public Balloon(Player player, Material balloonMaterial) { - this.playerUUID = player.getUniqueId(); - Location loc = player.getLocation().add(0, 2, 0); + public void update() { + Player player = Bukkit.getPlayer(this.playerUUID); + if (player != null && player.isOnline() && this.balloonEntity != null && this.balloonEntity.isValid()) { + if (!this.balloonEntity.isLeashed()) { + this.remove(); + } else { + Location targetLoc = player.getLocation().clone().add((double)0.0F, (double)2.5F, (double)0.0F); + Vector direction = targetLoc.toVector().subtract(this.balloonEntity.getLocation().toVector()); + double distance = direction.length(); + if (distance > (double)5.0F) { + this.balloonEntity.teleport(targetLoc); + } else if (distance > 0.1) { + this.balloonEntity.setVelocity(direction.multiply(0.4)); + } - // Das unsichtbare Träger-Entity - this.balloonEntity = (LivingEntity) loc.getWorld().spawnEntity(loc, EntityType.PIG); - this.balloonEntity.setInvisible(true); - this.balloonEntity.setSilent(true); - this.balloonEntity.setInvulnerable(true); - this.balloonEntity.setGravity(false); - this.balloonEntity.setLeashHolder(player); - // Tag damit GadgetModule Rechtsklicks auf den Ballon abfangen kann - this.balloonEntity.addScoreboardTag("nexus_balloon"); + this.headStand.teleport(this.balloonEntity.getLocation().clone().subtract((double)0.0F, (double)1.5F, (double)0.0F)); + } + } else { + this.remove(); + } + } - // Der ArmorStand, der den farbigen Block trägt - this.headStand = (ArmorStand) loc.getWorld().spawnEntity(loc, EntityType.ARMOR_STAND); - this.headStand.setVisible(false); - this.headStand.setGravity(false); - this.headStand.setMarker(true); - - // Hier wird das übergebene Material gesetzt (z.B. RED_WOOL, BLUE_WOOL etc.) - this.headStand.setHelmet(new ItemStack(balloonMaterial)); - } + public void remove() { + if (this.balloonEntity != null) { + this.balloonEntity.setLeashHolder((Entity)null); + this.balloonEntity.remove(); + } - public void update() { - Player player = org.bukkit.Bukkit.getPlayer(playerUUID); + if (this.headStand != null) { + this.headStand.remove(); + } - if (player == null || !player.isOnline() || balloonEntity == null || !balloonEntity.isValid()) { - remove(); - return; - } - - if (!balloonEntity.isLeashed()) { - remove(); - return; - } - - Location targetLoc = player.getLocation().clone().add(0, 2.5, 0); - Vector direction = targetLoc.toVector().subtract(balloonEntity.getLocation().toVector()); - double distance = direction.length(); - - if (distance > 5) { - balloonEntity.teleport(targetLoc); - } else if (distance > 0.1) { - balloonEntity.setVelocity(direction.multiply(0.4)); - } - - headStand.teleport(balloonEntity.getLocation().clone().subtract(0, 1.5, 0)); - } - - public void remove() { - if (balloonEntity != null) { - balloonEntity.setLeashHolder(null); - balloonEntity.remove(); - } - if (headStand != null) { - headStand.remove(); - } - } -} \ No newline at end of file + } +} diff --git a/src/main/java/de/nexuslobby/modules/gadgets/ChickenRain.java b/src/main/java/de/nexuslobby/modules/gadgets/ChickenRain.java index 8544fa4..3e878d7 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/ChickenRain.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/ChickenRain.java @@ -1,6 +1,11 @@ package de.nexuslobby.modules.gadgets; import de.nexuslobby.NexusLobby; +import java.util.Collections; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; +import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Particle; @@ -10,54 +15,40 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; -import java.util.Random; - public class ChickenRain { + private static final Set activeRains = Collections.synchronizedSet(new HashSet()); - // FIX: Verhindert, dass ein Spieler den Regen mehrfach gleichzeitig starten kann. - // Ohne diese Prüfung konnten beliebig viele parallele Tasks gestartet werden, - // was zu hunderten gespawnten Entities in Sekunden führte. - private static final java.util.Set activeRains = - java.util.Collections.synchronizedSet(new java.util.HashSet<>()); - - public static void start(Player player) { - if (activeRains.contains(player.getUniqueId())) return; // bereits aktiv - activeRains.add(player.getUniqueId()); - new BukkitRunnable() { + public static void start(final Player player) { + if (!activeRains.contains(player.getUniqueId())) { + activeRains.add(player.getUniqueId()); + (new BukkitRunnable() { int ticks = 0; final Random random = new Random(); - @Override public void run() { - if (!player.isOnline() || ticks > 100) { // 100 Ticks = 5 Sekunden - activeRains.remove(player.getUniqueId()); - this.cancel(); - return; - } - - // Alle 2 Ticks ein Huhn spawnen - if (ticks % 2 == 0) { - Location spawnLoc = player.getLocation().add( - (random.nextDouble() - 0.5) * 4, - 4.0, - (random.nextDouble() - 0.5) * 4 - ); - - Chicken chicken = (Chicken) spawnLoc.getWorld().spawnEntity(spawnLoc, EntityType.CHICKEN); - chicken.setBaby(); - chicken.setInvulnerable(true); - - // Nach 1.5 Sekunden "ploppt" das Huhn - Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), () -> { + if (player.isOnline() && this.ticks <= 100) { + if (this.ticks % 2 == 0) { + Location spawnLoc = player.getLocation().add((this.random.nextDouble() - (double)0.5F) * (double)4.0F, (double)4.0F, (this.random.nextDouble() - (double)0.5F) * (double)4.0F); + Chicken chicken = (Chicken)spawnLoc.getWorld().spawnEntity(spawnLoc, EntityType.CHICKEN); + chicken.setBaby(); + chicken.setInvulnerable(true); + Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), () -> { if (chicken.isValid()) { - chicken.getWorld().spawnParticle(Particle.CLOUD, chicken.getLocation(), 5, 0.2, 0.2, 0.2, 0.1); - chicken.getWorld().playSound(chicken.getLocation(), Sound.ENTITY_CHICKEN_EGG, 1.0f, 1.5f); - chicken.remove(); + chicken.getWorld().spawnParticle(Particle.CLOUD, chicken.getLocation(), 5, 0.2, 0.2, 0.2, 0.1); + chicken.getWorld().playSound(chicken.getLocation(), Sound.ENTITY_CHICKEN_EGG, 1.0F, 1.5F); + chicken.remove(); } - }, 30L); - } - ticks++; + + }, 30L); + } + + ++this.ticks; + } else { + ChickenRain.activeRains.remove(player.getUniqueId()); + this.cancel(); + } } - }.runTaskTimer(NexusLobby.getInstance(), 0L, 1L); - } -} \ No newline at end of file + }).runTaskTimer(NexusLobby.getInstance(), 0L, 1L); + } + } +} diff --git a/src/main/java/de/nexuslobby/modules/gadgets/FreezeRay.java b/src/main/java/de/nexuslobby/modules/gadgets/FreezeRay.java index 71e6892..1e4e00e 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/FreezeRay.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/FreezeRay.java @@ -1,104 +1,100 @@ package de.nexuslobby.modules.gadgets; import de.nexuslobby.NexusLobby; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; import org.bukkit.Location; import org.bukkit.Particle; import org.bukkit.Sound; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - public class FreezeRay { + private static final Set frozenPlayers = new HashSet(); - private static final Set frozenPlayers = new HashSet<>(); + public static boolean isFrozen(UUID uuid) { + return frozenPlayers.contains(uuid); + } - public static boolean isFrozen(UUID uuid) { return frozenPlayers.contains(uuid); } + public static void unfreeze(UUID uuid) { + frozenPlayers.remove(uuid); + } - /** Beim Disconnect aufrufen, damit kein Ghost-Eintrag bleibt. */ - public static void unfreeze(UUID uuid) { frozenPlayers.remove(uuid); } + public static void shoot(Player shooter) { + Location start = shooter.getEyeLocation(); + Vector direction = start.getDirection(); + shooter.getWorld().playSound(start, Sound.ENTITY_SNOW_GOLEM_SHOOT, 1.0F, 1.5F); - public static void shoot(Player shooter) { - Location start = shooter.getEyeLocation(); - Vector direction = start.getDirection(); + for(double d = (double)0.0F; d < (double)15.0F; d += 0.3) { + Location point = start.clone().add(direction.clone().multiply(d)); + point.getWorld().spawnParticle(Particle.SNOWFLAKE, point, 1, (double)0.0F, (double)0.0F, (double)0.0F, (double)0.0F); - shooter.getWorld().playSound(start, Sound.ENTITY_SNOW_GOLEM_SHOOT, 1.0f, 1.5f); + for(Entity entity : point.getWorld().getNearbyEntities(point, 0.8, 0.8, 0.8)) { + if (entity instanceof Player target) { + if (target != shooter) { + if (GadgetShield.isProtected(target)) { + String reason = GadgetShield.isAdminShielded(target) ? "Dieser Spieler hat Gadget-Schutz aktiviert." : "Dieser Spieler ist gerade im Parkour."; + shooter.sendMessage("§8[§6Nexus§8] §7" + reason); + return; + } - for (double d = 0; d < 15; d += 0.3) { - Location point = start.clone().add(direction.clone().multiply(d)); - - point.getWorld().spawnParticle(Particle.SNOWFLAKE, point, 1, 0, 0, 0, 0); - - for (Entity entity : point.getWorld().getNearbyEntities(point, 0.8, 0.8, 0.8)) { - if (entity instanceof Player target && target != shooter) { - // Schutz: Parkour-Spieler und Admins mit aktivem Gadget-Schutz - if (GadgetShield.isProtected(target)) { - String reason = GadgetShield.isAdminShielded(target) - ? "Dieser Spieler hat Gadget-Schutz aktiviert." - : "Dieser Spieler ist gerade im Parkour."; - shooter.sendMessage("§8[§6Nexus§8] §7" + reason); - return; - } - applyFreeze(target); - return; - } + applyFreeze(target); + return; + } } + } - if (point.getBlock().getType().isSolid()) { - break; - } - } - } + if (point.getBlock().getType().isSolid()) { + break; + } + } - private static void applyFreeze(Player target) { - if (frozenPlayers.contains(target.getUniqueId())) return; + } - frozenPlayers.add(target.getUniqueId()); - final Location freezeLocation = target.getLocation(); - - target.sendMessage("§8[§6Nexus§8] §bDu wurdest eingefroren!"); - target.getWorld().playSound(target.getLocation(), Sound.BLOCK_GLASS_BREAK, 1.0f, 0.5f); - - new org.bukkit.scheduler.BukkitRunnable() { + private static void applyFreeze(final Player target) { + if (!frozenPlayers.contains(target.getUniqueId())) { + frozenPlayers.add(target.getUniqueId()); + final Location freezeLocation = target.getLocation(); + target.sendMessage("§8[§6Nexus§8] §bDu wurdest eingefroren!"); + target.getWorld().playSound(target.getLocation(), Sound.BLOCK_GLASS_BREAK, 1.0F, 0.5F); + (new BukkitRunnable() { int ticks = 0; - @Override + public void run() { - if (!target.isOnline() || ticks >= 60) { - frozenPlayers.remove(target.getUniqueId()); - this.cancel(); - return; - } + if (target.isOnline() && this.ticks < 60) { + if (GadgetShield.isProtected(target)) { + FreezeRay.frozenPlayers.remove(target.getUniqueId()); + this.cancel(); + } else { + target.setVelocity(new Vector(0, 0, 0)); + Location current = target.getLocation(); + if (current.getX() != freezeLocation.getX() || current.getZ() != freezeLocation.getZ()) { + freezeLocation.setYaw(current.getYaw()); + freezeLocation.setPitch(current.getPitch()); + target.teleport(freezeLocation); + } - // Falls der Spieler während des Einfrierens geschützt wird → sofort freigeben - if (GadgetShield.isProtected(target)) { - frozenPlayers.remove(target.getUniqueId()); - this.cancel(); - return; - } + Location loc = target.getLocation(); - target.setVelocity(new Vector(0, 0, 0)); + for(int i = 0; i < 8; ++i) { + double angle = (double)i * Math.PI / (double)4.0F; + double x = Math.cos(angle) * 0.7; + double z = Math.sin(angle) * 0.7; + loc.getWorld().spawnParticle(Particle.SNOWFLAKE, loc.clone().add(x, (double)1.0F, z), 1, (double)0.0F, (double)0.0F, (double)0.0F, (double)0.0F); + loc.getWorld().spawnParticle(Particle.SNOWFLAKE, loc.clone().add(x, 0.2, z), 1, (double)0.0F, (double)0.0F, (double)0.0F, (double)0.0F); + } - Location current = target.getLocation(); - if (current.getX() != freezeLocation.getX() || current.getZ() != freezeLocation.getZ()) { - freezeLocation.setYaw(current.getYaw()); - freezeLocation.setPitch(current.getPitch()); - target.teleport(freezeLocation); - } - - Location loc = target.getLocation(); - for (int i = 0; i < 8; i++) { - double angle = i * Math.PI / 4; - double x = Math.cos(angle) * 0.7; - double z = Math.sin(angle) * 0.7; - loc.getWorld().spawnParticle(Particle.SNOWFLAKE, loc.clone().add(x, 1, z), 1, 0, 0, 0, 0); - loc.getWorld().spawnParticle(Particle.SNOWFLAKE, loc.clone().add(x, 0.2, z), 1, 0, 0, 0, 0); - } - - ticks += 2; + this.ticks += 2; + } + } else { + FreezeRay.frozenPlayers.remove(target.getUniqueId()); + this.cancel(); + } } - }.runTaskTimer(NexusLobby.getInstance(), 0L, 2L); - } -} \ No newline at end of file + }).runTaskTimer(NexusLobby.getInstance(), 0L, 2L); + } + } +} diff --git a/src/main/java/de/nexuslobby/modules/gadgets/GadgetModule.java b/src/main/java/de/nexuslobby/modules/gadgets/GadgetModule.java index 924fcad..a720419 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/GadgetModule.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/GadgetModule.java @@ -2,26 +2,6 @@ package de.nexuslobby.modules.gadgets; import de.nexuslobby.NexusLobby; import de.nexuslobby.api.Module; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.Sound; -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.entity.PlayerLeashEntityEvent; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.PlayerFishEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerUnleashEntityEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -29,408 +9,759 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Slime; +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerFishEvent; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerUnleashEntityEvent; +import org.bukkit.event.player.PlayerFishEvent.State; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; public class GadgetModule implements Module, Listener { + private final Map discoTasks = new HashMap(); + private final Map activeBalloons = new HashMap(); + private final Map activeEffects = new HashMap(); + private final Set activeShields = new HashSet(); + private final Map meteorCooldowns = new HashMap(); + private final Map freezeCooldowns = new HashMap(); + private final Map grapplingCooldowns = new HashMap(); + private static final long METEOR_CD_MS = 15000L; + private static final long FREEZE_CD_MS = 10000L; + private static final long GRAPPLING_CD_MS = 3000L; + private final String MAIN_TITLE = "§b§lGadgets §8- §7Menü"; + private final String BALLOON_TITLE = "§b§lGadgets §8- §eBallons"; + private final String PARTICLE_TITLE = "§b§lGadgets §8- §dPartikel"; + private final String FUN_TITLE = "§b§lGadgets §8- §6Lustiges"; + private final String HAT_TITLE = "§b§lGadgets §8- §aHüte & Köpfe"; + private final String PET_TITLE = "§b§lGadgets §8- §dBegleiter"; + private final String PET2_TITLE = "§b§lGadgets §8- §dBegleiter §7(2)"; + private final String PET3_TITLE = "§b§lGadgets §8- §dBegleiter §7(3)"; - private final Map activeBalloons = new HashMap<>(); - private final Map activeEffects = new HashMap<>(); - private final Set activeShields = new HashSet<>(); + public String getName() { + return "Gadgets"; + } - // ── Cooldowns ───────────────────────────────────────────────────────────── - /** Letzter Einsatz-Zeitstempel pro Spieler */ - private final Map meteorCooldowns = new HashMap<>(); - private final Map freezeCooldowns = new HashMap<>(); - private final Map grapplingCooldowns = new HashMap<>(); + public void onEnable() { + Bukkit.getPluginManager().registerEvents(this, NexusLobby.getInstance()); + PetManager.register(); + Bukkit.getScheduler().runTaskTimer(NexusLobby.getInstance(), () -> { + PetManager.updatePets(); + this.activeBalloons.values().forEach(Balloon::update); - /** Cooldown-Dauer in Millisekunden */ - private static final long METEOR_CD_MS = 15_000L; // 15 Sekunden - private static final long FREEZE_CD_MS = 10_000L; // 10 Sekunden - private static final long GRAPPLING_CD_MS = 3_000L; // 3 Sekunden - // ────────────────────────────────────────────────────────────────────────── - - private final String MAIN_TITLE = "§b§lGadgets §8- §7Menü"; - private final String BALLOON_TITLE = "§b§lGadgets §8- §eBallons"; - private final String PARTICLE_TITLE = "§b§lGadgets §8- §dPartikel"; - private final String FUN_TITLE = "§b§lGadgets §8- §6Lustiges"; - private final String HAT_TITLE = "§b§lGadgets §8- §aHüte & Köpfe"; - private final String PET_TITLE = "§b§lGadgets §8- §dBegleiter"; - - @Override - public String getName() { return "Gadgets"; } - - @Override - public void onEnable() { - Bukkit.getPluginManager().registerEvents(this, NexusLobby.getInstance()); - PetManager.register(); - - Bukkit.getScheduler().runTaskTimer(NexusLobby.getInstance(), () -> { - PetManager.updatePets(); - activeBalloons.values().forEach(Balloon::update); - for (Player p : Bukkit.getOnlinePlayers()) { - UUID uuid = p.getUniqueId(); - handleSpecialHatEffects(p); - if (activeEffects.containsKey(uuid)) activeEffects.get(uuid).update(p); - if (activeShields.contains(uuid)) ShieldTask.handleShield(p); - } - }, 1L, 1L); - } - - // ───────────────────────────────────────────────────────────────────────── - // Cooldown-Hilfsmethoden - // ───────────────────────────────────────────────────────────────────────── - - /** - * Prüft ob der Spieler noch im Cooldown ist. - * @return true → Gadget darf benutzt werden (Cooldown abgelaufen / nicht gesetzt) - * false → Cooldown noch aktiv, Nachricht wird gesendet - */ - private boolean checkAndSetCooldown(Player player, Map cdMap, long durationMs, String gadgetName) { - long now = System.currentTimeMillis(); - long last = cdMap.getOrDefault(player.getUniqueId(), 0L); - long remaining = durationMs - (now - last); - if (remaining > 0) { - long secLeft = (long) Math.ceil(remaining / 1000.0); - player.sendMessage("§8[§6Nexus§8] §c" + gadgetName + " §7hat noch §e" + secLeft + "s §7Cooldown."); - player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 0.5f, 0.8f); - return false; - } - cdMap.put(player.getUniqueId(), now); - return true; - } - - // ───────────────────────────────────────────────────────────────────────── - // Event Handler - // ───────────────────────────────────────────────────────────────────────── - - /** - * Verhindert Rechtsklick auf den unsichtbaren Ballon-Pig - * (verhindert Leine lösen, Inventar-Öffnen, etc.). - */ - @EventHandler - public void onInteractAtEntity(org.bukkit.event.player.PlayerInteractAtEntityEvent event) { - if (event.getRightClicked().getScoreboardTags().contains("nexus_balloon")) { - event.setCancelled(true); - } - } - - /** - * Verhindert das Ablösen der Leine vom Ballon-Pig durch Rechtsklick. - * Ohne diesen Handler wird die Leine gedroppt und der Ballon verschwindet. - */ - @EventHandler - public void onUnleash(PlayerUnleashEntityEvent event) { - if (event.getEntity().getScoreboardTags().contains("nexus_balloon")) { - event.setCancelled(true); - } - } - - @EventHandler - public void onInteract(PlayerInteractEvent event) { - ItemStack item = event.getItem(); - if (item == null || !item.hasItemMeta() || !item.getItemMeta().hasDisplayName()) return; - String name = item.getItemMeta().getDisplayName(); - - if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK) return; - - Player player = event.getPlayer(); - - // Wenn der Schütze selbst geschützt ist (Parkour oder Admin-Schutz) → kampfbezogene Gadgets sperren - if (GadgetShield.isProtected(player)) { - if (name.equals("§b§lFreeze-Ray") || name.equals("§c§lMeteorit")) { - if (GadgetShield.isAdminShielded(player)) { - player.sendMessage("§8[§6Nexus§8] §cDein Gadget-Schutz ist aktiv. Deaktiviere ihn mit §e/nexus gadgetshield§c."); - } else { - player.sendMessage("§8[§6Parkour§8] §cGadgets können während des Parkours nicht benutzt werden."); - } - event.setCancelled(true); - return; - } - } - - if (name.equals("§b§lFreeze-Ray")) { - event.setCancelled(true); - if (checkAndSetCooldown(player, freezeCooldowns, FREEZE_CD_MS, "§b§lFreeze-Ray")) { - FreezeRay.shoot(player); + for(Player p : Bukkit.getOnlinePlayers()) { + UUID uuid = p.getUniqueId(); + this.handleSpecialHatEffects(p); + if (this.activeEffects.containsKey(uuid)) { + ((ParticleEffect)this.activeEffects.get(uuid)).update(p); } - } else if (name.equals("§6§lPaintball-Gun")) { - PaintballGun.shoot(player); - event.setCancelled(true); - - } else if (name.equals("§c§lMeteorit")) { - event.setCancelled(true); - if (checkAndSetCooldown(player, meteorCooldowns, METEOR_CD_MS, "§c§lMeteorit")) { - MeteorStrike.launch(player); + if (this.activeShields.contains(uuid)) { + ShieldTask.handleShield(p); } - } - } + } - @EventHandler - public void onFish(PlayerFishEvent event) { - Player player = event.getPlayer(); - ItemStack item = player.getInventory().getItemInMainHand(); - if (item.getType() != Material.FISHING_ROD || !item.hasItemMeta() || !item.getItemMeta().hasDisplayName()) return; - if (!item.getItemMeta().getDisplayName().equals("§b§lEnterhaken")) return; + }, 1L, 1L); + } - if (event.getState() == PlayerFishEvent.State.IN_GROUND - || event.getState() == PlayerFishEvent.State.REEL_IN - || event.getState() == PlayerFishEvent.State.CAUGHT_ENTITY) { + private boolean checkAndSetCooldown(Player player, Map cdMap, long durationMs, String gadgetName) { + long now = System.currentTimeMillis(); + long last = (Long)cdMap.getOrDefault(player.getUniqueId(), 0L); + long remaining = durationMs - (now - last); + if (remaining > 0L) { + long secLeft = (long)Math.ceil((double)remaining / (double)1000.0F); + player.sendMessage("§8[§6Nexus§8] §c" + gadgetName + " §7hat noch §e" + secLeft + "s §7Cooldown."); + player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 0.5F, 0.8F); + return false; + } else { + cdMap.put(player.getUniqueId(), now); + return true; + } + } - if (event.getHook() == null) return; + @EventHandler + public void onInteractAtEntity(PlayerInteractAtEntityEvent event) { + if (event.getRightClicked().getScoreboardTags().contains("nexus_balloon")) { + event.setCancelled(true); + } - // Parkour-Check: Schütze im Parkour oder Admin-Schutz → nicht benutzen - if (GadgetShield.isProtected(player)) { - player.sendMessage("§8[§6Nexus§8] §cDer Enterhaken ist gerade nicht verfügbar."); - return; + } + + @EventHandler + public void onUnleash(PlayerUnleashEntityEvent event) { + if (event.getEntity().getScoreboardTags().contains("nexus_balloon")) { + event.setCancelled(true); + } + + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + ItemStack item = event.getItem(); + if (item != null && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) { + String name = item.getItemMeta().getDisplayName(); + if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) { + Player player = event.getPlayer(); + if (!GadgetShield.isProtected(player) || !name.equals("§b§lFreeze-Ray") && !name.equals("§c§lMeteorit")) { + if (name.equals("§b§lFreeze-Ray")) { + event.setCancelled(true); + if (this.checkAndSetCooldown(player, this.freezeCooldowns, 10000L, "§b§lFreeze-Ray")) { + FreezeRay.shoot(player); + } + } else if (name.equals("§6§lPaintball-Gun")) { + PaintballGun.shoot(player); + event.setCancelled(true); + } else if (name.equals("§c§lMeteorit")) { + event.setCancelled(true); + if (this.checkAndSetCooldown(player, this.meteorCooldowns, 15000L, "§c§lMeteorit")) { + MeteorStrike.launch(player); + } + } + + } else { + if (GadgetShield.isAdminShielded(player)) { + player.sendMessage("§8[§6Nexus§8] §cDein Gadget-Schutz ist aktiv. Deaktiviere ihn mit §e/nexus gadgetshield§c."); + } else { + player.sendMessage("§8[§6Parkour§8] §cGadgets können während des Parkours nicht benutzt werden."); + } + + event.setCancelled(true); + } + } + } + } + + @EventHandler + public void onFish(PlayerFishEvent event) { + Player player = event.getPlayer(); + ItemStack item = player.getInventory().getItemInMainHand(); + if (item.getType() == Material.FISHING_ROD && item.hasItemMeta() && item.getItemMeta().hasDisplayName()) { + if (item.getItemMeta().getDisplayName().equals("§b§lEnterhaken")) { + if (event.getState() == State.IN_GROUND || event.getState() == State.REEL_IN || event.getState() == State.CAUGHT_ENTITY) { + if (event.getHook() == null) { + return; + } + + if (GadgetShield.isProtected(player)) { + player.sendMessage("§8[§6Nexus§8] §cDer Enterhaken ist gerade nicht verfügbar."); + return; + } + + if (!this.checkAndSetCooldown(player, this.grapplingCooldowns, 3000L, "§b§lEnterhaken")) { + return; + } + + GrapplingHook.pullPlayer(player, event.getHook().getLocation()); } - if (!checkAndSetCooldown(player, grapplingCooldowns, GRAPPLING_CD_MS, "§b§lEnterhaken")) return; + } + } + } - GrapplingHook.pullPlayer(player, event.getHook().getLocation()); - } - } + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + if (FreezeRay.isFrozen(event.getPlayer().getUniqueId()) && (event.getFrom().getX() != event.getTo().getX() || event.getFrom().getZ() != event.getTo().getZ())) { + event.setTo(event.getFrom().setDirection(event.getTo().getDirection())); + } - @EventHandler - public void onPlayerMove(PlayerMoveEvent event) { - if (FreezeRay.isFrozen(event.getPlayer().getUniqueId())) { - if (event.getFrom().getX() != event.getTo().getX() || event.getFrom().getZ() != event.getTo().getZ()) { - event.setTo(event.getFrom().setDirection(event.getTo().getDirection())); + } + + private void handleSpecialHatEffects(Player p) { + ItemStack hat = p.getInventory().getHelmet(); + if (hat != null && hat.getType() != Material.AIR) { + switch (hat.getType()) { + case CAMPFIRE: + p.getWorld().spawnParticle(Particle.CAMPFIRE_COSY_SMOKE, p.getLocation().add((double)0.0F, 2.2, (double)0.0F), 1, 0.05, 0.05, 0.05, 0.02); + break; + case SPAWNER: + p.getWorld().spawnParticle(Particle.FLAME, p.getLocation().add((double)0.0F, 2.1, (double)0.0F), 1, 0.12, 0.12, 0.12, 0.02); + break; + case SEA_LANTERN: + case BEACON: + p.getWorld().spawnParticle(Particle.END_ROD, p.getLocation().add((double)0.0F, 2.1, (double)0.0F), 1, 0.1, 0.1, 0.1, 0.03); + break; + case ENCHANTING_TABLE: + p.getWorld().spawnParticle(Particle.ENCHANT, p.getLocation().add((double)0.0F, 2.3, (double)0.0F), 1, 0.2, 0.2, 0.2, (double)0.5F); + } + + } + } + + public void openGUI(Player player) { + Inventory gui = Bukkit.createInventory((InventoryHolder)null, 27, "§b§lGadgets §8- §7Menü"); + this.fillEdges(gui); + gui.setItem(10, this.createItem(Material.LEAD, "§e§lBallons", "§7Wähle einen fliegenden Begleiter")); + gui.setItem(11, this.createItem(Material.GOLDEN_HELMET, "§a§lHüte", "§7Setze dir etwas auf den Kopf")); + gui.setItem(13, this.createItem(Material.BONE, "§d§lBegleiter", "§7Echte Tiere, die dir folgen")); + gui.setItem(15, this.createItem(Material.FIREWORK_ROCKET, "§6§lLustiges", "§7Witzige Effekte")); + gui.setItem(16, this.createItem(Material.NETHER_STAR, "§d§lPartikel", "§7Magische Auren & Effekte")); + gui.setItem(22, this.createItem(Material.BARRIER, "§c§lStopp", "§7Alle Gadgets entfernen")); + player.openInventory(gui); + } + + private void openHatGUI(Player player) { + Inventory gui = Bukkit.createInventory((InventoryHolder)null, 45, "§b§lGadgets §8- §aHüte & Köpfe"); + this.fillEdges(gui); + gui.setItem(10, this.createItem(Material.JACK_O_LANTERN, "§6Kürbis-Hut", "§7Es ist immer Halloween!")); + gui.setItem(11, this.createItem(Material.SEA_LANTERN, "§bMeeres-Leuchten", "§7§oEffekt: Glitzern")); + gui.setItem(12, this.createItem(Material.GLOWSTONE, "§eGlowstone-Kopf", "§7Werde zur Lampe")); + gui.setItem(13, this.createItem(Material.TNT, "§cExplosiv-Hut", "§7Vorsicht, heiß!")); + gui.setItem(14, this.createItem(Material.GLASS, "§fAstronaut", "§7Bereit für den Mond?")); + gui.setItem(15, this.createItem(Material.DRAGON_HEAD, "§5Enderdrache", "§7Der König der Lüfte")); + gui.setItem(16, this.createItem(Material.CAKE, "§dKuchen-Kopf", "§7Jeder mag Kuchen!")); + gui.setItem(19, this.createItem(Material.SLIME_BLOCK, "§aGlibber-Block", "§7Ziemlich klebrig...")); + gui.setItem(20, this.createItem(Material.MELON, "§aMelonen-Helm", "§7Frisch und saftig")); + gui.setItem(21, this.createItem(Material.HAY_BLOCK, "§eStrohhut", "§7Sommer auf dem Land")); + gui.setItem(22, this.createItem(Material.SPAWNER, "§8Monster-Käfig", "§7§oEffekt: Flammen")); + gui.setItem(23, this.createItem(Material.CRAFTING_TABLE, "§6Werkbank", "§7Immer am Basteln")); + gui.setItem(24, this.createItem(Material.BOOKSHELF, "§fBücherregal", "§7Ein wahrer Schlaukopf")); + gui.setItem(25, this.createItem(Material.HONEY_BLOCK, "§6Honig-Hut", "§7Süß und klebrig")); + gui.setItem(28, this.createItem(Material.GOLD_BLOCK, "§6Gold-Bonze", "§7Zeig was du hast")); + gui.setItem(29, this.createItem(Material.DIAMOND_ORE, "§bDiamant-Erz", "§7Bau mich bloß nicht ab!")); + gui.setItem(30, this.createItem(Material.BEACON, "§fLeuchtfeuer", "§7§oEffekt: Glitzern")); + gui.setItem(31, this.createItem(Material.CONDUIT, "§3Auge des Meeres", "§7Die Macht von Atlantis")); + gui.setItem(32, this.createItem(Material.ENCHANTING_TABLE, "§dMagier", "§7§oEffekt: Runen")); + gui.setItem(33, this.createItem(Material.CAMPFIRE, "§cHeißer Kopf", "§7§oEffekt: Rauch")); + gui.setItem(34, this.createItem(Material.SKELETON_SKULL, "§7Skelett", "§7Ein wenig gruselig")); + gui.setItem(36, this.createItem(Material.ARROW, "§7Zurück", "§8Zum Hauptmenü")); + gui.setItem(40, this.createItem(Material.NETHER_STAR, "§7Hauptmenü", "§8Zum Gadget-Hauptmenü")); + player.openInventory(gui); + } + + private void openPetGUI(Player player) { + Inventory gui = Bukkit.createInventory((InventoryHolder)null, 54, "§b§lGadgets §8- §dBegleiter"); + this.fillEdges(gui); + gui.setItem(10, this.createItem(Material.BONE, "§fBaby-Wolf", "§7Ein kleiner treuer Begleiter")); + gui.setItem(11, this.createItem(Material.BONE, "§7Baby-Ashen Wolf", "§7Ein kleiner Aschen-Wolf")); + gui.setItem(12, this.createItem(Material.CAT_SPAWN_EGG, "§6Baby-Katze", "§7Ein kleiner Schmusefreund")); + gui.setItem(13, this.createItem(Material.PANDA_SPAWN_EGG, "§aBaby-Panda", "§7Ein kleiner Flauschball")); + gui.setItem(14, this.createItem(Material.FOX_SPAWN_EGG, "§6Baby-Fuchs", "§7Ein kleiner Schlaukopf")); + gui.setItem(15, this.createItem(Material.FROG_SPAWN_EGG, "§aBaby-Frosch", "§7Ein kleiner Hopsfreund")); + gui.setItem(16, this.createItem(Material.TURTLE_SPAWN_EGG, "§2Baby-Schildkröte", "§7Ein kleiner Panzenträger")); + gui.setItem(28, this.createItem(Material.FOX_SPAWN_EGG, "§bBaby-Schneefuchs", "§7Ein kleiner Schnee-Fuchs")); + gui.setItem(29, this.createItem(Material.RABBIT_SPAWN_EGG, "§fBaby-Kaninchen", "§7Ein kleiner Flitzer")); + gui.setItem(30, this.createItem(Material.AXOLOTL_SPAWN_EGG, "§dBaby-Axolotl", "§7Ein kleiner Wasserfreund")); + gui.setItem(31, this.createItem(Material.OCELOT_SPAWN_EGG, "§6Baby-Ozelot", "§7Ein kleiner Schleicher")); + gui.setItem(32, this.createItem(Material.POLAR_BEAR_SPAWN_EGG, "§fBaby-Eisbär", "§7Ein kleiner Eisbär")); + gui.setItem(33, this.createItem(Material.BEE_SPAWN_EGG, "§eBaby-Biene", "§7Eine kleine Biene")); + gui.setItem(34, this.createItem(Material.CHICKEN_SPAWN_EGG, "§fKüken", "§7Ein kleines Huhn")); + gui.setItem(19, this.createItem(Material.BONE, "§fWolf", "§7Ein treuer Begleiter")); + gui.setItem(20, this.createItem(Material.BONE, "§7Ashen Wolf", "§7Ein seltener Aschen-Wolf")); + gui.setItem(21, this.createItem(Material.CAT_SPAWN_EGG, "§6Katze", "§7Ein verschmuster Freund")); + gui.setItem(22, this.createItem(Material.PANDA_SPAWN_EGG, "§aPanda", "§7Ein gemütlicher Zeitgenosse")); + gui.setItem(23, this.createItem(Material.FOX_SPAWN_EGG, "§6Fuchs", "§7Ein schlauer Begleiter")); + gui.setItem(24, this.createItem(Material.FROG_SPAWN_EGG, "§aFrosch", "§7Ein echter Hopsmeister")); + gui.setItem(25, this.createItem(Material.TURTLE_SPAWN_EGG, "§2Schildkröte", "§7Gemütlich und gelassen")); + gui.setItem(37, this.createItem(Material.FOX_SPAWN_EGG, "§bSchneefuchs", "§7Ein Fuchs aus kalten Biomen")); + gui.setItem(38, this.createItem(Material.RABBIT_SPAWN_EGG, "§fKaninchen", "§7Ein schneller Hopper")); + gui.setItem(39, this.createItem(Material.AXOLOTL_SPAWN_EGG, "§dAxolotl", "§7Ein seltener Wasserfreund")); + gui.setItem(40, this.createItem(Material.OCELOT_SPAWN_EGG, "§6Ozelot", "§7Ein wachsamer Begleiter")); + gui.setItem(41, this.createItem(Material.POLAR_BEAR_SPAWN_EGG, "§fEisbär", "§7Ein starker Eisbär")); + gui.setItem(42, this.createItem(Material.BEE_SPAWN_EGG, "§eBiene", "§7Eine fleißige Biene")); + gui.setItem(43, this.createItem(Material.CHICKEN_SPAWN_EGG, "§fHuhn", "§7Ein gackerndes Huhn")); + gui.setItem(45, this.createItem(Material.ARROW, "§7Zurück", "§8Zum Hauptmenü")); + gui.setItem(49, this.createItem(Material.NETHER_STAR, "§7Hauptmenü", "§8Zum Gadget-Hauptmenü")); + gui.setItem(53, this.createItem(Material.ARROW, "§7Weiter", "§8Seite 2")); + player.openInventory(gui); + } + + private void openPetGUI2(Player player) { + Inventory gui = Bukkit.createInventory((InventoryHolder)null, 54, "§b§lGadgets §8- §dBegleiter §7(2)"); + this.fillEdges(gui); + gui.setItem(19, this.createItem(Material.ARMADILLO_SPAWN_EGG, "§7Baby-Armadillo", "§7Ein kleiner Gürteltier")); + gui.setItem(28, this.createItem(Material.ARMADILLO_SPAWN_EGG, "§7Armadillo", "§7Ein Gürteltier")); + gui.setItem(45, this.createItem(Material.ARROW, "§7Zurück", "§8Seite 1")); + gui.setItem(49, this.createItem(Material.NETHER_STAR, "§7Hauptmenü", "§8Zum Gadget-Hauptmenü")); + gui.setItem(53, this.createItem(Material.ARROW, "§7Weiter", "§8Seite 3")); + player.openInventory(gui); + } + + private void openPetGUI3(Player player) { + Inventory gui = Bukkit.createInventory((InventoryHolder)null, 54, "§b§lGadgets §8- §dBegleiter §7(3)"); + this.fillEdges(gui); + gui.setItem(19, this.createItem(Material.PARROT_SPAWN_EGG, "§cPapagei", "§7Ein bunter Begleiter")); + gui.setItem(20, this.createItem(Material.ALLAY_SPAWN_EGG, "§bAllay", "§7Ein magischer Helfer")); + gui.setItem(21, this.createItem(Material.SNIFFER_SPAWN_EGG, "§aSniffer", "§7Ein uraltes Tier")); + gui.setItem(45, this.createItem(Material.ARROW, "§7Zurück", "§8Seite 2")); + gui.setItem(49, this.createItem(Material.NETHER_STAR, "§7Hauptmenü", "§8Zum Gadget-Hauptmenü")); + player.openInventory(gui); + } + + private void openBalloonGUI(Player player) { + Inventory gui = Bukkit.createInventory((InventoryHolder)null, 45, "§b§lGadgets §8- §eBallons"); + this.fillEdges(gui); + Material[] wools = new Material[]{Material.WHITE_WOOL, Material.ORANGE_WOOL, Material.MAGENTA_WOOL, Material.LIGHT_BLUE_WOOL, Material.YELLOW_WOOL, Material.LIME_WOOL, Material.PINK_WOOL, Material.GRAY_WOOL, Material.CYAN_WOOL, Material.PURPLE_WOOL, Material.BLUE_WOOL, Material.BROWN_WOOL, Material.GREEN_WOOL, Material.RED_WOOL}; + int slot = 10; + + for(Material m : wools) { + if (slot == 17) { + slot = 19; + } + if (slot == 26) { + slot = 28; + } + + gui.setItem(slot++, this.createItem(m, "§fBallon: " + m.name().replace("_WOOL", ""), "§7Klicke zum Ausrüsten")); + } + + gui.setItem(36, this.createItem(Material.ARROW, "§7Zurück", "§8Zum Hauptmenü")); + gui.setItem(40, this.createItem(Material.NETHER_STAR, "§7Hauptmenü", "§8Zum Gadget-Hauptmenü")); + player.openInventory(gui); + } + + private void openParticleGUI(Player player) { + Inventory gui = Bukkit.createInventory((InventoryHolder)null, 36, "§b§lGadgets §8- §dPartikel"); + this.fillEdges(gui); + gui.setItem(11, this.createItem(Material.POPPY, "§cHerzchen-Aura", "§7Verbreite Liebe in der Lobby")); + gui.setItem(13, this.createItem(Material.BLAZE_POWDER, "§6Flammen-Ring", "§7Lass es brennen!")); + gui.setItem(15, this.createItem(Material.WATER_BUCKET, "§bRegenwolke", "§7Deine persönliche Abkühlung")); + gui.setItem(27, this.createItem(Material.ARROW, "§7Zurück", "§8Zum Hauptmenü")); + gui.setItem(31, this.createItem(Material.NETHER_STAR, "§7Hauptmenü", "§8Zum Gadget-Hauptmenü")); + player.openInventory(gui); + } + + private void openFunGUI(Player player) { + Inventory gui = Bukkit.createInventory((InventoryHolder)null, 36, "§b§lGadgets §8- §6Lustiges"); + this.fillEdges(gui); + gui.setItem(10, this.createItem(Material.FISHING_ROD, "§b§lEnterhaken", "§7Zieh dich durch die Luft! §8(3s CD)")); + gui.setItem(11, this.createItem(Material.PACKED_ICE, "§b§lFreeze-Ray", "§7Friere andere ein! §8(10s CD)")); + gui.setItem(12, this.createItem(Material.GOLDEN_HOE, "§6§lPaintball-Gun", "§7Male die Lobby bunt aus!")); + gui.setItem(13, this.createItem(Material.FEATHER, "§f§lMini-Tornado", "§7Wirbele dich herum!")); + gui.setItem(14, this.createItem(Material.FIRE_CHARGE, "§c§lMeteorit", "§7Lass es krachen! §8(15s CD)")); + gui.setItem(15, this.createItem(Material.SHIELD, "§5§lSchutzzone", "§7Halte andere auf Distanz")); + gui.setItem(16, this.createItem(Material.EGG, "§f§lChicken-Rain", "§7Gack-Gack! Hühner überall!")); + gui.setItem(19, this.createItem(Material.SLIME_BALL, "§a§lMob-Party", "§7Lustige Mini-Mobs tanzen um dich!")); + gui.setItem(20, this.createItem(Material.NOTE_BLOCK, "§d§lTanz-Emote", "§7Führe einen Tanz auf!")); + gui.setItem(21, this.createItem(Material.FIREWORK_ROCKET, "§c§lKonfetti-Kanone", "§7Schieße Konfetti in die Luft!")); + gui.setItem(22, this.createItem(Material.TNT, "§c§lFake-TNT", "§7Täusche andere mit einer harmlosen Explosion!")); + gui.setItem(27, this.createItem(Material.ARROW, "§7Zurück", "§8Zum Hauptmenü")); + gui.setItem(31, this.createItem(Material.NETHER_STAR, "§7Hauptmenü", "§8Zum Gadget-Hauptmenü")); + player.openInventory(gui); + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + String title = event.getView().getTitle(); + if (title.startsWith("§b§lGadgets")) { + event.setCancelled(true); + final Player player = (Player)event.getWhoClicked(); + ItemStack item = event.getCurrentItem(); + if (item != null && item.getType() != Material.AIR) { + if (item.getType() == Material.ARROW) { + String displayName = item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : ""; + if (displayName.equals("§7Weiter")) { + if (title.equals("§b§lGadgets §8- §dBegleiter")) { + this.openPetGUI2(player); + return; + } + + if (title.equals("§b§lGadgets §8- §dBegleiter §7(2)")) { + this.openPetGUI3(player); + return; + } + } + + if (displayName.equals("§7Zurück")) { + if (title.equals("§b§lGadgets §8- §dBegleiter §7(2)")) { + this.openPetGUI(player); + return; + } + + if (title.equals("§b§lGadgets §8- §dBegleiter §7(3)")) { + this.openPetGUI2(player); + return; + } + + this.openGUI(player); + return; + } } - } - } - // ───────────────────────────────────────────────────────────────────────── - // GUI - // ───────────────────────────────────────────────────────────────────────── - - private void handleSpecialHatEffects(Player p) { - ItemStack hat = p.getInventory().getHelmet(); - if (hat == null || hat.getType() == Material.AIR) return; - - switch (hat.getType()) { - case CAMPFIRE -> p.getWorld().spawnParticle(Particle.CAMPFIRE_COSY_SMOKE, p.getLocation().add(0, 2.2, 0), 1, 0.05, 0.05, 0.05, 0.02); - case SPAWNER -> p.getWorld().spawnParticle(Particle.FLAME, p.getLocation().add(0, 2.1, 0), 1, 0.12, 0.12, 0.12, 0.02); - case SEA_LANTERN, BEACON -> p.getWorld().spawnParticle(Particle.END_ROD, p.getLocation().add(0, 2.1, 0), 1, 0.1, 0.1, 0.1, 0.03); - case ENCHANTING_TABLE -> p.getWorld().spawnParticle(Particle.ENCHANT, p.getLocation().add(0, 2.3, 0), 1, 0.2, 0.2, 0.2, 0.5); - default -> {} - } - } - - public void openGUI(Player player) { - Inventory gui = Bukkit.createInventory(null, 27, MAIN_TITLE); - fillEdges(gui); - gui.setItem(10, createItem(Material.LEAD, "§e§lBallons", "§7Wähle einen fliegenden Begleiter")); - gui.setItem(11, createItem(Material.GOLDEN_HELMET, "§a§lHüte", "§7Setze dir etwas auf den Kopf")); - gui.setItem(13, createItem(Material.BONE, "§d§lBegleiter", "§7Echte Tiere, die dir folgen")); - gui.setItem(15, createItem(Material.FIREWORK_ROCKET,"§6§lLustiges", "§7Witzige Effekte")); - gui.setItem(16, createItem(Material.NETHER_STAR, "§d§lPartikel", "§7Magische Auren & Effekte")); - gui.setItem(22, createItem(Material.BARRIER, "§c§lStopp", "§7Alle Gadgets entfernen")); - player.openInventory(gui); - } - - private void openHatGUI(Player player) { - Inventory gui = Bukkit.createInventory(null, 45, HAT_TITLE); - fillEdges(gui); - gui.setItem(10, createItem(Material.JACK_O_LANTERN, "§6Kürbis-Hut", "§7Es ist immer Halloween!")); - gui.setItem(11, createItem(Material.SEA_LANTERN, "§bMeeres-Leuchten", "§7§oEffekt: Glitzern")); - gui.setItem(12, createItem(Material.GLOWSTONE, "§eGlowstone-Kopf", "§7Werde zur Lampe")); - gui.setItem(13, createItem(Material.TNT, "§cExplosiv-Hut", "§7Vorsicht, heiß!")); - gui.setItem(14, createItem(Material.GLASS, "§fAstronaut", "§7Bereit für den Mond?")); - gui.setItem(15, createItem(Material.DRAGON_HEAD, "§5Enderdrache", "§7Der König der Lüfte")); - gui.setItem(16, createItem(Material.CAKE, "§dKuchen-Kopf", "§7Jeder mag Kuchen!")); - gui.setItem(19, createItem(Material.SLIME_BLOCK, "§aGlibber-Block", "§7Ziemlich klebrig...")); - gui.setItem(20, createItem(Material.MELON, "§aMelonen-Helm", "§7Frisch und saftig")); - gui.setItem(21, createItem(Material.HAY_BLOCK, "§eStrohhut", "§7Sommer auf dem Land")); - gui.setItem(22, createItem(Material.SPAWNER, "§8Monster-Käfig", "§7§oEffekt: Flammen")); - gui.setItem(23, createItem(Material.CRAFTING_TABLE, "§6Werkbank", "§7Immer am Basteln")); - gui.setItem(24, createItem(Material.BOOKSHELF, "§fBücherregal", "§7Ein wahrer Schlaukopf")); - gui.setItem(25, createItem(Material.HONEY_BLOCK, "§6Honig-Hut", "§7Süß und klebrig")); - gui.setItem(28, createItem(Material.GOLD_BLOCK, "§6Gold-Bonze", "§7Zeig was du hast")); - gui.setItem(29, createItem(Material.DIAMOND_ORE, "§bDiamant-Erz", "§7Bau mich bloß nicht ab!")); - gui.setItem(30, createItem(Material.BEACON, "§fLeuchtfeuer", "§7§oEffekt: Glitzern")); - gui.setItem(31, createItem(Material.CONDUIT, "§3Auge des Meeres", "§7Die Macht von Atlantis")); - gui.setItem(32, createItem(Material.ENCHANTING_TABLE,"§dMagier", "§7§oEffekt: Runen")); - gui.setItem(33, createItem(Material.CAMPFIRE, "§cHeißer Kopf", "§7§oEffekt: Rauch")); - gui.setItem(34, createItem(Material.SKELETON_SKULL, "§7Skelett", "§7Ein wenig gruselig")); - gui.setItem(40, createItem(Material.ARROW, "§7Zurück", "§8Zum Hauptmenü")); - player.openInventory(gui); - } - - private void openPetGUI(Player player) { - Inventory gui = Bukkit.createInventory(null, 27, PET_TITLE); - fillEdges(gui); - gui.setItem(11, createItem(Material.BONE, "§fWolf", "§7Ein treuer Begleiter")); - gui.setItem(13, createItem(Material.CAT_SPAWN_EGG, "§6Katze", "§7Ein verschmuster Freund")); - gui.setItem(15, createItem(Material.PANDA_SPAWN_EGG,"§aPanda", "§7Ein gemütlicher Zeitgenosse")); - gui.setItem(22, createItem(Material.ARROW, "§7Zurück", "§8Zum Hauptmenü")); - player.openInventory(gui); - } - - private void openBalloonGUI(Player player) { - Inventory gui = Bukkit.createInventory(null, 36, BALLOON_TITLE); - fillEdges(gui); - Material[] wools = {Material.WHITE_WOOL, Material.ORANGE_WOOL, Material.MAGENTA_WOOL, - Material.LIGHT_BLUE_WOOL, Material.YELLOW_WOOL, Material.LIME_WOOL, Material.PINK_WOOL, - Material.GRAY_WOOL, Material.CYAN_WOOL, Material.PURPLE_WOOL, Material.BLUE_WOOL, - Material.BROWN_WOOL, Material.GREEN_WOOL, Material.RED_WOOL}; - int slot = 10; - for (Material m : wools) { - if (slot == 17) slot = 19; - gui.setItem(slot++, createItem(m, "§fBallon: " + m.name().replace("_WOOL",""), "§7Klicke zum Ausrüsten")); - } - gui.setItem(31, createItem(Material.ARROW, "§7Zurück", "§8Zum Hauptmenü")); - player.openInventory(gui); - } - - private void openParticleGUI(Player player) { - Inventory gui = Bukkit.createInventory(null, 27, PARTICLE_TITLE); - fillEdges(gui); - gui.setItem(11, createItem(Material.POPPY, "§cHerzchen-Aura", "§7Verbreite Liebe in der Lobby")); - gui.setItem(13, createItem(Material.BLAZE_POWDER, "§6Flammen-Ring", "§7Lass es brennen!")); - gui.setItem(15, createItem(Material.WATER_BUCKET, "§bRegenwolke", "§7Deine persönliche Abkühlung")); - gui.setItem(22, createItem(Material.ARROW, "§7Zurück", "§8Zum Hauptmenü")); - player.openInventory(gui); - } - - private void openFunGUI(Player player) { - Inventory gui = Bukkit.createInventory(null, 27, FUN_TITLE); - fillEdges(gui); - gui.setItem(10, createItem(Material.FISHING_ROD, "§b§lEnterhaken", "§7Zieh dich durch die Luft! §8(3s CD)")); - gui.setItem(11, createItem(Material.PACKED_ICE, "§b§lFreeze-Ray", "§7Friere andere ein! §8(10s CD)")); - gui.setItem(12, createItem(Material.GOLDEN_HOE, "§6§lPaintball-Gun","§7Male die Lobby bunt aus!")); - gui.setItem(14, createItem(Material.FIRE_CHARGE, "§c§lMeteorit", "§7Lass es krachen! §8(15s CD)")); - gui.setItem(15, createItem(Material.SHIELD, "§5§lSchutzzone", "§7Halte andere auf Distanz")); - gui.setItem(16, createItem(Material.EGG, "§f§lChicken-Rain","§7Gack-Gack! Hühner überall!")); - gui.setItem(22, createItem(Material.ARROW, "§7Zurück", "§8Zum Hauptmenü")); - player.openInventory(gui); - } - - @EventHandler - public void onInventoryClick(InventoryClickEvent event) { - String title = event.getView().getTitle(); - if (!title.startsWith("§b§lGadgets")) return; - event.setCancelled(true); - Player player = (Player) event.getWhoClicked(); - ItemStack item = event.getCurrentItem(); - if (item == null || item.getType() == Material.AIR) return; - - if (item.getType() == Material.ARROW) { openGUI(player); return; } - - if (title.equals(MAIN_TITLE)) { - if (item.getType() == Material.LEAD) openBalloonGUI(player); - else if (item.getType() == Material.GOLDEN_HELMET) openHatGUI(player); - else if (item.getType() == Material.BONE) openPetGUI(player); - else if (item.getType() == Material.NETHER_STAR) openParticleGUI(player); - else if (item.getType() == Material.FIREWORK_ROCKET) openFunGUI(player); - else if (item.getType() == Material.BARRIER) { removeGadgets(player); player.closeInventory(); } - } else if (title.equals(HAT_TITLE)) { - if (item.getType() != Material.GRAY_STAINED_GLASS_PANE) { - String hatName = item.hasItemMeta() && item.getItemMeta().hasDisplayName() - ? item.getItemMeta().getDisplayName() : item.getType().name(); - HatManager.setHat(player, item.getType(), hatName); - player.playSound(player.getLocation(), Sound.ITEM_ARMOR_EQUIP_GENERIC, 1, 1); - player.closeInventory(); + if (item.getType() == Material.NETHER_STAR && title.startsWith("§b§lGadgets §8- §d") + || item.getType() == Material.NETHER_STAR && title.equals("§b§lGadgets §8- §aHüte & Köpfe") + || item.getType() == Material.NETHER_STAR && title.equals("§b§lGadgets §8- §eBallons") + || item.getType() == Material.NETHER_STAR && title.equals("§b§lGadgets §8- §dPartikel") + || item.getType() == Material.NETHER_STAR && title.equals("§b§lGadgets §8- §6Lustiges")) { + this.openGUI(player); + return; } - } else if (title.equals(PET_TITLE)) { - if (item.getType() == Material.BONE) PetManager.spawnEntityPet(player, "WOLF"); - else if (item.getType() == Material.CAT_SPAWN_EGG) PetManager.spawnEntityPet(player, "CAT"); - else if (item.getType() == Material.PANDA_SPAWN_EGG) PetManager.spawnEntityPet(player, "PANDA"); - player.sendMessage("§8[§6Nexus§8] §dDein Pet wurde gerufen!"); - player.closeInventory(); - } else if (title.equals(BALLOON_TITLE)) { - if (item.getType().toString().endsWith("_WOOL")) { - if (activeBalloons.containsKey(player.getUniqueId())) activeBalloons.get(player.getUniqueId()).remove(); - activeBalloons.put(player.getUniqueId(), new Balloon(player, item.getType())); - player.sendMessage("§8[§6Nexus§8] §aBallon aktiviert!"); - player.closeInventory(); + + if (title.equals("§b§lGadgets §8- §7Menü")) { + if (item.getType() == Material.LEAD) { + this.openBalloonGUI(player); + } else if (item.getType() == Material.GOLDEN_HELMET) { + this.openHatGUI(player); + } else if (item.getType() == Material.BONE) { + this.openPetGUI(player); + } else if (item.getType() == Material.NETHER_STAR) { + this.openParticleGUI(player); + } else if (item.getType() == Material.FIREWORK_ROCKET) { + this.openFunGUI(player); + } else if (item.getType() == Material.BARRIER) { + this.removeGadgets(player); + player.closeInventory(); + } + } else if (title.equals("§b§lGadgets §8- §aHüte & Köpfe")) { + if (item.getType() != Material.GRAY_STAINED_GLASS_PANE) { + String hatName = item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : item.getType().name(); + HatManager.setHat(player, item.getType(), hatName); + player.playSound(player.getLocation(), Sound.ITEM_ARMOR_EQUIP_GENERIC, 1.0F, 1.0F); + player.closeInventory(); + } + } else if (title.equals("§b§lGadgets §8- §dBegleiter")) { + String displayName = item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : ""; + boolean spawned = true; + if (displayName.equals("§fBaby-Wolf")) { + PetManager.spawnEntityPet(player, "WOLF", true); + } else if (displayName.equals("§fWolf")) { + PetManager.spawnEntityPet(player, "WOLF", false); + } else if (displayName.equals("§7Baby-Ashen Wolf")) { + PetManager.spawnEntityPet(player, "WOLF", true, "ASHEN"); + } else if (displayName.equals("§7Ashen Wolf")) { + PetManager.spawnEntityPet(player, "WOLF", false, "ASHEN"); + } else if (displayName.equals("§6Baby-Katze")) { + PetManager.spawnEntityPet(player, "CAT", true); + } else if (displayName.equals("§6Katze")) { + PetManager.spawnEntityPet(player, "CAT", false); + } else if (displayName.equals("§aBaby-Panda")) { + PetManager.spawnEntityPet(player, "PANDA", true); + } else if (displayName.equals("§aPanda")) { + PetManager.spawnEntityPet(player, "PANDA", false); + } else if (displayName.equals("§6Baby-Fuchs")) { + PetManager.spawnEntityPet(player, "FOX", true); + } else if (displayName.equals("§6Fuchs")) { + PetManager.spawnEntityPet(player, "FOX", false); + } else if (displayName.equals("§bBaby-Schneefuchs")) { + PetManager.spawnEntityPet(player, "FOX", true, "SNOW"); + } else if (displayName.equals("§bSchneefuchs")) { + PetManager.spawnEntityPet(player, "FOX", false, "SNOW"); + } else if (displayName.equals("§6Baby-Ozelot")) { + PetManager.spawnEntityPet(player, "OCELOT", true); + } else if (displayName.equals("§6Ozelot")) { + PetManager.spawnEntityPet(player, "OCELOT", false); + } else if (displayName.equals("§aBaby-Frosch")) { + PetManager.spawnEntityPet(player, "FROG", true); + } else if (displayName.equals("§aFrosch")) { + PetManager.spawnEntityPet(player, "FROG", false); + } else if (displayName.equals("§2Baby-Schildkröte")) { + PetManager.spawnEntityPet(player, "TURTLE", true); + } else if (displayName.equals("§2Schildkröte")) { + PetManager.spawnEntityPet(player, "TURTLE", false); + } else if (displayName.equals("§fBaby-Kaninchen")) { + PetManager.spawnEntityPet(player, "RABBIT", true); + } else if (displayName.equals("§fKaninchen")) { + PetManager.spawnEntityPet(player, "RABBIT", false); + } else if (displayName.equals("§dBaby-Axolotl")) { + PetManager.spawnEntityPet(player, "AXOLOTL", true); + } else if (displayName.equals("§dAxolotl")) { + PetManager.spawnEntityPet(player, "AXOLOTL", false); + } else if (displayName.equals("§fBaby-Eisbär")) { + PetManager.spawnEntityPet(player, "POLAR_BEAR", true); + } else if (displayName.equals("§fEisbär")) { + PetManager.spawnEntityPet(player, "POLAR_BEAR", false); + } else if (displayName.equals("§eBaby-Biene")) { + PetManager.spawnEntityPet(player, "BEE", true); + } else if (displayName.equals("§eBiene")) { + PetManager.spawnEntityPet(player, "BEE", false); + } else if (displayName.equals("§fKüken")) { + PetManager.spawnEntityPet(player, "CHICKEN", true); + } else if (displayName.equals("§fHuhn")) { + PetManager.spawnEntityPet(player, "CHICKEN", false); + } else if (displayName.equals("§7Baby-Armadillo")) { + PetManager.spawnEntityPet(player, "ARMADILLO", true); + } else if (displayName.equals("§7Armadillo")) { + PetManager.spawnEntityPet(player, "ARMADILLO", false); + } else { + spawned = false; + } + + if (spawned) { + player.sendMessage("§8[§6Nexus§8] §dDein Pet wurde gerufen!"); + player.closeInventory(); + } + } else if (title.equals("§b§lGadgets §8- §dBegleiter §7(2)")) { + String displayName = item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : ""; + boolean spawned = true; + if (displayName.equals("§7Baby-Armadillo")) { + PetManager.spawnEntityPet(player, "ARMADILLO", true); + } else if (displayName.equals("§7Armadillo")) { + PetManager.spawnEntityPet(player, "ARMADILLO", false); + } else { + spawned = false; + } + + if (spawned) { + player.sendMessage("§8[§6Nexus§8] §dDein Pet wurde gerufen!"); + player.closeInventory(); + } + } else if (title.equals("§b§lGadgets §8- §dBegleiter §7(3)")) { + String displayName = item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : ""; + boolean spawned = true; + if (displayName.equals("§cPapagei")) { + PetManager.spawnEntityPet(player, "PARROT", false); + } else if (displayName.equals("§bAllay")) { + PetManager.spawnEntityPet(player, "ALLAY", false); + } else if (displayName.equals("§aSniffer")) { + PetManager.spawnEntityPet(player, "SNIFFER", false); + } else { + spawned = false; + } + + if (spawned) { + player.sendMessage("§8[§6Nexus§8] §dDein Pet wurde gerufen!"); + player.closeInventory(); + } + } else if (title.equals("§b§lGadgets §8- §eBallons")) { + if (item.getType().toString().endsWith("_WOOL")) { + if (this.activeBalloons.containsKey(player.getUniqueId())) { + ((Balloon)this.activeBalloons.get(player.getUniqueId())).remove(); + } + + this.activeBalloons.put(player.getUniqueId(), new Balloon(player, item.getType())); + player.sendMessage("§8[§6Nexus§8] §aBallon aktiviert!"); + player.closeInventory(); + } + } else if (title.equals("§b§lGadgets §8- §dPartikel")) { + if (item.getType() == Material.POPPY) { + this.activeEffects.put(player.getUniqueId(), new ParticleEffect("hearts")); + } else if (item.getType() == Material.BLAZE_POWDER) { + this.activeEffects.put(player.getUniqueId(), new ParticleEffect("flames")); + } else if (item.getType() == Material.WATER_BUCKET) { + this.activeEffects.put(player.getUniqueId(), new ParticleEffect("cloud")); + } + + player.sendMessage("§8[§6Nexus§8] §aPartikel aktiviert!"); + player.closeInventory(); + } else if (title.equals("§b§lGadgets §8- §6Lustiges")) { + if (item.getType() == Material.EGG) { + ChickenRain.start(player); + player.sendMessage("§8[§6Nexus§8] §fHühnerregen gestartet!"); + player.closeInventory(); + } else if (item.getType() == Material.FISHING_ROD) { + player.getInventory().addItem(new ItemStack[]{this.createItem(Material.FISHING_ROD, "§b§lEnterhaken", "§7Rechtsklick zum Katapultieren §8(3s CD)")}); + player.closeInventory(); + } else if (item.getType() == Material.PACKED_ICE) { + player.getInventory().addItem(new ItemStack[]{this.createItem(Material.PACKED_ICE, "§b§lFreeze-Ray", "§7Rechtsklick zum Einfrieren §8(10s CD)")}); + player.closeInventory(); + } else if (item.getType() == Material.GOLDEN_HOE) { + player.getInventory().addItem(new ItemStack[]{this.createItem(Material.GOLDEN_HOE, "§6§lPaintball-Gun", "§7Rechtsklick zum Schießen")}); + player.closeInventory(); + } else if (item.getType() == Material.FIRE_CHARGE) { + player.getInventory().addItem(new ItemStack[]{this.createItem(Material.FIRE_CHARGE, "§c§lMeteorit", "§7Rechtsklick zum Markieren §8(15s CD)")}); + player.closeInventory(); + } else if (item.getType() == Material.SHIELD) { + if (this.activeShields.contains(player.getUniqueId())) { + this.activeShields.remove(player.getUniqueId()); + player.sendMessage("§8[§6Nexus§8] §cSchutzzone deaktiviert."); + } else { + this.activeShields.add(player.getUniqueId()); + player.sendMessage("§8[§6Nexus§8] §5Schutzzone aktiviert!"); + } + + player.closeInventory(); + } else if (item.getType() == Material.FEATHER) { + Bukkit.getScheduler().runTaskTimer(NexusLobby.getInstance(), new Runnable() { + int ticks = 0; + + public void run() { + if (this.ticks < 20) { + float yaw = player.getLocation().getYaw() + 36.0F; + Location loc = player.getLocation().clone(); + loc.setYaw(yaw); + loc.setY(loc.getY() + (double)0.5F); + player.teleport(loc); + player.getWorld().spawnParticle(Particle.CLOUD, loc.clone().add((double)0.0F, (double)1.5F, (double)0.0F), 14, 0.4, 0.2, 0.4, 0.02); + player.setVelocity(player.getVelocity().setY(0.13)); + ++this.ticks; + } + } + }, 0L, 1L); + player.playSound(player.getLocation(), Sound.ENTITY_PHANTOM_FLAP, 1.0F, 1.2F); + player.sendMessage("§8[§6Nexus§8] §fMini-Tornado: Du wirbelst herum!"); + player.closeInventory(); + } else if (item.getType() == Material.TNT) { + Location tntLoc = player.getLocation().add((double)0.0F, (double)0.5F, (double)0.0F); + player.getWorld().spawnParticle(Particle.SMOKE, tntLoc, 16, 0.4, 0.2, 0.4, 0.01); + player.getWorld().playSound(tntLoc, Sound.ENTITY_TNT_PRIMED, 1.0F, 1.0F); + Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), () -> { + player.getWorld().spawnParticle(Particle.EXPLOSION, tntLoc, 2, (double)0.5F, 0.2, (double)0.5F, 0.1); + player.getWorld().playSound(tntLoc, Sound.ENTITY_GENERIC_EXPLODE, 1.0F, 1.1F); + }, 30L); + player.sendMessage("§8[§6Nexus§8] §cFake-TNT gezündet! Keine Sorge, alles harmlos."); + player.closeInventory(); + } else if (item.getType() == Material.SLIME_BALL) { + World world = player.getWorld(); + Location baseLoc = player.getLocation(); + EntityType[] types = new EntityType[]{EntityType.ZOMBIE, EntityType.SKELETON, EntityType.CREEPER, EntityType.SLIME}; + final List spawned = new ArrayList(); + + for(int i = 0; i < types.length; ++i) { + Location mobLoc = baseLoc.clone().add(Math.cos((double)i * Math.PI / (double)2.0F) * (double)1.5F, (double)0.0F, Math.sin((double)i * Math.PI / (double)2.0F) * (double)1.5F); + Entity ent = world.spawnEntity(mobLoc, types[i]); + if (ent instanceof LivingEntity) { + LivingEntity mob = (LivingEntity)ent; + mob.setCustomName("§aParty-Mob"); + mob.setCustomNameVisible(true); + mob.setAI(false); + mob.setInvulnerable(true); + mob.setCollidable(false); + mob.setSilent(true); + mob.setGlowing(true); + + try { + if (mob instanceof Zombie) { + Zombie zombie = (Zombie)mob; + zombie.setBaby(true); + } else if (mob instanceof Slime) { + Slime slime = (Slime)mob; + slime.setSize(1); + } + } catch (Exception var15) { + } + + spawned.add(mob); + } + } + + Bukkit.getScheduler().runTaskTimer(NexusLobby.getInstance(), new Runnable() { + int ticks = 0; + + public void run() { + if (this.ticks >= 80) { + spawned.forEach((e) -> e.remove()); + } else { + for(LivingEntity mob : spawned) { + mob.getWorld().spawnParticle(Particle.NOTE, mob.getLocation().add((double)0.0F, (double)1.0F, (double)0.0F), 6, 0.3, 0.2, 0.3, 0.01); + mob.teleport(mob.getLocation().add((double)0.0F, 0.08 * Math.sin((double)this.ticks / (double)2.0F), (double)0.0F)); + } + + ++this.ticks; + } + } + }, 0L, 2L); + player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_CELEBRATE, 1.0F, 1.2F); + player.sendMessage("§8[§6Nexus§8] §aMob-Party gestartet! Die Mobs tanzen um dich."); + player.closeInventory(); + } else if (item.getType() == Material.FIREWORK_ROCKET) { + for(int i = 0; i < 3; ++i) { + Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), () -> { + player.getWorld().spawnParticle(Particle.CRIT, player.getLocation().add((double)0.0F, (double)1.0F, (double)0.0F), 40, 0.8, (double)0.5F, 0.8, 0.15); + player.getWorld().spawnParticle(Particle.NOTE, player.getLocation().add((double)0.0F, (double)1.0F, (double)0.0F), 20, 0.7, 0.3, 0.7, 0.1); + player.playSound(player.getLocation(), Sound.ENTITY_FIREWORK_ROCKET_BLAST, 1.0F, 1.1F); + }, (long)i * 6L); + } + + player.sendMessage("§8[§6Nexus§8] §cKonfetti-Kanone: Buntes Konfetti überall!"); + player.closeInventory(); + } else if (item.getType() == Material.NOTE_BLOCK) { + Bukkit.getScheduler().runTaskTimer(NexusLobby.getInstance(), new Runnable() { + int ticks = 0; + + public void run() { + if (this.ticks < 40) { + if (this.ticks % 8 == 0) { + player.setVelocity(player.getVelocity().setY(0.4)); + player.getWorld().spawnParticle(Particle.NOTE, player.getLocation().add((double)0.0F, (double)2.0F, (double)0.0F), 8, (double)0.5F, 0.2, (double)0.5F, 0.01); + player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BELL, 1.0F, 1.2F); + } + + ++this.ticks; + } + } + }, 0L, 2L); + player.sendMessage("§8[§6Nexus§8] §dTanz-Emote: Du beginnst zu tanzen!"); + player.closeInventory(); + } } - } else if (title.equals(PARTICLE_TITLE)) { - if (item.getType() == Material.POPPY) activeEffects.put(player.getUniqueId(), new ParticleEffect("hearts")); - else if (item.getType() == Material.BLAZE_POWDER) activeEffects.put(player.getUniqueId(), new ParticleEffect("flames")); - else if (item.getType() == Material.WATER_BUCKET) activeEffects.put(player.getUniqueId(), new ParticleEffect("cloud")); - player.sendMessage("§8[§6Nexus§8] §aPartikel aktiviert!"); - player.closeInventory(); - } else if (title.equals(FUN_TITLE)) { - if (item.getType() == Material.EGG) { - ChickenRain.start(player); - player.sendMessage("§8[§6Nexus§8] §fHühnerregen gestartet!"); - player.closeInventory(); - } else if (item.getType() == Material.FISHING_ROD) { - player.getInventory().addItem(createItem(Material.FISHING_ROD, "§b§lEnterhaken", "§7Rechtsklick zum Katapultieren §8(3s CD)")); - player.closeInventory(); - } else if (item.getType() == Material.PACKED_ICE) { - player.getInventory().addItem(createItem(Material.PACKED_ICE, "§b§lFreeze-Ray", "§7Rechtsklick zum Einfrieren §8(10s CD)")); - player.closeInventory(); - } else if (item.getType() == Material.GOLDEN_HOE) { - player.getInventory().addItem(createItem(Material.GOLDEN_HOE, "§6§lPaintball-Gun", "§7Rechtsklick zum Schießen")); - player.closeInventory(); - } else if (item.getType() == Material.FIRE_CHARGE) { - player.getInventory().addItem(createItem(Material.FIRE_CHARGE, "§c§lMeteorit", "§7Rechtsklick zum Markieren §8(15s CD)")); - player.closeInventory(); - } else if (item.getType() == Material.SHIELD) { - if (activeShields.contains(player.getUniqueId())) { - activeShields.remove(player.getUniqueId()); - player.sendMessage("§8[§6Nexus§8] §cSchutzzone deaktiviert."); - } else { - activeShields.add(player.getUniqueId()); - player.sendMessage("§8[§6Nexus§8] §5Schutzzone aktiviert!"); - } - player.closeInventory(); - } - } - } - private void removeGadgets(Player player) { - if (activeBalloons.containsKey(player.getUniqueId())) { - activeBalloons.get(player.getUniqueId()).remove(); - activeBalloons.remove(player.getUniqueId()); - } - activeEffects.remove(player.getUniqueId()); - activeShields.remove(player.getUniqueId()); - PetManager.removePet(player); - FreezeRay.unfreeze(player.getUniqueId()); - HatManager.removeHat(player); - player.getInventory().remove(Material.FISHING_ROD); - player.getInventory().remove(Material.PACKED_ICE); - player.getInventory().remove(Material.GOLDEN_HOE); - player.getInventory().remove(Material.FIRE_CHARGE); - player.sendMessage("§8[§6Nexus§8] §cAlle Gadgets abgelegt."); - } + } + } + } - private void fillEdges(Inventory inv) { - ItemStack glass = createItem(Material.GRAY_STAINED_GLASS_PANE, " ", null); - for (int i = 0; i < inv.getSize(); i++) { - if (i < 9 || i >= inv.getSize() - 9 || i % 9 == 0 || (i + 1) % 9 == 0) inv.setItem(i, glass); - } - } + private void removeGadgets(Player player) { + UUID uuid = player.getUniqueId(); + Integer discoTask = (Integer)this.discoTasks.remove(uuid); + if (discoTask != null) { + Bukkit.getScheduler().cancelTask(discoTask); + } - private ItemStack createItem(Material mat, String name, String lore) { - ItemStack item = new ItemStack(mat); - ItemMeta meta = item.getItemMeta(); - if (meta != null) { - meta.setDisplayName(name); - List l = new ArrayList<>(); - if (lore != null && !lore.isEmpty()) { - l.add(ChatColor.translateAlternateColorCodes('&', lore)); - meta.setLore(l); - } - meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); - meta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE); - meta.addItemFlags(ItemFlag.HIDE_ENCHANTS); - item.setItemMeta(meta); - } - return item; - } + if (this.activeBalloons.containsKey(player.getUniqueId())) { + ((Balloon)this.activeBalloons.get(player.getUniqueId())).remove(); + this.activeBalloons.remove(player.getUniqueId()); + } - @Override - public void onDisable() { - org.bukkit.event.HandlerList.unregisterAll(this); - PetManager.unregister(); - PetManager.clearAll(); - activeBalloons.values().forEach(Balloon::remove); - activeBalloons.clear(); - activeEffects.clear(); - activeShields.clear(); - GadgetShield.clear(); - } + this.activeEffects.remove(player.getUniqueId()); + this.activeShields.remove(player.getUniqueId()); + PetManager.removePet(player); + FreezeRay.unfreeze(player.getUniqueId()); + HatManager.removeHat(player); + player.getInventory().remove(Material.FISHING_ROD); + player.getInventory().remove(Material.PACKED_ICE); + player.getInventory().remove(Material.GOLDEN_HOE); + player.getInventory().remove(Material.FIRE_CHARGE); + player.sendMessage("§8[§6Nexus§8] §cAlle Gadgets abgelegt."); + } + + private void fillEdges(Inventory inv) { + ItemStack glass = this.createItem(Material.GRAY_STAINED_GLASS_PANE, " ", (String)null); + + for(int i = 0; i < inv.getSize(); ++i) { + if (i < 9 || i >= inv.getSize() - 9 || i % 9 == 0 || (i + 1) % 9 == 0) { + inv.setItem(i, glass); + } + } + + } + + private ItemStack createItem(Material mat, String name, String lore) { + ItemStack item = new ItemStack(mat); + ItemMeta meta = item.getItemMeta(); + if (meta != null) { + meta.setDisplayName(name); + List l = new ArrayList(); + if (lore != null && !lore.isEmpty()) { + l.add(ChatColor.translateAlternateColorCodes('&', lore)); + meta.setLore(l); + } + + meta.addItemFlags(new ItemFlag[]{ItemFlag.HIDE_ATTRIBUTES}); + meta.addItemFlags(new ItemFlag[]{ItemFlag.HIDE_UNBREAKABLE}); + meta.addItemFlags(new ItemFlag[]{ItemFlag.HIDE_ENCHANTS}); + item.setItemMeta(meta); + } + + return item; + } + + public void onDisable() { + HandlerList.unregisterAll(this); + PetManager.unregister(); + PetManager.clearAll(); + this.activeBalloons.values().forEach(Balloon::remove); + this.activeBalloons.clear(); + this.activeEffects.clear(); + this.activeShields.clear(); + GadgetShield.clear(); + } } \ No newline at end of file diff --git a/src/main/java/de/nexuslobby/modules/gadgets/GadgetShield.java b/src/main/java/de/nexuslobby/modules/gadgets/GadgetShield.java index 72318e5..99a4dd2 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/GadgetShield.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/GadgetShield.java @@ -2,58 +2,44 @@ package de.nexuslobby.modules.gadgets; import de.nexuslobby.NexusLobby; import de.nexuslobby.modules.parkour.ParkourManager; -import org.bukkit.Sound; -import org.bukkit.entity.Player; - import java.util.HashSet; import java.util.Set; import java.util.UUID; +import org.bukkit.Sound; +import org.bukkit.entity.Player; -/** - * Verwaltet den Gadget-Schutz für Admins und Parkour-Spieler. - * Eigenständige Klasse – kein Eingriff in GadgetModule nötig. - */ public class GadgetShield { + private static final Set shielded = new HashSet(); - /** UUIDs der Admins, die ihren Gadget-Schutz aktiviert haben */ - private static final Set shielded = new HashSet<>(); + public static boolean toggle(Player player) { + UUID uuid = player.getUniqueId(); + if (shielded.contains(uuid)) { + shielded.remove(uuid); + player.sendMessage("§8[§6Nexus§8] §cGadget-Schutz §7deaktiviert."); + player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1.0F, 1.0F); + return false; + } else { + shielded.add(uuid); + player.sendMessage("§8[§6Nexus§8] §aGadget-Schutz §7aktiviert. §8Du bist nun immun gegen Gadgets."); + player.playSound(player.getLocation(), Sound.BLOCK_AMETHYST_BLOCK_CHIME, 1.0F, 1.5F); + return true; + } + } - /** - * Schaltet den Gadget-Schutz ein oder aus. - * Gibt true zurück wenn der Schutz jetzt aktiv ist. - */ - public static boolean toggle(Player player) { - UUID uuid = player.getUniqueId(); - if (shielded.contains(uuid)) { - shielded.remove(uuid); - player.sendMessage("§8[§6Nexus§8] §cGadget-Schutz §7deaktiviert."); - player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_BASS, 1f, 1f); - return false; - } else { - shielded.add(uuid); - player.sendMessage("§8[§6Nexus§8] §aGadget-Schutz §7aktiviert. §8Du bist nun immun gegen Gadgets."); - player.playSound(player.getLocation(), Sound.BLOCK_AMETHYST_BLOCK_CHIME, 1f, 1.5f); - return true; - } - } + public static boolean isAdminShielded(Player player) { + return shielded.contains(player.getUniqueId()); + } - /** Gibt zurück ob ein Spieler explizit durch den Admin-Schutz geschützt ist. */ - public static boolean isAdminShielded(Player player) { - return shielded.contains(player.getUniqueId()); - } + public static boolean isProtected(Player player) { + if (shielded.contains(player.getUniqueId())) { + return true; + } else { + ParkourManager pm = NexusLobby.getInstance().getParkourManager(); + return pm != null && pm.isIngame(player); + } + } - /** - * Gibt zurück ob ein Spieler durch irgendeinen Schutz immun gegen Gadgets ist - * (Admin-Schutz ODER aktiver Parkour-Run). - */ - public static boolean isProtected(Player player) { - if (shielded.contains(player.getUniqueId())) return true; - ParkourManager pm = NexusLobby.getInstance().getParkourManager(); - return pm != null && pm.isIngame(player); - } - - /** Beim Server-Stop / Plugin-Disable aufrufen */ - public static void clear() { - shielded.clear(); - } -} \ No newline at end of file + public static void clear() { + shielded.clear(); + } +} diff --git a/src/main/java/de/nexuslobby/modules/gadgets/GrapplingHook.java b/src/main/java/de/nexuslobby/modules/gadgets/GrapplingHook.java index 19e5ac3..cd74972 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/GrapplingHook.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/GrapplingHook.java @@ -6,32 +6,20 @@ import org.bukkit.entity.Player; import org.bukkit.util.Vector; public class GrapplingHook { + public static void pullPlayer(Player player, Location target) { + Location playerLoc = player.getLocation(); + double distance = target.distance(playerLoc); + if (!(distance < (double)2.0F) && !(distance > (double)50.0F)) { + Vector v = target.toVector().subtract(playerLoc.toVector()); + v.multiply(0.3); + v.setY(v.getY() * 0.6 + (double)0.5F); + if (v.length() > (double)2.5F) { + v.normalize().multiply((double)2.5F); + } - public static void pullPlayer(Player player, Location target) { - Location playerLoc = player.getLocation(); - - // Vektor vom Spieler zum Ziel berechnen - double distance = target.distance(playerLoc); - - // Wenn das Ziel zu nah oder zu weit weg ist, nichts tun - if (distance < 2 || distance > 50) return; - - // Berechnung des Wurfs (Vektor) - Vector v = target.toVector().subtract(playerLoc.toVector()); - - // Den Vektor normalisieren und skalieren (Stärke des Zugs) - v.multiply(0.3); // Basis-Geschwindigkeit - v.setY(v.getY() * 0.6 + 0.5); // Etwas mehr Höhe für den Bogen-Effekt - - // Geschwindigkeit begrenzen, damit man nicht aus der Map schießt - if (v.length() > 2.5) { - v.normalize().multiply(2.5); - } - - player.setVelocity(v); - - // Sound-Effekt für das "Ziehen" - player.playSound(playerLoc, Sound.ENTITY_WIND_CHARGE_WIND_BURST, 1.0f, 1.2f); - player.playSound(playerLoc, Sound.ITEM_TRIDENT_RIPTIDE_1, 0.5f, 1.5f); - } -} \ No newline at end of file + player.setVelocity(v); + player.playSound(playerLoc, Sound.ENTITY_WIND_CHARGE_WIND_BURST, 1.0F, 1.2F); + player.playSound(playerLoc, Sound.ITEM_TRIDENT_RIPTIDE_1, 0.5F, 1.5F); + } + } +} diff --git a/src/main/java/de/nexuslobby/modules/gadgets/HatManager.java b/src/main/java/de/nexuslobby/modules/gadgets/HatManager.java index fdebdcf..e56fb00 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/HatManager.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/HatManager.java @@ -6,21 +6,19 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; public class HatManager { + public static void setHat(Player player, Material material, String name) { + ItemStack hat = new ItemStack(material); + ItemMeta meta = hat.getItemMeta(); + if (meta != null) { + meta.setDisplayName("§6Hut: " + name); + hat.setItemMeta(meta); + } - public static void setHat(Player player, Material material, String name) { - ItemStack hat = new ItemStack(material); - ItemMeta meta = hat.getItemMeta(); - if (meta != null) { - meta.setDisplayName("§6Hut: " + name); - hat.setItemMeta(meta); - } - - // Den Gegenstand auf den Kopf setzen - player.getInventory().setHelmet(hat); - player.sendMessage("§8[§6Nexus§8] §aDu trägst nun: " + name); - } + player.getInventory().setHelmet(hat); + player.sendMessage("§8[§6Nexus§8] §aDu trägst nun: " + name); + } - public static void removeHat(Player player) { - player.getInventory().setHelmet(null); - } -} \ No newline at end of file + public static void removeHat(Player player) { + player.getInventory().setHelmet((ItemStack)null); + } +} diff --git a/src/main/java/de/nexuslobby/modules/gadgets/MeteorStrike.java b/src/main/java/de/nexuslobby/modules/gadgets/MeteorStrike.java index 3ea3e9c..753617e 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/MeteorStrike.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/MeteorStrike.java @@ -1,6 +1,7 @@ package de.nexuslobby.modules.gadgets; import de.nexuslobby.NexusLobby; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Particle; import org.bukkit.Sound; @@ -9,51 +10,45 @@ import org.bukkit.entity.Player; import org.bukkit.util.Vector; public class MeteorStrike { + public static void launch(Player shooter) { + Location target = null; + Location start = shooter.getEyeLocation(); + Vector direction = start.getDirection(); - public static void launch(Player shooter) { - Location target = null; - Location start = shooter.getEyeLocation(); - Vector direction = start.getDirection(); + for(double d = (double)0.0F; d < (double)30.0F; d += (double)0.5F) { + Location point = start.clone().add(direction.clone().multiply(d)); + if (point.getBlock().getType().isSolid()) { + target = point; + break; + } + } - for (double d = 0; d < 30; d += 0.5) { - Location point = start.clone().add(direction.clone().multiply(d)); - if (point.getBlock().getType().isSolid()) { - target = point; - break; - } - } - - if (target == null) return; - final Location finalTarget = target.clone().add(0, 0.5, 0); - - finalTarget.getWorld().spawnParticle(Particle.FLAME, finalTarget, 20, 0.5, 0.1, 0.5, 0.05); - shooter.sendMessage("§8[§6Nexus§8] §cMeteorit im Anflug..."); - - org.bukkit.Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), () -> { + if (target != null) { + Location finalTarget = target.clone().add((double)0.0F, (double)0.5F, (double)0.0F); + finalTarget.getWorld().spawnParticle(Particle.FLAME, finalTarget, 20, (double)0.5F, 0.1, (double)0.5F, 0.05); + shooter.sendMessage("§8[§6Nexus§8] §cMeteorit im Anflug..."); + Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), () -> { finalTarget.getWorld().spawnParticle(Particle.EXPLOSION_EMITTER, finalTarget, 1); - finalTarget.getWorld().spawnParticle(Particle.LAVA, finalTarget, 30, 0.5, 0.5, 0.5, 0.1); - finalTarget.getWorld().playSound(finalTarget, Sound.ENTITY_GENERIC_EXPLODE, 1.0f, 0.8f); + finalTarget.getWorld().spawnParticle(Particle.LAVA, finalTarget, 30, (double)0.5F, (double)0.5F, (double)0.5F, 0.1); + finalTarget.getWorld().playSound(finalTarget, Sound.ENTITY_GENERIC_EXPLODE, 1.0F, 0.8F); - for (Entity entity : finalTarget.getWorld().getNearbyEntities(finalTarget, 4, 4, 4)) { - if (entity instanceof Player p) { - // Schutz: Admins mit Gadget-Schutz und Parkour-Spieler werden nicht weggeschleudert - if (GadgetShield.isProtected(p)) { - if (GadgetShield.isAdminShielded(p)) { - p.sendMessage("§8[§6Nexus§8] §7Dein Gadget-Schutzschild hat den Meteoriten abgelenkt!"); - } else { - p.sendMessage("§8[§6Parkour§8] §7Dein Parkour-Schutzschild hat den Meteoriten abgelenkt!"); - } - continue; - } - Vector v = p.getLocation().toVector() - .subtract(finalTarget.toVector()) - .normalize() - .multiply(1.5) - .setY(0.5); - p.setVelocity(v); - p.sendMessage("§cBUMM!"); - } + for(Entity entity : finalTarget.getWorld().getNearbyEntities(finalTarget, (double)4.0F, (double)4.0F, (double)4.0F)) { + if (entity instanceof Player p) { + if (GadgetShield.isProtected(p)) { + if (GadgetShield.isAdminShielded(p)) { + p.sendMessage("§8[§6Nexus§8] §7Dein Gadget-Schutzschild hat den Meteoriten abgelenkt!"); + } else { + p.sendMessage("§8[§6Parkour§8] §7Dein Parkour-Schutzschild hat den Meteoriten abgelenkt!"); + } + } else { + Vector v = p.getLocation().toVector().subtract(finalTarget.toVector()).normalize().multiply((double)1.5F).setY((double)0.5F); + p.setVelocity(v); + p.sendMessage("§cBUMM!"); + } + } } - }, 30L); - } -} \ No newline at end of file + + }, 30L); + } + } +} diff --git a/src/main/java/de/nexuslobby/modules/gadgets/PaintballGun.java b/src/main/java/de/nexuslobby/modules/gadgets/PaintballGun.java index 3355c02..b5cc059 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/PaintballGun.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/PaintballGun.java @@ -1,6 +1,7 @@ package de.nexuslobby.modules.gadgets; import de.nexuslobby.NexusLobby; +import java.util.Random; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -10,80 +11,65 @@ import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import java.util.Random; - public class PaintballGun { - private static final Random random = new Random(); - - // Wir nutzen jetzt Wolle für kräftigere Farben - private static final Material[] COLORS = { - Material.RED_WOOL, Material.BLUE_WOOL, Material.LIME_WOOL, - Material.ORANGE_WOOL, Material.MAGENTA_WOOL, Material.LIGHT_BLUE_WOOL, - Material.YELLOW_WOOL, Material.PURPLE_WOOL, Material.PINK_WOOL - }; + private static final Random random = new Random(); + private static final Material[] COLORS; - public static void shoot(Player shooter) { - Location start = shooter.getEyeLocation(); - Vector direction = start.getDirection(); - Material randomColor = COLORS[random.nextInt(COLORS.length)]; + public static void shoot(Player shooter) { + Location start = shooter.getEyeLocation(); + Vector direction = start.getDirection(); + Material randomColor = COLORS[random.nextInt(COLORS.length)]; + shooter.getWorld().playSound(start, Sound.ENTITY_CHICKEN_EGG, 1.0F, 2.0F); - shooter.getWorld().playSound(start, Sound.ENTITY_CHICKEN_EGG, 1.0f, 2.0f); + for(double d = (double)0.0F; d < (double)25.0F; d += (double)0.5F) { + Location point = start.clone().add(direction.clone().multiply(d)); + point.getWorld().spawnParticle(Particle.ITEM_SNOWBALL, point, 1, (double)0.0F, (double)0.0F, (double)0.0F, (double)0.0F); + Block block = point.getBlock(); + if (block.getType().isSolid()) { + impact(block, randomColor); + break; + } + } - for (double d = 0; d < 25; d += 0.5) { - Location point = start.clone().add(direction.clone().multiply(d)); - - // Flug-Partikel (kleiner Rauch oder Schneeball) - point.getWorld().spawnParticle(Particle.ITEM_SNOWBALL, point, 1, 0, 0, 0, 0); + } - Block block = point.getBlock(); - if (block.getType().isSolid()) { - impact(block, randomColor); - break; + private static void impact(Block centerBlock, Material color) { + Location centerLoc = centerBlock.getLocation(); + centerLoc.getWorld().playSound(centerLoc, Sound.ENTITY_SLIME_SQUISH, 1.0F, 1.2F); + int radius = 2; + + for(int x = -radius; x <= radius; ++x) { + for(int y = -radius; y <= radius; ++y) { + for(int z = -radius; z <= radius; ++z) { + if ((double)(x * x + y * y + z * z) <= (double)(radius * radius) + (double)0.5F) { + Block target = centerLoc.clone().add((double)x, (double)y, (double)z).getBlock(); + if (target.getType().isSolid()) { + applyColor(target, color); + } + } } - } - } + } + } - private static void impact(Block centerBlock, Material color) { - Location centerLoc = centerBlock.getLocation(); - centerLoc.getWorld().playSound(centerLoc, Sound.ENTITY_SLIME_SQUISH, 1.0f, 1.2f); - - int radius = 2; // Radius der Farbkugel + } - // Wir gehen alle Blöcke im Würfel um den Einschlag durch - for (int x = -radius; x <= radius; x++) { - for (int y = -radius; y <= radius; y++) { - for (int z = -radius; z <= radius; z++) { - - // Berechne Distanz für eine Kugelform (statt Würfel) - if (x * x + y * y + z * z <= radius * radius + 0.5) { - Block target = centerLoc.clone().add(x, y, z).getBlock(); - - // Nur solide Blöcke färben (keine Luft/Gras) - if (target.getType().isSolid()) { - applyColor(target, color); - } - } - } - } - } - } + private static void applyColor(Block block, Material color) { + Location loc = block.getLocation(); + loc.getWorld().spawnParticle(Particle.BLOCK, loc.clone().add((double)0.5F, (double)0.5F, (double)0.5F), 3, 0.1, 0.1, 0.1, color.createBlockData()); - private static void applyColor(Block block, Material color) { - Location loc = block.getLocation(); - - // Effekt-Partikel am Block - loc.getWorld().spawnParticle(Particle.BLOCK, loc.clone().add(0.5, 0.5, 0.5), 3, 0.1, 0.1, 0.1, color.createBlockData()); + for(Player online : Bukkit.getOnlinePlayers()) { + online.sendBlockChange(loc, color.createBlockData()); + } - // Block-Änderung an alle senden - for (Player online : Bukkit.getOnlinePlayers()) { - online.sendBlockChange(loc, color.createBlockData()); - } + Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), () -> { + for(Player online : Bukkit.getOnlinePlayers()) { + online.sendBlockChange(loc, block.getBlockData()); + } - // Nach 10 Sekunden zurücksetzen - Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), () -> { - for (Player online : Bukkit.getOnlinePlayers()) { - online.sendBlockChange(loc, block.getBlockData()); - } - }, 400L); - } -} \ No newline at end of file + }, 400L); + } + + static { + COLORS = new Material[]{Material.RED_WOOL, Material.BLUE_WOOL, Material.LIME_WOOL, Material.ORANGE_WOOL, Material.MAGENTA_WOOL, Material.LIGHT_BLUE_WOOL, Material.YELLOW_WOOL, Material.PURPLE_WOOL, Material.PINK_WOOL}; + } +} diff --git a/src/main/java/de/nexuslobby/modules/gadgets/ParticleEffect.java b/src/main/java/de/nexuslobby/modules/gadgets/ParticleEffect.java index 8212fb1..d15665d 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/ParticleEffect.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/ParticleEffect.java @@ -5,27 +5,29 @@ import org.bukkit.Particle; import org.bukkit.entity.Player; public class ParticleEffect { - private final String type; - private double angle = 0; + private final String type; + private double angle = (double)0.0F; - public ParticleEffect(String type) { this.type = type; } + public ParticleEffect(String type) { + this.type = type; + } - public void update(Player player) { - Location loc = player.getLocation(); - switch (type.toLowerCase()) { - case "hearts": - player.getWorld().spawnParticle(Particle.HEART, loc.clone().add(0, 2.2, 0), 1, 0.3, 0.3, 0.3, 0); - break; - case "flames": - double x = 0.6 * Math.cos(angle); - double z = 0.6 * Math.sin(angle); - player.getWorld().spawnParticle(Particle.FLAME, loc.clone().add(x, 0.1, z), 1, 0, 0, 0, 0); - angle += 0.2; - break; - case "cloud": - player.getWorld().spawnParticle(Particle.CLOUD, loc.clone().add(0, 2.5, 0), 2, 0.2, 0.05, 0.2, 0); - player.getWorld().spawnParticle(Particle.FALLING_WATER, loc.clone().add(0, 2.4, 0), 1, 0.1, 0, 0.1, 0); - break; - } - } -} \ No newline at end of file + public void update(Player player) { + Location loc = player.getLocation(); + switch (this.type.toLowerCase()) { + case "hearts": + player.getWorld().spawnParticle(Particle.HEART, loc.clone().add((double)0.0F, 2.2, (double)0.0F), 1, 0.3, 0.3, 0.3, (double)0.0F); + break; + case "flames": + double x = 0.6 * Math.cos(this.angle); + double z = 0.6 * Math.sin(this.angle); + player.getWorld().spawnParticle(Particle.FLAME, loc.clone().add(x, 0.1, z), 1, (double)0.0F, (double)0.0F, (double)0.0F, (double)0.0F); + this.angle += 0.2; + break; + case "cloud": + player.getWorld().spawnParticle(Particle.CLOUD, loc.clone().add((double)0.0F, (double)2.5F, (double)0.0F), 2, 0.2, 0.05, 0.2, (double)0.0F); + player.getWorld().spawnParticle(Particle.FALLING_WATER, loc.clone().add((double)0.0F, 2.4, (double)0.0F), 1, 0.1, (double)0.0F, 0.1, (double)0.0F); + } + + } +} diff --git a/src/main/java/de/nexuslobby/modules/gadgets/PetManager.java b/src/main/java/de/nexuslobby/modules/gadgets/PetManager.java index f440105..91cdee1 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/PetManager.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/PetManager.java @@ -1,158 +1,234 @@ package de.nexuslobby.modules.gadgets; import de.nexuslobby.NexusLobby; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; +import org.bukkit.entity.Ageable; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Fox; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; +import org.bukkit.entity.Wolf; +import org.bukkit.entity.Fox.Type; import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityTargetEvent; import org.bukkit.event.player.PlayerQuitEvent; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; public class PetManager implements Listener { + private static final Map activePets = new HashMap(); + private static PetManager instance; - private static final Map activePets = new HashMap<>(); + public PetManager() { + Bukkit.getPluginManager().registerEvents(this, NexusLobby.getInstance()); + } - // Singleton-Instanz, damit registerEvents() nur einmal aufgerufen wird - private static PetManager instance; + public static void register() { + if (instance == null) { + instance = new PetManager(); + } - public PetManager() { - Bukkit.getPluginManager().registerEvents(this, NexusLobby.getInstance()); - } + } - /** - * Registriert den PetManager als Listener, falls noch nicht geschehen. - * Muss einmalig beim Plugin-Start aufgerufen werden (z.B. aus GadgetModule.onEnable). - */ - public static void register() { - if (instance == null) { - instance = new PetManager(); - } - } + public static void unregister() { + if (instance != null) { + HandlerList.unregisterAll(instance); + instance = null; + } - public static void unregister() { - if (instance != null) { - org.bukkit.event.HandlerList.unregisterAll(instance); - instance = null; - } - } + } - /** - * Spawnt ein echtes Tier-Entity für den Spieler. - */ - public static void spawnEntityPet(Player player, String type) { - removePet(player); + public static void spawnEntityPet(Player player, String type) { + spawnEntityPet(player, type, false); + } - EntityType entityType; - try { - entityType = EntityType.valueOf(type); - } catch (IllegalArgumentException e) { - player.sendMessage("§cFehler: Tier-Typ nicht gefunden."); - return; - } + public static void spawnEntityPet(Player player, String type, boolean baby) { + spawnEntityPet(player, type, baby, (String)null); + } - Location loc = player.getLocation(); - Entity pet = player.getWorld().spawnEntity(loc, entityType); + public static void spawnEntityPet(Player player, String type, boolean baby, String variantName) { + removePet(player); - pet.setCustomName("§d" + player.getName() + "'s " + capitalize(type.toLowerCase())); - pet.setCustomNameVisible(true); - pet.setInvulnerable(true); - pet.setPersistent(false); + EntityType entityType; + try { + entityType = EntityType.valueOf(type); + } catch (IllegalArgumentException var12) { + player.sendMessage("§cFehler: Tier-Typ nicht gefunden."); + return; + } - if (pet instanceof LivingEntity) { - LivingEntity le = (LivingEntity) pet; - le.setRemoveWhenFarAway(false); - - // Verhindert, dass das Pet andere angreift - if (le instanceof Tameable) { - ((Tameable) le).setTamed(true); - ((Tameable) le).setOwner(player); + Location loc = player.getLocation(); + Entity pet = player.getWorld().spawnEntity(loc, entityType); + String agePrefix = baby ? "§bBaby " : ""; + String petName = buildPetDisplayName(type, variantName); + pet.setCustomName(agePrefix + petName); + pet.setCustomNameVisible(true); + pet.setInvulnerable(true); + pet.setPersistent(false); + applyNeutralPetTeam(pet); + if (pet instanceof LivingEntity le) { + le.setRemoveWhenFarAway(false); + if (le instanceof Ageable ageable) { + if (baby) { + ageable.setBaby(); + } else { + ageable.setAdult(); } - } + } - activePets.put(player.getUniqueId(), pet); - } + if (le instanceof Wolf && variantName != null && !variantName.isEmpty()) { + Wolf.Variant variant = resolveWolfVariant(variantName); + if (variant != null) { + ((Wolf)le).setVariant(variant); + } + } - /** - * Steuert das Folgen der Tiere. Wird vom GadgetModule-Timer aufgerufen. - */ - public static void updatePets() { - for (Map.Entry entry : activePets.entrySet()) { - Player owner = Bukkit.getPlayer(entry.getKey()); - Entity pet = entry.getValue(); + if (le instanceof Fox && variantName != null && !variantName.isEmpty()) { + try { + ((Fox)le).setFoxType(Type.valueOf(variantName)); + } catch (IllegalArgumentException var11) { + } + } - if (owner == null || !owner.isOnline() || pet.isDead()) { - continue; + if (le instanceof Tameable) { + ((Tameable)le).setTamed(true); + ((Tameable)le).setOwner(player); + } + } + + activePets.put(player.getUniqueId(), pet); + } + + public static void updatePets() { + for(Map.Entry entry : activePets.entrySet()) { + Player owner = Bukkit.getPlayer((UUID)entry.getKey()); + Entity pet = (Entity)entry.getValue(); + if (owner != null && owner.isOnline() && !pet.isDead()) { + if (pet.getWorld().equals(owner.getWorld()) && !(pet.getLocation().distance(owner.getLocation()) > (double)10.0F)) { + if (pet.getLocation().distance(owner.getLocation()) > (double)3.0F) { + Location target = owner.getLocation().clone().add(owner.getLocation().getDirection().multiply((double)-1.5F)); + target.setY(owner.getLocation().getY()); + pet.teleport(pet.getLocation().add(target.toVector().subtract(pet.getLocation().toVector()).normalize().multiply(0.2))); + Location lookAt = pet.getLocation(); + lookAt.setDirection(owner.getLocation().toVector().subtract(pet.getLocation().toVector())); + pet.teleport(lookAt); + } + } else { + pet.teleport(owner.getLocation()); + } + } + } + + } + + public static void removePet(Player player) { + if (activePets.containsKey(player.getUniqueId())) { + Entity pet = (Entity)activePets.get(player.getUniqueId()); + removeFromPetTeam(pet); + pet.remove(); + activePets.remove(player.getUniqueId()); + } + + } + + public static void clearAll() { + for(Entity pet : activePets.values()) { + removeFromPetTeam(pet); + pet.remove(); + } + + activePets.clear(); + } + + private static String capitalize(String str) { + if (str != null && !str.isEmpty()) { + String var10000 = str.substring(0, 1).toUpperCase(); + return var10000 + str.substring(1); + } else { + return str; + } + } + + private static String buildPetDisplayName(String type, String variantName) { + String baseType = capitalize(type.toLowerCase()); + if (variantName != null && !variantName.isEmpty()) { + String variant = capitalize(variantName.toLowerCase()); + return variant + " " + baseType; + } else { + return baseType; + } + } + + private static Wolf.Variant resolveWolfVariant(String variantName) { + String keyName = variantName.toLowerCase(); + NamespacedKey key = NamespacedKey.minecraft(keyName); + return (Wolf.Variant)Registry.WOLF_VARIANT.get(key); + } + + private static Team getOrCreatePetTeam() { + Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); + Team team = scoreboard.getTeam("nexus_pets"); + if (team == null) { + team = scoreboard.registerNewTeam("nexus_pets"); + team.setPrefix(""); + team.setSuffix(""); + } + + return team; + } + + private static void applyNeutralPetTeam(Entity pet) { + Team team = getOrCreatePetTeam(); + String entry = pet.getUniqueId().toString(); + if (!team.hasEntry(entry)) { + team.addEntry(entry); + } + + } + + private static void removeFromPetTeam(Entity pet) { + if (pet != null) { + Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); + Team team = scoreboard.getTeam("nexus_pets"); + if (team != null) { + String entry = pet.getUniqueId().toString(); + if (team.hasEntry(entry)) { + team.removeEntry(entry); } - // Wenn das Pet in einer anderen Welt ist oder zu weit weg, teleportiere es - if (!pet.getWorld().equals(owner.getWorld()) || pet.getLocation().distance(owner.getLocation()) > 10) { - pet.teleport(owner.getLocation()); - continue; - } + } + } + } - // Sanftes Folgen: Wenn das Pet weiter als 3 Blöcke weg ist - if (pet.getLocation().distance(owner.getLocation()) > 3) { - Location target = owner.getLocation().clone().add(owner.getLocation().getDirection().multiply(-1.5)); - target.setY(owner.getLocation().getY()); - - // Teleportiert das Pet leicht zum Ziel (simuliert Laufen) - pet.teleport(pet.getLocation().add(target.toVector().subtract(pet.getLocation().toVector()).normalize().multiply(0.2))); - - // Blickrichtung anpassen - Location lookAt = pet.getLocation(); - lookAt.setDirection(owner.getLocation().toVector().subtract(pet.getLocation().toVector())); - pet.teleport(lookAt); - } - } - } + @EventHandler + public void onPetDamage(EntityDamageEvent event) { + if (activePets.containsValue(event.getEntity())) { + event.setCancelled(true); + } - public static void removePet(Player player) { - if (activePets.containsKey(player.getUniqueId())) { - activePets.get(player.getUniqueId()).remove(); - activePets.remove(player.getUniqueId()); - } - } + } - public static void clearAll() { - for (Entity pet : activePets.values()) { - pet.remove(); - } - activePets.clear(); - } + @EventHandler + public void onPetTarget(EntityTargetEvent event) { + if (activePets.containsValue(event.getEntity())) { + event.setCancelled(true); + } - private static String capitalize(String str) { - if (str == null || str.isEmpty()) return str; - return str.substring(0, 1).toUpperCase() + str.substring(1); - } + } - // --- Events um die Pets zu schützen --- - - @EventHandler - public void onPetDamage(EntityDamageEvent event) { - if (activePets.containsValue(event.getEntity())) { - event.setCancelled(true); - } - } - - @EventHandler - public void onPetTarget(EntityTargetEvent event) { - if (activePets.containsValue(event.getEntity())) { - event.setCancelled(true); - } - } - - @EventHandler - public void onQuit(PlayerQuitEvent event) { - removePet(event.getPlayer()); - } -} \ No newline at end of file + @EventHandler + public void onQuit(PlayerQuitEvent event) { + removePet(event.getPlayer()); + } +} diff --git a/src/main/java/de/nexuslobby/modules/gadgets/ShieldTask.java b/src/main/java/de/nexuslobby/modules/gadgets/ShieldTask.java index 3a37d2b..52036be 100644 --- a/src/main/java/de/nexuslobby/modules/gadgets/ShieldTask.java +++ b/src/main/java/de/nexuslobby/modules/gadgets/ShieldTask.java @@ -1,53 +1,41 @@ package de.nexuslobby.modules.gadgets; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import org.bukkit.Particle; import org.bukkit.Sound; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - public class ShieldTask { + private static final Map pushCooldowns = new HashMap(); + private static final long PUSH_COOLDOWN_MS = 3000L; - /** - * Cooldown: Ein Spieler darf nur alle 3 Sekunden weggedrückt werden. - * Verhindert das permanente "Kleben" am Schutzschild-Träger. - */ - private static final Map pushCooldowns = new HashMap<>(); - private static final long PUSH_COOLDOWN_MS = 3_000L; + public static void handleShield(Player owner) { + for(double i = (double)0.0F; i < (Math.PI * 2D); i += (Math.PI / 8D)) { + double x = Math.cos(i) * 2.2; + double z = Math.sin(i) * 2.2; + owner.getWorld().spawnParticle(Particle.WITCH, owner.getLocation().add(x, (double)0.5F, z), 1, (double)0.0F, (double)0.0F, (double)0.0F, (double)0.0F); + } - public static void handleShield(Player owner) { - // Erzeuge einen Partikel-Ring um den Spieler - for (double i = 0; i < Math.PI * 2; i += Math.PI / 8) { - double x = Math.cos(i) * 2.2; - double z = Math.sin(i) * 2.2; - owner.getWorld().spawnParticle(Particle.WITCH, owner.getLocation().add(x, 0.5, z), 1, 0, 0, 0, 0); - } + long now = System.currentTimeMillis(); - long now = System.currentTimeMillis(); + for(Entity entity : owner.getNearbyEntities(2.2, (double)2.0F, 2.2)) { + if (entity instanceof Player target) { + if (entity != owner && !GadgetShield.isProtected(target)) { + long lastPush = (Long)pushCooldowns.getOrDefault(target.getUniqueId(), 0L); + if (now - lastPush >= 3000L) { + pushCooldowns.put(target.getUniqueId(), now); + Vector direction = target.getLocation().toVector().subtract(owner.getLocation().toVector()).normalize(); + direction.multiply(0.4).setY(0.2); + target.setVelocity(direction); + target.playSound(target.getLocation(), Sound.ENTITY_CHICKEN_EGG, 0.5F, 0.5F); + } + } + } + } - // Stoße andere Spieler weg - for (Entity entity : owner.getNearbyEntities(2.2, 2.0, 2.2)) { - if (!(entity instanceof Player target) || entity == owner) continue; - - // FIX: OP-Admins mit aktivem Gadget-Schutz und Parkour-Spieler sind immun - if (GadgetShield.isProtected(target)) continue; - - // FIX: 3-Sekunden-Cooldown – jedes Ziel wird max. 1x alle 3s weggedrückt - long lastPush = pushCooldowns.getOrDefault(target.getUniqueId(), 0L); - if (now - lastPush < PUSH_COOLDOWN_MS) continue; - pushCooldowns.put(target.getUniqueId(), now); - - Vector direction = target.getLocation().toVector() - .subtract(owner.getLocation().toVector()) - .normalize(); - direction.multiply(0.4).setY(0.2); - - target.setVelocity(direction); - target.playSound(target.getLocation(), Sound.ENTITY_CHICKEN_EGG, 0.5f, 0.5f); - } - } -} \ No newline at end of file + } +} diff --git a/src/main/java/de/nexuslobby/modules/intro/IntroModule.java b/src/main/java/de/nexuslobby/modules/intro/IntroModule.java index 701f65e..7848408 100644 --- a/src/main/java/de/nexuslobby/modules/intro/IntroModule.java +++ b/src/main/java/de/nexuslobby/modules/intro/IntroModule.java @@ -2,8 +2,6 @@ package de.nexuslobby.modules.intro; import de.nexuslobby.NexusLobby; import de.nexuslobby.api.Module; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; @@ -16,7 +14,6 @@ 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.PlayerToggleSneakEvent; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; @@ -27,13 +24,24 @@ import java.util.*; public class IntroModule implements Module, Listener, CommandExecutor { private final Set activeIntro = new HashSet<>(); + private final List points = new ArrayList<>(); + private final List labels = new ArrayList<>(); + + // Abschluss-Titel (konfigurierbar) + private String endTitle = "§a§lWillkommen!"; + private String endSubtitle = "§7Viel Spaß auf NexusLobby"; + private File configFile; private FileConfiguration config; // --- Einstellungen --- - private final int TICKS_FLUG = 70; // Dauer der Fahrt zwischen zwei Punkten (3.5 Sek) - private final int TICKS_PAUSE = 30; // Standzeit an jedem Punkt (1.5 Sek) + private final int TICKS_FLUG = 70; + private final int TICKS_PAUSE = 30; + + private final int TITLE_FADE_IN = 10; + private final int TITLE_STAY = 50; + private final int TITLE_FADE_OUT = 10; @Override public String getName() { return "Intro"; } @@ -44,7 +52,7 @@ public class IntroModule implements Module, Listener, CommandExecutor { if (NexusLobby.getInstance().getCommand("intro") != null) { NexusLobby.getInstance().getCommand("intro").setExecutor(this); } - loadPoints(); + loadConfig(); } @Override @@ -53,30 +61,79 @@ public class IntroModule implements Module, Listener, CommandExecutor { activeIntro.clear(); } - private void loadPoints() { + // ───────────────────────────────────────────────────────────────────────── + // Persistenz + // ───────────────────────────────────────────────────────────────────────── + + private void loadConfig() { points.clear(); + labels.clear(); configFile = new File(NexusLobby.getInstance().getDataFolder(), "intro.yml"); if (!configFile.exists()) { try { configFile.createNewFile(); } catch (IOException ignored) {} } config = YamlConfiguration.loadConfiguration(configFile); - List list = config.getList("points"); + + // Abschluss-Titel laden + endTitle = config.getString("end-title", "§a§lWillkommen!"); + endSubtitle = config.getString("end-subtitle", "§7Viel Spaß auf NexusLobby"); + + // Punkte laden + List list = config.getList("intro-points"); if (list != null) { for (Object obj : list) { - if (obj instanceof Location loc) points.add(loc); + if (obj instanceof Map map) { + Object locObj = map.get("location"); + Object labelObj = map.get("label"); + if (locObj instanceof Location loc) { + points.add(loc); + labels.add(labelObj != null ? labelObj.toString() : ""); + } + } + } + } + + // Rückwärts-Kompatibilität + if (points.isEmpty()) { + List oldList = config.getList("points"); + if (oldList != null) { + for (Object obj : oldList) { + if (obj instanceof Location loc) { + points.add(loc); + labels.add(""); + } + } } } } - private void savePoints() { - config.set("points", points); - try { - config.save(configFile); - } catch (IOException e) { + private void saveConfig() { + // Abschluss-Titel speichern + config.set("end-title", endTitle); + config.set("end-subtitle", endSubtitle); + + // Punkte speichern + List> data = new ArrayList<>(); + for (int i = 0; i < points.size(); i++) { + Map entry = new LinkedHashMap<>(); + entry.put("location", points.get(i)); + entry.put("label", labels.get(i)); + data.add(entry); + } + config.set("intro-points", data); + config.set("points", null); + + try { + config.save(configFile); + } catch (IOException e) { NexusLobby.getInstance().getLogger().severe("Fehler beim Speichern der Intro-Config: " + e.getMessage()); } } + // ───────────────────────────────────────────────────────────────────────── + // Events + // ───────────────────────────────────────────────────────────────────────── + @EventHandler public void onJoin(PlayerJoinEvent event) { if (!event.getPlayer().hasPlayedBefore() && points.size() >= 2) { @@ -84,12 +141,9 @@ public class IntroModule implements Module, Listener, CommandExecutor { } } - @EventHandler - public void onSneak(PlayerToggleSneakEvent event) { - if (activeIntro.contains(event.getPlayer().getUniqueId()) && event.isSneaking()) { - stopIntro(event.getPlayer(), true); - } - } + // ───────────────────────────────────────────────────────────────────────── + // Befehle + // ───────────────────────────────────────────────────────────────────────── @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { @@ -97,26 +151,52 @@ public class IntroModule implements Module, Listener, CommandExecutor { if (!p.hasPermission("nexuslobby.admin")) return true; if (args.length == 0) { - p.sendMessage("§8§m------------------------------------"); - p.sendMessage("§6§lNexus Intro System (Cinematic)"); - p.sendMessage("§e/intro add §7- Punkt hinzufügen"); - p.sendMessage("§e/intro clear §7- Alle Punkte löschen"); - p.sendMessage("§e/intro start §7- Teste die Fahrt"); - p.sendMessage("§8§m------------------------------------"); + sendHelp(p); return true; } switch (args[0].toLowerCase()) { + case "add" -> { + String pointLabel = args.length > 1 + ? String.join(" ", Arrays.copyOfRange(args, 1, args.length)) + : ""; points.add(p.getLocation()); - savePoints(); - p.sendMessage("§8[§6Nexus§8] §aPunkt #" + points.size() + " wurde gesetzt!"); + labels.add(pointLabel); + saveConfig(); + if (pointLabel.isEmpty()) { + p.sendMessage("§8[§6Nexus§8] §aPunkt §e#" + points.size() + " §awurde gesetzt."); + } else { + p.sendMessage("§8[§6Nexus§8] §aPunkt §e#" + points.size() + " §amit Text §e\"" + pointLabel + "\" §agesetzt."); + } } + case "clear" -> { points.clear(); - savePoints(); + labels.clear(); + saveConfig(); p.sendMessage("§8[§6Nexus§8] §cAlle Intro-Punkte wurden gelöscht."); } + + case "list" -> { + if (points.isEmpty()) { + p.sendMessage("§8[§6Nexus§8] §cKeine Punkte vorhanden."); + return true; + } + p.sendMessage("§8§m------------------------------------"); + p.sendMessage("§6§lIntro-Punkte (" + points.size() + ")"); + for (int i = 0; i < points.size(); i++) { + Location loc = points.get(i); + String lbl = labels.get(i).isEmpty() ? "§7(kein Text)" : "§e" + labels.get(i); + p.sendMessage("§8#" + (i + 1) + " §7" + + String.format("%.1f", loc.getX()) + ", " + + String.format("%.1f", loc.getY()) + ", " + + String.format("%.1f", loc.getZ()) + + " " + lbl); + } + p.sendMessage("§8§m------------------------------------"); + } + case "start" -> { if (points.size() < 2) { p.sendMessage("§8[§6Nexus§8] §cDu brauchst mindestens 2 Punkte für eine Fahrt."); @@ -124,18 +204,69 @@ public class IntroModule implements Module, Listener, CommandExecutor { startIntro(p); } } + + // /intro setendtitle — setzt den großen Abschluss-Titel + case "setendtitle" -> { + if (args.length < 2) { + p.sendMessage("§8[§6Nexus§8] §cBenutzung: §e/intro setendtitle "); + p.sendMessage("§7Farbcodes mit §e& §7möglich. Beispiel: §e/intro setendtitle &a&lWillkommen!"); + return true; + } + endTitle = colorize(String.join(" ", Arrays.copyOfRange(args, 1, args.length))); + saveConfig(); + p.sendMessage("§8[§6Nexus§8] §aAbschluss-Titel gesetzt: " + endTitle); + // Vorschau + p.sendTitle(endTitle, endSubtitle, TITLE_FADE_IN, TITLE_STAY, TITLE_FADE_OUT); + } + + // /intro setendsubtitle — setzt den kleinen Abschluss-Untertitel + case "setendsubtitle" -> { + if (args.length < 2) { + p.sendMessage("§8[§6Nexus§8] §cBenutzung: §e/intro setendsubtitle "); + p.sendMessage("§7Farbcodes mit §e& §7möglich. Beispiel: §e/intro setendsubtitle &7Viel Spaß!"); + return true; + } + endSubtitle = colorize(String.join(" ", Arrays.copyOfRange(args, 1, args.length))); + saveConfig(); + p.sendMessage("§8[§6Nexus§8] §aAbschluss-Untertitel gesetzt: " + endSubtitle); + // Vorschau + p.sendTitle(endTitle, endSubtitle, TITLE_FADE_IN, TITLE_STAY, TITLE_FADE_OUT); + } + + default -> sendHelp(p); } return true; } + private void sendHelp(Player p) { + p.sendMessage("§8§m------------------------------------"); + p.sendMessage("§6§lNexus Intro System (Cinematic)"); + p.sendMessage("§e/intro add [Text] §7- Punkt + optionaler Titel"); + p.sendMessage("§e/intro clear §7- Alle Punkte löschen"); + p.sendMessage("§e/intro list §7- Alle Punkte anzeigen"); + p.sendMessage("§e/intro start §7- Fahrt testen"); + p.sendMessage("§e/intro setendtitle §7- Abschluss-Titel setzen"); + p.sendMessage("§e/intro setendsubtitle §7- Abschluss-Untertitel setzen"); + p.sendMessage("§7Aktuell: §r" + endTitle + " §8/ §r" + endSubtitle); + p.sendMessage("§8§m------------------------------------"); + } + + // ───────────────────────────────────────────────────────────────────────── + // Intro-Logik + // ───────────────────────────────────────────────────────────────────────── + public void startIntro(Player player) { activeIntro.add(player.getUniqueId()); player.setGameMode(GameMode.SPECTATOR); + // Titel für den ersten Punkt sofort anzeigen + showTitleForSegment(player, 0); + new BukkitRunnable() { - int currentSegment = 0; - int tickInSegment = 0; - boolean isPausing = true; + int currentSegment = 0; + int tickInSegment = 0; + boolean isPausing = true; + int lastTitleSegment = 0; @Override public void run() { @@ -146,79 +277,89 @@ public class IntroModule implements Module, Listener, CommandExecutor { } if (currentSegment >= points.size() - 1) { - stopIntro(player, false); + stopIntro(player); this.cancel(); return; } Location start = points.get(currentSegment); - Location end = points.get(currentSegment + 1); + Location end = points.get(currentSegment + 1); if (isPausing) { - // Kamera steht am aktuellen Punkt player.teleport(start); tickInSegment++; if (tickInSegment >= TICKS_PAUSE) { - isPausing = false; + isPausing = false; tickInSegment = 0; } } else { - // Kamera fliegt zum nächsten Punkt double progress = (double) tickInSegment / (double) TICKS_FLUG; - - // "Smooth Step" für flüssigeres Beschleunigen/Bremsen - double smoothT = progress * progress * (3 - 2 * progress); - - Location nextLoc = interpolate(start, end, smoothT); - player.teleport(nextLoc); + double smoothT = progress * progress * (3 - 2 * progress); + + player.teleport(interpolate(start, end, smoothT)); tickInSegment++; if (tickInSegment >= TICKS_FLUG) { - isPausing = true; + isPausing = true; tickInSegment = 0; currentSegment++; + + if (currentSegment < points.size() && currentSegment != lastTitleSegment) { + showTitleForSegment(player, currentSegment); + lastTitleSegment = currentSegment; + } } } - player.spigot().sendMessage(ChatMessageType.ACTION_BAR, - new TextComponent("§6§lINTRO-TOUR §8| §ePunkt " + (currentSegment + 1) + " §8| §7Sneak zum Abbrechen")); - } catch (Exception e) { this.cancel(); - stopIntro(player, true); + stopIntro(player); } } }.runTaskTimer(NexusLobby.getInstance(), 0L, 1L); } + private void showTitleForSegment(Player player, int segmentIndex) { + if (segmentIndex < 0 || segmentIndex >= labels.size()) return; + String lbl = labels.get(segmentIndex); + if (lbl == null || lbl.isEmpty()) return; + + player.sendTitle( + "§6§l" + lbl, + "§7✦ NexusLobby ✦", + TITLE_FADE_IN, + TITLE_STAY, + TITLE_FADE_OUT + ); + } + private Location interpolate(Location start, Location end, double t) { double x = start.getX() + (end.getX() - start.getX()) * t; double y = start.getY() + (end.getY() - start.getY()) * t; double z = start.getZ() + (end.getZ() - start.getZ()) * t; - - // Sanfte Drehung - float startYaw = start.getYaw(); - float endYaw = end.getYaw(); - // Verhindert ruckartige 360-Grad Dreher - float diff = (endYaw - startYaw) % 360; - if (diff > 180) diff -= 360; - if (diff < -180) diff += 360; - float yaw = startYaw + diff * (float)t; + float startYaw = start.getYaw(); + float endYaw = end.getYaw(); + float diff = (endYaw - startYaw) % 360; + if (diff > 180) diff -= 360; + if (diff < -180) diff += 360; + float yaw = startYaw + diff * (float) t; float pitch = (float) (start.getPitch() + (end.getPitch() - start.getPitch()) * t); return new Location(start.getWorld(), x, y, z, yaw, pitch); } - private void stopIntro(Player player, boolean canceled) { + private void stopIntro(Player player) { activeIntro.remove(player.getUniqueId()); player.setGameMode(GameMode.ADVENTURE); player.teleport(player.getWorld().getSpawnLocation()); - - if (canceled) { - player.sendMessage("§8[§6Nexus§8] §cIntro abgebrochen."); - } else { - player.sendMessage("§8[§6Nexus§8] §aWillkommen auf dem Netzwerk!"); - } + + // Abschluss-Titel — komplett konfigurierbar + player.sendTitle(endTitle, endSubtitle, 10, 60, 20); + } + + /** Ersetzt &-Farbcodes durch §-Codes */ + private String colorize(String input) { + return input.replace("&", "§"); } } \ No newline at end of file diff --git a/src/main/java/de/nexuslobby/modules/servers/ServerSwitcherListener.java b/src/main/java/de/nexuslobby/modules/servers/ServerSwitcherListener.java index 9c3925c..241f5c6 100644 --- a/src/main/java/de/nexuslobby/modules/servers/ServerSwitcherListener.java +++ b/src/main/java/de/nexuslobby/modules/servers/ServerSwitcherListener.java @@ -146,20 +146,50 @@ public class ServerSwitcherListener implements Listener, CommandExecutor { int clickedSlot = e.getSlot(); ConfigurationSection serversSection = NexusLobby.getInstance().getConfig().getConfigurationSection("compass.servers"); - if (serversSection != null) { - for (String serverId : serversSection.getKeys(false)) { - String path = "compass.servers." + serverId; - int configSlot = NexusLobby.getInstance().getConfig().getInt(path + ".slot", -1); + if (serversSection == null) return; - if (configSlot == clickedSlot) { - String command = NexusLobby.getInstance().getConfig().getString(path + ".command"); - if (command != null && !command.isEmpty()) { - p.closeInventory(); - p.chat("/" + command); - return; - } - } + for (String serverId : serversSection.getKeys(false)) { + String path = "compass.servers." + serverId; + int configSlot = NexusLobby.getInstance().getConfig().getInt(path + ".slot", -1); + + if (configSlot != clickedSlot) continue; + + String command = NexusLobby.getInstance().getConfig().getString(path + ".command", "").trim(); + if (command.isEmpty()) return; + + p.closeInventory(); + + // "server " → BungeeCord Connect Plugin-Message + if (command.toLowerCase().startsWith("server ")) { + String serverName = command.substring(7).trim(); + connectBungee(p, serverName); + } else { + // Alle anderen Befehle als Konsolen-Befehl ausführen + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), + command.replace("%player%", p.getName())); } + return; + } + } + + /** + * Sendet den Spieler per BungeeCord Plugin-Message an einen anderen Server. + */ + private void connectBungee(Player player, String serverName) { + if (!Bukkit.getMessenger().isOutgoingChannelRegistered( + NexusLobby.getInstance(), "BungeeCord")) { + player.sendMessage("§8[§6Nexus§8] §cKein BungeeCord-Kanal registriert."); + return; + } + try { + java.io.ByteArrayOutputStream b = new java.io.ByteArrayOutputStream(); + java.io.DataOutputStream out = new java.io.DataOutputStream(b); + out.writeUTF("Connect"); + out.writeUTF(serverName); + player.sendPluginMessage(NexusLobby.getInstance(), "BungeeCord", b.toByteArray()); + player.sendMessage("§8[§6Nexus§8] §7Verbinde mit §e" + serverName + "§7..."); + } catch (java.io.IOException ex) { + player.sendMessage("§8[§6Nexus§8] §cFehler beim Verbinden: " + ex.getMessage()); } } } \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index b7f8fcd..b97c225 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: NexusLobby main: de.nexuslobby.NexusLobby -version: "1.7" +version: "1.8" api-version: "1.21" author: M_Viper description: Modular Lobby Plugin with an invisible Particle-Parkour system.