Update from Git Manager GUI

This commit is contained in:
2026-02-01 22:19:40 +01:00
parent ce43cac14f
commit 6a892c45db
9 changed files with 570 additions and 42 deletions

View File

@@ -22,7 +22,8 @@ import de.nexuslobby.modules.intro.IntroModule;
import de.nexuslobby.modules.border.BorderModule; import de.nexuslobby.modules.border.BorderModule;
import de.nexuslobby.modules.parkour.ParkourManager; import de.nexuslobby.modules.parkour.ParkourManager;
import de.nexuslobby.modules.parkour.ParkourListener; import de.nexuslobby.modules.parkour.ParkourListener;
import de.nexuslobby.modules.player.PlayerInspectModule; // NEU import de.nexuslobby.modules.player.PlayerInspectModule;
import de.nexuslobby.modules.ball.SoccerModule; // NEU
import de.nexuslobby.utils.*; import de.nexuslobby.utils.*;
import me.clip.placeholderapi.expansion.PlaceholderExpansion; import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.ClickEvent;
@@ -67,6 +68,7 @@ public class NexusLobby extends JavaPlugin implements Listener {
private IntroModule introModule; private IntroModule introModule;
private BorderModule borderModule; private BorderModule borderModule;
private ParkourManager parkourManager; private ParkourManager parkourManager;
private SoccerModule soccerModule; // NEU
private ConversationManager conversationManager; private ConversationManager conversationManager;
@@ -94,6 +96,10 @@ public class NexusLobby extends JavaPlugin implements Listener {
return parkourManager; return parkourManager;
} }
public SoccerModule getSoccerModule() { // NEU
return soccerModule;
}
@Override @Override
public void onEnable() { public void onEnable() {
instance = this; instance = this;
@@ -233,7 +239,11 @@ public class NexusLobby extends JavaPlugin implements Listener {
moduleManager.registerModule(tablistModule); moduleManager.registerModule(tablistModule);
// Player Inspect Modul registrieren // Player Inspect Modul registrieren
moduleManager.registerModule(new PlayerInspectModule()); // NEU moduleManager.registerModule(new PlayerInspectModule());
// Soccer Modul registrieren
this.soccerModule = new SoccerModule(); // NEU
moduleManager.registerModule(this.soccerModule); // NEU
this.portalManager = new PortalManager(this); this.portalManager = new PortalManager(this);
moduleManager.registerModule(portalManager); moduleManager.registerModule(portalManager);

View File

@@ -32,7 +32,7 @@ public class LobbyTabCompleter implements TabCompleter {
if (cmdName.equals("nexuslobby") || cmdName.equals("nexus")) { if (cmdName.equals("nexuslobby") || cmdName.equals("nexus")) {
if (args.length == 1) { if (args.length == 1) {
if (sender.hasPermission("nexuslobby.admin")) { if (sender.hasPermission("nexuslobby.admin")) {
suggestions.addAll(Arrays.asList("reload", "setspawn", "silentjoin", "parkour")); suggestions.addAll(Arrays.asList("reload", "setspawn", "silentjoin", "parkour", "ball")); // NEU: ball
} }
suggestions.add("sb"); suggestions.add("sb");
} else if (args.length == 2) { } else if (args.length == 2) {
@@ -45,6 +45,10 @@ public class LobbyTabCompleter implements TabCompleter {
suggestions.addAll(Arrays.asList("on", "off")); suggestions.addAll(Arrays.asList("on", "off"));
} else if (args[0].equalsIgnoreCase("parkour")) { } else if (args[0].equalsIgnoreCase("parkour")) {
suggestions.addAll(Arrays.asList("setstart", "setfinish", "setcheckpoint", "reset", "clear", "removeall")); suggestions.addAll(Arrays.asList("setstart", "setfinish", "setcheckpoint", "reset", "clear", "removeall"));
} else if (args[0].equalsIgnoreCase("ball")) { // NEU: Ball Subcommands
if (sender.hasPermission("nexuslobby.admin")) {
suggestions.addAll(Arrays.asList("setspawn", "reload"));
}
} }
} else if (args.length == 3) { } else if (args.length == 3) {
if (args[0].equalsIgnoreCase("parkour") && args[1].equalsIgnoreCase("setcheckpoint")) { if (args[0].equalsIgnoreCase("parkour") && args[1].equalsIgnoreCase("setcheckpoint")) {
@@ -118,7 +122,6 @@ public class LobbyTabCompleter implements TabCompleter {
} else if (args[0].equalsIgnoreCase("name")) { } else if (args[0].equalsIgnoreCase("name")) {
suggestions.addAll(Arrays.asList("<Anzeigename>", "none")); suggestions.addAll(Arrays.asList("<Anzeigename>", "none"));
} else if (args[0].equalsIgnoreCase("conv")) { } else if (args[0].equalsIgnoreCase("conv")) {
// ERWEITERT: select3 und select4 hinzugefügt
suggestions.addAll(Arrays.asList("select1", "select2", "select3", "select4", "link", "unlink", "start")); suggestions.addAll(Arrays.asList("select1", "select2", "select3", "select4", "link", "unlink", "start"));
} else if (args[0].equalsIgnoreCase("remove")) { } else if (args[0].equalsIgnoreCase("remove")) {
suggestions.addAll(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "all")); suggestions.addAll(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "all"));

View File

@@ -110,6 +110,13 @@ public class NexusLobbyCommand implements CommandExecutor {
handleScoreboard(player, args); handleScoreboard(player, args);
break; break;
case "ball": // NEU: Weiterleitung an das SoccerModule
if (NexusLobby.getInstance().getSoccerModule() != null) {
return NexusLobby.getInstance().getSoccerModule().onCommand(sender, command, label, args);
}
player.sendMessage("§cDas Fußball-Modul ist nicht geladen.");
break;
case "parkour": case "parkour":
if (args.length < 2) { if (args.length < 2) {
player.sendMessage("§8[§6Nexus§8] §7Nutze: §e/nexus parkour <setstart|setfinish|setcheckpoint|reset|clear|removeall>"); player.sendMessage("§8[§6Nexus§8] §7Nutze: §e/nexus parkour <setstart|setfinish|setcheckpoint|reset|clear|removeall>");
@@ -225,6 +232,7 @@ public class NexusLobbyCommand implements CommandExecutor {
player.sendMessage("§f/spawn §7- Zum Spawn"); player.sendMessage("§f/spawn §7- Zum Spawn");
player.sendMessage("§f/setstart §8| §f/setcheckpoint §8| §f/setfinish"); player.sendMessage("§f/setstart §8| §f/setcheckpoint §8| §f/setfinish");
player.sendMessage("§f/nexus parkour removeall §7- Strecke löschen"); player.sendMessage("§f/nexus parkour removeall §7- Strecke löschen");
player.sendMessage("§f/nexus ball setspawn §7- Fußball Spawn setzen"); // NEU
player.sendMessage("§f/nexus setspawn §7- Spawn setzen"); player.sendMessage("§f/nexus setspawn §7- Spawn setzen");
player.sendMessage("§f/nexus sb <on|off> §7- Scoreboard"); player.sendMessage("§f/nexus sb <on|off> §7- Scoreboard");
player.sendMessage("§f/nexus reload §7- Config laden"); player.sendMessage("§f/nexus reload §7- Config laden");

View File

@@ -0,0 +1,312 @@
package de.nexuslobby.modules.ball;
import de.nexuslobby.NexusLobby;
import de.nexuslobby.api.Module;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.profile.PlayerProfile;
import org.bukkit.profile.PlayerTextures;
import org.bukkit.util.Vector;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;
import java.util.Objects;
public class SoccerModule implements Module, Listener, CommandExecutor {
private ArmorStand ball;
private Location spawnLocation;
private long lastMoveTime;
private final String TEXTURE_URL = "http://textures.minecraft.net/texture/451f8cfcfb85d77945dc6a3618414093e70436b46d2577b28c727f1329b7265e";
private final String BALL_TAG = "nexusball_entity"; // Eindeutiges Tag zur Identifizierung
private final String BALL_NAME = "§x§N§e§x§u§s§B§a§l§l"; // Zusätzliche Erkennung
@Override
public String getName() { return "Soccer"; }
@Override
public void onEnable() {
Bukkit.getPluginManager().registerEvents(this, NexusLobby.getInstance());
if (NexusLobby.getInstance().getCommand("nexuslobby") != null) {
Objects.requireNonNull(NexusLobby.getInstance().getCommand("nexuslobby")).setExecutor(this);
}
loadConfigLocation();
// AGGRESSIVES MEHRFACHES CLEANUP-SYSTEM
// 1. Sofort beim Enable
removeAllOldBallsGlobal();
// 2. Nach 0.5 Sekunden
Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), this::removeAllOldBallsGlobal, 10L);
// 3. Nach 1 Sekunde
Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), this::removeAllOldBallsGlobal, 20L);
// 4. Nach 2 Sekunden - cleanup und dann spawnen
Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), () -> {
removeAllOldBallsGlobal();
spawnBall();
}, 40L);
// 5. Nach 3 Sekunden - finales Cleanup für hartnäckige Duplikate
Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), this::removeAllOldBallsGlobal, 60L);
// 6. Nach 5 Sekunden - letzter Check
Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), this::removeAllOldBallsGlobal, 100L);
// Haupt-Physik & Anti-Klon Tick
Bukkit.getScheduler().runTaskTimer(NexusLobby.getInstance(), () -> {
// ANTI-KLON-SYSTEM: Prüfe die Umgebung des Spawns auf illegale Kopien
if (spawnLocation != null && spawnLocation.getWorld() != null) {
for (Entity entity : spawnLocation.getWorld().getNearbyEntities(spawnLocation, 50, 50, 50)) {
if (entity instanceof ArmorStand stand) {
// Wenn der ArmorStand unser Tag hat, aber nicht unsere aktive Instanz ist -> Löschen
if (stand.getScoreboardTags().contains(BALL_TAG)) {
if (ball == null || !stand.getUniqueId().equals(ball.getUniqueId())) {
stand.remove();
}
}
}
}
}
if (ball == null || !ball.isValid()) return;
Vector vel = ball.getVelocity();
double speed = vel.length();
handleWallBounce(vel);
handleParticles(speed);
// Dribbel-Logik
for (Entity nearby : ball.getNearbyEntities(0.7, 0.5, 0.7)) {
if (nearby instanceof Player p) {
Vector direction = ball.getLocation().toVector().subtract(p.getLocation().toVector());
if (direction.lengthSquared() > 0) {
direction.normalize();
direction.setY(0.12);
ball.setVelocity(direction.multiply(0.35));
}
lastMoveTime = System.currentTimeMillis();
}
}
// Automatischer Respawn bei Inaktivität oder Void
long delay = NexusLobby.getInstance().getConfig().getLong("ball.respawn_delay", 60) * 1000;
if (System.currentTimeMillis() - lastMoveTime > delay || ball.getLocation().getY() < -5) {
respawnBall();
}
}, 1L, 1L);
}
/**
* Scannt ALLE Welten nach Entities mit dem BALL_TAG und entfernt sie.
* Nutzt mehrere Erkennungsmethoden für maximale Sicherheit.
*/
private void removeAllOldBallsGlobal() {
int removed = 0;
// Alle Welten durchsuchen
for (World world : Bukkit.getWorlds()) {
for (Entity entity : world.getEntities()) {
if (entity instanceof ArmorStand stand) {
boolean shouldRemove = false;
// Methode 1: Tag-basiert
if (stand.getScoreboardTags().contains(BALL_TAG)) {
shouldRemove = true;
}
// Methode 2: Name-basiert (falls Tags verloren gehen)
if (stand.getCustomName() != null && stand.getCustomName().equals(BALL_NAME)) {
shouldRemove = true;
}
// Methode 3: Kopf-Textur-basiert (prüfe ob es ein Soccer-Ball Kopf ist)
if (stand.getEquipment() != null && stand.getEquipment().getHelmet() != null) {
ItemStack helmet = stand.getEquipment().getHelmet();
if (helmet.getType() == Material.PLAYER_HEAD && helmet.hasItemMeta()) {
SkullMeta meta = (SkullMeta) helmet.getItemMeta();
if (meta.hasOwner() && meta.getOwnerProfile() != null) {
PlayerProfile profile = meta.getOwnerProfile();
if (profile.getName() != null && profile.getName().equals("SoccerBall")) {
shouldRemove = true;
}
}
}
}
// Methode 4: Position-basiert - Entferne alle unsichtbaren, kleinen ArmorStands in der Nähe des Spawns
if (spawnLocation != null && spawnLocation.getWorld() != null &&
stand.getWorld().equals(spawnLocation.getWorld()) &&
stand.isSmall() && stand.isInvisible() && !stand.hasBasePlate()) {
double distance = stand.getLocation().distance(spawnLocation);
// Wenn innerhalb von 5 Blöcken vom Spawn und hat einen Kopf
if (distance < 5.0 && stand.getEquipment() != null &&
stand.getEquipment().getHelmet() != null &&
stand.getEquipment().getHelmet().getType() == Material.PLAYER_HEAD) {
shouldRemove = true;
}
}
// Nur entfernen wenn es NICHT unsere aktuelle Ball-Instanz ist
if (shouldRemove && (ball == null || !stand.getUniqueId().equals(ball.getUniqueId()))) {
stand.remove();
removed++;
}
}
}
}
if (removed > 0) {
Bukkit.getLogger().info("[NexusLobby] " + removed + " alte Ball-Entities entfernt.");
}
}
private void handleWallBounce(Vector vel) {
if (vel.lengthSquared() < 0.001) return;
Location loc = ball.getLocation();
Block nextX = loc.clone().add(vel.getX() * 1.3, 0.5, 0).getBlock();
Block nextZ = loc.clone().add(0, 0.5, vel.getZ() * 1.3).getBlock();
boolean bounced = false;
if (nextX.getType().isSolid()) { vel.setX(-vel.getX() * 0.75); bounced = true; }
if (nextZ.getType().isSolid()) { vel.setZ(-vel.getZ() * 0.75); bounced = true; }
if (bounced) {
ball.setVelocity(vel);
ball.getWorld().playSound(ball.getLocation(), Sound.BLOCK_WOOD_BREAK, 0.6f, 1.3f);
}
}
private void handleParticles(double speed) {
if (speed < 0.05) return;
Location loc = ball.getLocation().add(0, 0.2, 0);
World world = loc.getWorld();
if (world == null) return;
if (speed > 0.85) world.spawnParticle(Particle.SONIC_BOOM, loc, 1, 0, 0, 0, 0);
else if (speed > 0.45) world.spawnParticle(Particle.CRIT, loc, 3, 0.1, 0.1, 0.1, 0.08);
else world.spawnParticle(Particle.SMOKE, loc, 1, 0.05, 0, 0.05, 0.02);
}
private void spawnBall() {
if (spawnLocation == null || (ball != null && ball.isValid())) return;
// Ball direkt auf dem Boden spawnen (keine Y-Offset Erhöhung)
Location spawnLoc = spawnLocation.clone();
ball = (ArmorStand) spawnLoc.getWorld().spawnEntity(spawnLoc, EntityType.ARMOR_STAND);
ball.setInvisible(true);
ball.setGravity(true);
ball.setBasePlate(false);
ball.setSmall(true);
ball.setInvulnerable(false);
ball.setArms(false);
ball.setCustomNameVisible(false);
// Setze Custom Name für zusätzliche Erkennung (unsichtbar für Spieler)
ball.setCustomName(BALL_NAME);
// Deaktiviert das Speichern in der Welt-Datei
ball.setPersistent(false);
// Markiert den Ball für das Cleanup-System
ball.addScoreboardTag(BALL_TAG);
ItemStack ballHead = getSoccerHead();
if (ball.getEquipment() != null) ball.getEquipment().setHelmet(ballHead);
lastMoveTime = System.currentTimeMillis();
}
private ItemStack getSoccerHead() {
ItemStack head = new ItemStack(Material.PLAYER_HEAD);
SkullMeta meta = (SkullMeta) head.getItemMeta();
if (meta == null) return head;
PlayerProfile profile = Bukkit.createPlayerProfile(UUID.randomUUID(), "SoccerBall");
try {
profile.getTextures().setSkin(new URL(TEXTURE_URL));
} catch (MalformedURLException ignored) {}
meta.setOwnerProfile(profile);
head.setItemMeta(meta);
return head;
}
public void respawnBall() {
if (ball != null) {
ball.remove();
ball = null;
}
removeAllOldBallsGlobal();
spawnBall();
}
@EventHandler
public void onBallPunch(EntityDamageByEntityEvent event) {
if (event.getEntity().equals(ball)) {
event.setCancelled(true);
if (event.getDamager() instanceof Player p) {
Vector shootDir = p.getLocation().getDirection();
if (shootDir.lengthSquared() > 0) {
shootDir.normalize().multiply(1.35).setY(0.38);
ball.setVelocity(shootDir);
}
ball.getWorld().playSound(ball.getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 0.6f, 1.5f);
lastMoveTime = System.currentTimeMillis();
}
}
}
@EventHandler
public void onBallInteract(PlayerInteractAtEntityEvent event) {
if (event.getRightClicked().equals(ball)) event.setCancelled(true);
}
private void loadConfigLocation() {
FileConfiguration config = NexusLobby.getInstance().getConfig();
if (config.contains("ball.spawn")) spawnLocation = config.getLocation("ball.spawn");
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player p) || !p.hasPermission("nexuslobby.admin")) return true;
if (args.length >= 2 && args[0].equalsIgnoreCase("ball")) {
if (args[1].equalsIgnoreCase("setspawn")) {
spawnLocation = p.getLocation();
NexusLobby.getInstance().getConfig().set("ball.spawn", spawnLocation);
NexusLobby.getInstance().saveConfig();
respawnBall();
p.sendMessage("§8[§6Nexus§8] §aBall-Spawn gesetzt. Cleanup ist aktiv!");
return true;
} else if (args[1].equalsIgnoreCase("respawn")) {
respawnBall();
p.sendMessage("§8[§6Nexus§8] §eBall manuell respawnt.");
return true;
}
}
return false;
}
@Override
public void onDisable() {
if (ball != null) ball.remove();
}
}

View File

@@ -3,6 +3,7 @@ package de.nexuslobby.modules.gadgets;
import de.nexuslobby.NexusLobby; import de.nexuslobby.NexusLobby;
import de.nexuslobby.api.Module; import de.nexuslobby.api.Module;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Particle; import org.bukkit.Particle;
import org.bukkit.Sound; import org.bukkit.Sound;
@@ -15,6 +16,7 @@ import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
@@ -59,7 +61,6 @@ public class GadgetModule implements Module, Listener {
}, 1L, 1L); }, 1L, 1L);
} }
// Event für die Benutzung der aktiven Gadgets
@EventHandler @EventHandler
public void onInteract(PlayerInteractEvent event) { public void onInteract(PlayerInteractEvent event) {
ItemStack item = event.getItem(); ItemStack item = event.getItem();
@@ -80,7 +81,6 @@ public class GadgetModule implements Module, Listener {
} }
} }
// Verhindert Bewegung für eingefrorene Spieler (Stasis)
@EventHandler @EventHandler
public void onPlayerMove(PlayerMoveEvent event) { public void onPlayerMove(PlayerMoveEvent event) {
if (FreezeRay.frozenPlayers.contains(event.getPlayer().getUniqueId())) { if (FreezeRay.frozenPlayers.contains(event.getPlayer().getUniqueId())) {
@@ -95,19 +95,11 @@ public class GadgetModule implements Module, Listener {
if (hat == null || hat.getType() == Material.AIR) return; if (hat == null || hat.getType() == Material.AIR) return;
switch (hat.getType()) { switch (hat.getType()) {
case CAMPFIRE: 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);
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);
break; 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 SPAWNER: case ENCHANTING_TABLE -> p.getWorld().spawnParticle(Particle.ENCHANT, p.getLocation().add(0, 2.3, 0), 1, 0.2, 0.2, 0.2, 0.5);
p.getWorld().spawnParticle(Particle.FLAME, p.getLocation().add(0, 2.1, 0), 1, 0.12, 0.12, 0.12, 0.02); default -> {}
break;
case SEA_LANTERN:
case BEACON:
p.getWorld().spawnParticle(Particle.END_ROD, p.getLocation().add(0, 2.1, 0), 1, 0.1, 0.1, 0.1, 0.03);
break;
case ENCHANTING_TABLE:
p.getWorld().spawnParticle(Particle.ENCHANT, p.getLocation().add(0, 2.3, 0), 1, 0.2, 0.2, 0.2, 0.5);
break;
} }
} }
@@ -136,7 +128,6 @@ public class GadgetModule implements Module, Listener {
gui.setItem(14, createItem(Material.GLASS, "§fAstronaut", "§7Bereit für den Mond?")); 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(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(16, createItem(Material.CAKE, "§dKuchen-Kopf", "§7Jeder mag Kuchen!"));
gui.setItem(19, createItem(Material.SLIME_BLOCK, "§aGlibber-Block", "§7Ziemlich klebrig...")); gui.setItem(19, createItem(Material.SLIME_BLOCK, "§aGlibber-Block", "§7Ziemlich klebrig..."));
gui.setItem(20, createItem(Material.MELON, "§aMelonen-Helm", "§7Frisch und saftig")); 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(21, createItem(Material.HAY_BLOCK, "§eStrohhut", "§7Sommer auf dem Land"));
@@ -144,7 +135,6 @@ public class GadgetModule implements Module, Listener {
gui.setItem(23, createItem(Material.CRAFTING_TABLE, "§6Werkbank", "§7Immer am Basteln")); gui.setItem(23, createItem(Material.CRAFTING_TABLE, "§6Werkbank", "§7Immer am Basteln"));
gui.setItem(24, createItem(Material.BOOKSHELF, "§fBücherregal", "§7Ein wahrer Schlaukopf")); 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(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(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(29, createItem(Material.DIAMOND_ORE, "§bDiamant-Erz", "§7Bau mich bloß nicht ab!"));
gui.setItem(30, createItem(Material.BEACON, "§fLeuchtfeuer", "§7§oEffekt: Glitzern")); gui.setItem(30, createItem(Material.BEACON, "§fLeuchtfeuer", "§7§oEffekt: Glitzern"));
@@ -224,37 +214,32 @@ public class GadgetModule implements Module, Listener {
else if (item.getType() == Material.NETHER_STAR) openParticleGUI(player); else if (item.getType() == Material.NETHER_STAR) openParticleGUI(player);
else if (item.getType() == Material.FIREWORK_ROCKET) openFunGUI(player); else if (item.getType() == Material.FIREWORK_ROCKET) openFunGUI(player);
else if (item.getType() == Material.BARRIER) { removeGadgets(player); player.closeInventory(); } else if (item.getType() == Material.BARRIER) { removeGadgets(player); player.closeInventory(); }
} } else if (title.equals(HAT_TITLE)) {
else if (title.equals(HAT_TITLE)) {
if (item.getType() != Material.GRAY_STAINED_GLASS_PANE) { if (item.getType() != Material.GRAY_STAINED_GLASS_PANE) {
HatManager.setHat(player, item.getType(), item.getItemMeta().getDisplayName()); HatManager.setHat(player, item.getType(), item.getItemMeta().getDisplayName());
player.playSound(player.getLocation(), Sound.ITEM_ARMOR_EQUIP_GENERIC, 1, 1); player.playSound(player.getLocation(), Sound.ITEM_ARMOR_EQUIP_GENERIC, 1, 1);
player.closeInventory(); player.closeInventory();
} }
} } else if (title.equals(PET_TITLE)) {
else if (title.equals(PET_TITLE)) {
if (item.getType() == Material.BONE) PetManager.spawnEntityPet(player, "WOLF"); 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.CAT_SPAWN_EGG) PetManager.spawnEntityPet(player, "CAT");
else if (item.getType() == Material.PANDA_SPAWN_EGG) PetManager.spawnEntityPet(player, "PANDA"); else if (item.getType() == Material.PANDA_SPAWN_EGG) PetManager.spawnEntityPet(player, "PANDA");
player.sendMessage("§8[§6Nexus§8] §dDein Pet wurde gerufen!"); player.sendMessage("§8[§6Nexus§8] §dDein Pet wurde gerufen!");
player.closeInventory(); player.closeInventory();
} } else if (title.equals(BALLOON_TITLE)) {
else if (title.equals(BALLOON_TITLE)) {
if (item.getType().toString().endsWith("_WOOL")) { if (item.getType().toString().endsWith("_WOOL")) {
if (activeBalloons.containsKey(player.getUniqueId())) activeBalloons.get(player.getUniqueId()).remove(); if (activeBalloons.containsKey(player.getUniqueId())) activeBalloons.get(player.getUniqueId()).remove();
activeBalloons.put(player.getUniqueId(), new Balloon(player, item.getType())); activeBalloons.put(player.getUniqueId(), new Balloon(player, item.getType()));
player.sendMessage("§8[§6Nexus§8] §aBallon aktiviert!"); player.sendMessage("§8[§6Nexus§8] §aBallon aktiviert!");
player.closeInventory(); player.closeInventory();
} }
} } else if (title.equals(PARTICLE_TITLE)) {
else if (title.equals(PARTICLE_TITLE)) {
if (item.getType() == Material.POPPY) activeEffects.put(player.getUniqueId(), new ParticleEffect("hearts")); 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.BLAZE_POWDER) activeEffects.put(player.getUniqueId(), new ParticleEffect("flames"));
else if (item.getType() == Material.WATER_BUCKET) activeEffects.put(player.getUniqueId(), new ParticleEffect("cloud")); else if (item.getType() == Material.WATER_BUCKET) activeEffects.put(player.getUniqueId(), new ParticleEffect("cloud"));
player.sendMessage("§8[§6Nexus§8] §aPartikel aktiviert!"); player.sendMessage("§8[§6Nexus§8] §aPartikel aktiviert!");
player.closeInventory(); player.closeInventory();
} } else if (title.equals(FUN_TITLE)) {
else if (title.equals(FUN_TITLE)) {
if (item.getType() == Material.EGG) { if (item.getType() == Material.EGG) {
ChickenRain.start(player); ChickenRain.start(player);
player.sendMessage("§8[§6Nexus§8] §fHühnerregen gestartet!"); player.sendMessage("§8[§6Nexus§8] §fHühnerregen gestartet!");
@@ -288,7 +273,7 @@ public class GadgetModule implements Module, Listener {
public void onFish(PlayerFishEvent event) { public void onFish(PlayerFishEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
ItemStack item = player.getInventory().getItemInMainHand(); ItemStack item = player.getInventory().getItemInMainHand();
if (item != null && item.getType() == Material.FISHING_ROD && item.hasItemMeta() && item.getItemMeta().getDisplayName().equals("§b§lEnterhaken")) { if (item.getType() == Material.FISHING_ROD && item.hasItemMeta() && item.getItemMeta().getDisplayName().equals("§b§lEnterhaken")) {
if (event.getState() == PlayerFishEvent.State.IN_GROUND || event.getState() == PlayerFishEvent.State.REEL_IN || event.getState() == PlayerFishEvent.State.CAUGHT_ENTITY) { if (event.getState() == PlayerFishEvent.State.IN_GROUND || event.getState() == PlayerFishEvent.State.REEL_IN || event.getState() == PlayerFishEvent.State.CAUGHT_ENTITY) {
if (event.getHook() != null) { if (event.getHook() != null) {
GrapplingHook.pullPlayer(player, event.getHook().getLocation()); GrapplingHook.pullPlayer(player, event.getHook().getLocation());
@@ -314,6 +299,7 @@ public class GadgetModule implements Module, Listener {
} }
private void fillEdges(Inventory inv) { private void fillEdges(Inventory inv) {
// Bedrock braucht einen Space, um den Namen korrekt anzuzeigen
ItemStack glass = createItem(Material.GRAY_STAINED_GLASS_PANE, " ", null); ItemStack glass = createItem(Material.GRAY_STAINED_GLASS_PANE, " ", null);
for (int i = 0; i < inv.getSize(); i++) { 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); if (i < 9 || i >= inv.getSize() - 9 || i % 9 == 0 || (i + 1) % 9 == 0) inv.setItem(i, glass);
@@ -325,11 +311,19 @@ public class GadgetModule implements Module, Listener {
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
if (meta != null) { if (meta != null) {
meta.setDisplayName(name); meta.setDisplayName(name);
if (lore != null) {
// WICHTIG FÜR BEDROCK: Saubere ArrayList für Lore
List<String> l = new ArrayList<>(); List<String> l = new ArrayList<>();
l.add(lore); if (lore != null && !lore.isEmpty()) {
l.add(ChatColor.translateAlternateColorCodes('&', lore));
meta.setLore(l); meta.setLore(l);
} }
// VERSTECKT ATTRIBUTE: Verhindert "+Armor" etc., was bei Bedrock die Lore überdeckt
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
meta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE);
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
item.setItemMeta(meta); item.setItemMeta(meta);
} }
return item; return item;

View File

@@ -6,12 +6,12 @@ import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.GameRule;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType; // DIESER IMPORT HAT GEFEHLT
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@@ -54,8 +54,30 @@ public class LobbySettingsModule implements Module, Listener {
Set<String> keys = settingsConfig.getConfigurationSection("gamerules").getKeys(false); Set<String> keys = settingsConfig.getConfigurationSection("gamerules").getKeys(false);
for (World world : Bukkit.getWorlds()) { for (World world : Bukkit.getWorlds()) {
for (String key : keys) { for (String key : keys) {
String value = String.valueOf(settingsConfig.get("gamerules." + key)); Object value = settingsConfig.get("gamerules." + key);
world.setGameRuleValue(key, value); updateGameRule(world, key, value);
}
}
}
// Hilfsmethode zur sicheren Anwendung von GameRules in 1.21
private void updateGameRule(World world, String ruleName, Object value) {
GameRule<?> rule = GameRule.getByName(ruleName);
if (rule == null) return;
if (value instanceof Boolean && rule.getType() == Boolean.class) {
world.setGameRule((GameRule<Boolean>) rule, (Boolean) value);
} else if (value instanceof Integer && rule.getType() == Integer.class) {
world.setGameRule((GameRule<Integer>) rule, (Integer) value);
} else {
// Falls der Wert aus der Config als String kommt, versuchen wir ihn zu parsen
String strValue = String.valueOf(value);
if (rule.getType() == Boolean.class) {
world.setGameRule((GameRule<Boolean>) rule, Boolean.parseBoolean(strValue));
} else if (rule.getType() == Integer.class) {
try {
world.setGameRule((GameRule<Integer>) rule, Integer.parseInt(strValue));
} catch (NumberFormatException ignored) {}
} }
} }
} }
@@ -154,7 +176,7 @@ public class LobbySettingsModule implements Module, Listener {
settingsConfig.set(path, newValue); settingsConfig.set(path, newValue);
saveSettings(); saveSettings();
if (path.startsWith("gamerules.")) { if (path.startsWith("gamerules.")) {
for (World w : Bukkit.getWorlds()) w.setGameRuleValue(key, String.valueOf(newValue)); for (World w : Bukkit.getWorlds()) updateGameRule(w, key, newValue);
} }
} else if (value instanceof Integer) { } else if (value instanceof Integer) {
int newVal = (Integer) value + (event.getClick().isLeftClick() ? 1 : -1); int newVal = (Integer) value + (event.getClick().isLeftClick() ? 1 : -1);
@@ -162,7 +184,7 @@ public class LobbySettingsModule implements Module, Listener {
settingsConfig.set(path, newVal); settingsConfig.set(path, newVal);
saveSettings(); saveSettings();
if (path.startsWith("gamerules.")) { if (path.startsWith("gamerules.")) {
for (World w : Bukkit.getWorlds()) w.setGameRuleValue(key, String.valueOf(newVal)); for (World w : Bukkit.getWorlds()) updateGameRule(w, key, newVal);
} }
} }
@@ -171,7 +193,6 @@ public class LobbySettingsModule implements Module, Listener {
} }
private void refreshCategory(Player p, String category) { private void refreshCategory(Player p, String category) {
// Die refresh-Logik wurde vereinfacht, um Fehler zu vermeiden
if (category.equals("Lobby-Schutz")) openCategory(p, "Lobby-Schutz", "allowPvp", "allowBlockBreaking", "allowBlockPlacing", "allowBlockInteracting", "allowItemDropping", "allowItemPickup", "allowExplosions"); if (category.equals("Lobby-Schutz")) openCategory(p, "Lobby-Schutz", "allowPvp", "allowBlockBreaking", "allowBlockPlacing", "allowBlockInteracting", "allowItemDropping", "allowItemPickup", "allowExplosions");
else if (category.equals("Chat")) openCategory(p, "Chat", "announceAdvancements", "commandBlockOutput", "logAdminCommands", "sendCommandFeedback", "showDeathMessages", "reducedDebugInfo"); else if (category.equals("Chat")) openCategory(p, "Chat", "announceAdvancements", "commandBlockOutput", "logAdminCommands", "sendCommandFeedback", "showDeathMessages", "reducedDebugInfo");
else if (category.equals("Drops")) openCategory(p, "Drops", "keepInventory", "doEntityDrops", "doMobLoot", "doTileDrops", "mobExplosionDropDecay", "blockExplosionDropDecay", "tntExplosionDropDecay"); else if (category.equals("Drops")) openCategory(p, "Drops", "keepInventory", "doEntityDrops", "doMobLoot", "doTileDrops", "mobExplosionDropDecay", "blockExplosionDropDecay", "tntExplosionDropDecay");

View File

@@ -160,3 +160,19 @@ hider:
all: "&aAlle Spieler: &7Sichtbar" all: "&aAlle Spieler: &7Sichtbar"
# Anzeigename des Items und Nachricht, wenn alle versteckt sind # Anzeigename des Items und Nachricht, wenn alle versteckt sind
none: "&cKeine Spieler: &7Versteckt" none: "&cKeine Spieler: &7Versteckt"
# -----------------------------------------------------
# BALL / SOCCER EINSTELLUNGEN
# -----------------------------------------------------
ball:
enabled: true
# Der Spawnpunkt wird automatisch über /nexus ball setspawn hier gespeichert
spawn:
world: "world"
x: 10.5
y: 65.0
z: 10.5
yaw: 0.0
pitch: 0.0
# Zeit in Sekunden, bis der Ball bei Inaktivität respawnt
respawn_delay: 60

View File

@@ -0,0 +1,164 @@
# =============================================================
# NexusLobby - Lebendige Dialoge v2
# =============================================================
conversations:
parkour_begruessung:
morgens:
dialogue:
- '&6&lTrainer &8» &fGuten Morgen! Zeit für Frühsport! *streckt sich*'
- '&6&lTrainer &8» &fWillkommen bei &e&lNexusLobby&f!'
- '&6&lTrainer &8» &eKlick mich an&f, um den Parkour zu starten!'
mittags:
dialogue:
- '&6&lTrainer &8» &fDie Sonne brennt, der Parkour wartet!'
- '&6&lTrainer &8» &fHast du das Zeug zum &aParkour-Meister&f?'
- '&6&lTrainer &8» &eKlick mich an&f, wenn du dich traust!'
abends:
dialogue:
- '&6&lTrainer &8» &fNoch eine Runde vor dem Schlafengehen?'
- '&6&lTrainer &8» &fZeig bei &e&lNexusLobby&f, was du noch drauf hast!'
- '&6&lTrainer &8» &eKlick mich an&f, für deinen neuen Rekord!'
owner_besuch:
morgens:
dialogue:
- '&dTimmy: &fMami, ist der Owner schon wach? &e*hüpft*'
- '&5Sarah: &7Bestimmt! Er schließt den Server auf.'
- '&dTimmy: &fIch zeig ihm meinen Teddy mit Krone! &a*stolz*'
- '&5Sarah: &7Leise sein, falls er noch arbeitet. *psst*'
mittags:
dialogue:
- '&dTimmy: &fDa ist das Büro! Ich seh die Fenster! &e*rennt*'
- '&5Sarah: &cStopp! &7Nicht so stürmisch, Timmy.'
- '&dTimmy: &fAber Teddy will den Schreibtisch sehen!'
- '&5Sarah: &7Komm an meine Hand. Wir klopfen ganz brav.'
abends:
dialogue:
- '&dTimmy: &fGuck! Im Büro brennt noch Licht! &b*zeigt*'
- '&5Sarah: &7Er arbeitet sicher noch an Updates.'
- '&dTimmy: &fIst er ein Roboter? Er schläft nie! &7*staunt*'
- '&5Sarah: &7Nein, er braucht nur viel Zaubertrank. *lacht*'
fussball_match:
morgens:
dialogue:
- '&eLeon: &fFinn! Aufwachen! Kick den Ball! &e*kickt*'
- '&6Finn: &8*gähnt* &7Mein Fuß schläft noch, Leon...'
- '&eLeon: &fKeine Ausreden! Pass an! &6*kickt hart*'
- '&6Finn: &fHuch! &7*stoppt unsicher* &fBin ja schon wach!'
mittags:
dialogue:
- '&eLeon: &fPass auf! Jetzt kommt mein Spezialschuss!'
- '&6Finn: &fDen hab ich! &e*macht Hechtsprung* &fJaaaa!'
- '&eLeon: &7Wie hast du den denn erwischt? &c*schmollt*'
- '&6Finn: &fIch kenne deine Tricks, Leon! *grinst*'
abends:
dialogue:
- '&eLeon: &7Ich seh den Ball kaum noch. &8*kneift Augen*'
- '&6Finn: &fEgal! Nächstes Tor gewinnt die Krone!'
- '&eLeon: &fHe! Das war Foul! Du hast geschubst! &c*meckert*'
- '&6Finn: &7Körpereinsatz! Fang mich doch! &a*rennt weg*'
baum_drama:
morgens:
dialogue:
- '&aLotte: &fDie Aussicht ist göttlich! &d*atmet tief*'
- '&bSchmidt: &7Lotte, komm runter! Es ist 7 Uhr morgens!'
- '&aLotte: &fIch beobachte Vögel. Ich bin jetzt einer!'
- '&bSchmidt: &7Du brauchst Kaffee, keinen Baum. &8*seufzt*'
mittags:
dialogue:
- '&aLotte: &fIch kann fliegen! Seht mich an! &7*balanciert*'
- '&bSchmidt: &cLotte, komm sofort vom Baum runter!'
- '&aLotte: &fIch bin ein stolzer Adler! &e*breitet Arme aus*'
- '&bSchmidt: &7Du bist eine Frau auf einer Birke! Abstieg!'
abends:
dialogue:
- '&aLotte: &fVon hier sieht man das Feuerwerk besser!'
- '&bSchmidt: &7Es wird kalt. Und da oben sind Spinnen!'
- '&aLotte: &fSpinnen? &7*schaut hektisch* &fWo?!'
- '&bSchmidt: &7Komm zur Leiter. Ich rette dich. &e*grinst*'
familien_spaziergang:
morgens:
dialogue:
- '&9Tom: &7Schaut mal diesen Sonnenaufgang an. &6*genießt*'
- '&5Eva: &7Lass dir Zeit. Die Welt wacht gerade erst auf.'
- '&dJasmin: &fPapa, die Blumen gehen auf! &e*bleibt stehen*'
- '&9Tom: &7Wollen wir zum Bäcker? Frische Brötchen!'
mittags:
dialogue:
- '&9Tom: &7Klar, Jasmin. Wünsch dir was ganz Besonderes!'
- '&5Eva: &7Nicht reinfallen! Das Wasser ist tief. &6*lacht*'
- '&dJasmin: &fDarf ich eine Münze werfen? Bitte! &d*hüpft*'
- '&9Tom: &7Ich wünsche mir... &7*kneift Augen zu* &f...Eis!'
abends:
dialogue:
- '&9Tom: &7Der ganze Spawn leuchtet jetzt schön. &b*guckt*'
- '&5Eva: &7Es wird so herrlich ruhig hier, oder? &d*lächelt*'
- '&dJasmin: &fPapa, darf ich auf deine Schultern? &7*gähnt*'
- '&9Tom: &7Hopp! &e*hebt sie hoch* &7Na, wie ist die Sicht?'
frauen_plausch:
morgens:
dialogue:
- '&9Marie: &7Guten Morgen! Du siehst verschlafen aus.'
- '&fPia: &7Die Party gestern war zu lang. Kaffee... &8*gähnt*'
- '&9Marie: &7Der Bäcker hat frische Zimtschnecken! Komm!'
- '&fPia: &fSorg dafür, dass ich nicht umkippe. &7*lacht*'
mittags:
dialogue:
- '&9Marie: &7Hast du den neuen Shop gesehen? Tolle Erze!'
- '&fPia: &fEcht jetzt? &7Ich dachte, die Mine ist zu.'
- '&9Marie: &7Die haben einen neuen Tunnel! Riesige Smaragde!'
- '&fPia: &fWahnsinn. Ich muss mein Inventar leeren!'
abends:
dialogue:
- '&9Marie: &7Hast du die Lichter am Hafen gesehen? &b*staunt*'
- '&fPia: &7Leider verpasst... ich musste Truhen sortieren.'
- '&9Marie: &7Du arbeitest zu viel, Pia. Genieß den Abend!'
- '&fPia: &7Stimmt. Morgen machen wir blau, okay?'
wettrennen_jungs:
morgens:
dialogue:
- '&bNico: &fErster am Portal! Lauf schneller, Lukas!'
- '&fLukas: &c*keucht* &fWarte! Meine Schuhe sind offen!'
- '&bNico: &fKeine Ausreden! Die Sonne lacht! &a*rennt*'
- '&fLukas: &fNa warte, ich krieg dich noch! &7*sprintet*'
mittags:
dialogue:
- '&bNico: &fKomm schon, du lahme Ente! &a*rast davon*'
- '&fLukas: &c*außer Atem* &7Ich... hab heute schon gefarmt!'
- '&bNico: &fErster! Gewonnen! &7*tanzt* &fHer mit dem Apfel!'
- '&fLukas: &fMorgen gewinnen meine Speed-Stiefel! &c*schwitzt*'
abends:
dialogue:
- '&bNico: &fLetztes Rennen! Verlierer poliert Rüstungen!'
- '&fLukas: &fDiesmal nicht, Nico! &e*nimmt Anlauf*'
- '&bNico: &fOh, jetzt wird es ernst? &7Fertig... LOS!'
- '&fLukas: &fJaaa! Ich bin vorne! Wer ist jetzt lahm?! &a*lacht*'
mutter_kind_spiel:
morgens:
dialogue:
- '&dMia: &fMami, schau! Meine Puppen warten schon. &d*zeigt*'
- '&5Sandra: &7Warten sie auf den Empfang, Mia?'
- '&dMia: &fJa, sie wollen zum Owner! &e*rückt Puppe recht*'
- '&5Sandra: &7Dann müssen sie brav Schlange stehen. &7*lächelt*'
mittags:
dialogue:
- '&dMia: &fGuck! Ein riesiges Hotel aus Klötzen! &e*stapelt*'
- '&5Sandra: &7Oha, wird das ein Dino-Hotel?'
- '&dMia: &fJa! Der Dino frisst nur Kekse! &e*füttert ihn*'
- '&5Sandra: &7Bau fleißig weiter, kleine Architektin.'
abends:
dialogue:
- '&dMia: &fMami, Dino ist müde. &7*gähnt laut*'
- '&5Sandra: &7Pack ihn gut in seine Decke ein, Mia.'
- '&dMia: &fMuss ich meine Klötze einpacken? &c*traurig*'
- '&5Sandra: &7Ja, aber morgen bauen wir ein Schloss!'
links:

View File

@@ -1,6 +1,6 @@
name: NexusLobby name: NexusLobby
main: de.nexuslobby.NexusLobby main: de.nexuslobby.NexusLobby
version: "1.0.8" version: "1.1.0"
api-version: "1.21" api-version: "1.21"
author: M_Viper author: M_Viper
description: Modular Lobby Plugin with an invisible Particle-Parkour system. description: Modular Lobby Plugin with an invisible Particle-Parkour system.