From 43b4ab60e4c25aab53095824316ead14d20f6a10 Mon Sep 17 00:00:00 2001 From: SimolZimol <70102430+SimolZimol@users.noreply.github.com> Date: Thu, 9 Oct 2025 18:56:48 +0200 Subject: [PATCH] modified: plugin.yml modified: src/main/java/com/simolzimol/levelcraft/LevelCraft.java modified: src/main/java/com/simolzimol/levelcraft/command/TestSmithChestCommand.java modified: src/main/java/com/simolzimol/levelcraft/item/ItemUtil.java modified: src/main/java/com/simolzimol/levelcraft/item/Rarity.java modified: src/main/java/com/simolzimol/levelcraft/listener/CustomStatsListener.java modified: src/main/java/com/simolzimol/levelcraft/system/PlayerStatsManager.java --- plugin.yml | 14 ++++- .../com/simolzimol/levelcraft/LevelCraft.java | 15 +++-- .../command/TestSmithChestCommand.java | 8 +-- .../simolzimol/levelcraft/item/ItemUtil.java | 63 +++++++++---------- .../simolzimol/levelcraft/item/Rarity.java | 20 +++--- .../listener/CustomStatsListener.java | 16 ++--- .../levelcraft/system/PlayerStatsManager.java | 10 +-- 7 files changed, 81 insertions(+), 65 deletions(-) diff --git a/plugin.yml b/plugin.yml index 3ef6fda..ea334eb 100644 --- a/plugin.yml +++ b/plugin.yml @@ -3,7 +3,17 @@ main: com.simolzimol.levelcraft.LevelCraft version: 1.0 api-version: 1.21 author: SimolZimol -description: TEXT +description: RPG-Style Item Enhancement Plugin with custom stats, rarities and bonuses + commands: testsmithchest: - description: Gibt dir eine Kiste \ No newline at end of file + description: Spawns a weaponsmith chest for testing + usage: /testsmithchest + +permissions: + levelcraft.admin: + description: Administrative commands for LevelCraft + default: op + levelcraft.use: + description: Basic usage of LevelCraft features + default: true \ No newline at end of file diff --git a/src/main/java/com/simolzimol/levelcraft/LevelCraft.java b/src/main/java/com/simolzimol/levelcraft/LevelCraft.java index 918d534..a6cb17c 100644 --- a/src/main/java/com/simolzimol/levelcraft/LevelCraft.java +++ b/src/main/java/com/simolzimol/levelcraft/LevelCraft.java @@ -3,9 +3,16 @@ package com.simolzimol.levelcraft; import org.bukkit.plugin.java.JavaPlugin; public class LevelCraft extends JavaPlugin { + private static LevelCraft instance; + + public static LevelCraft getInstance() { + return instance; + } + @Override public void onEnable() { - getLogger().info("LevelCraft aktiviert!"); + instance = this; + getLogger().info("LevelCraft enabled!"); com.simolzimol.levelcraft.item.ItemUtil.init(this); getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.CraftListener(), this); getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.LootListener(this), this); @@ -15,13 +22,13 @@ public class LevelCraft extends JavaPlugin { getServer().getPluginManager().registerEvents(new com.simolzimol.levelcraft.listener.CustomStatsListener(), this); getCommand("testsmithchest").setExecutor(new com.simolzimol.levelcraft.command.TestSmithChestCommand()); - // ActionBar-Task für alle Spieler starten + // Start ActionBar task for all players com.simolzimol.levelcraft.system.PlayerStatsManager.startActionBarTask(this); - com.simolzimol.levelcraft.system.PlayerStatsManager.startRegenTask(this); // <--- hinzufügen + com.simolzimol.levelcraft.system.PlayerStatsManager.startRegenTask(this); } @Override public void onDisable() { - getLogger().info("LevelCraft deaktiviert!"); + getLogger().info("LevelCraft disabled!"); } } diff --git a/src/main/java/com/simolzimol/levelcraft/command/TestSmithChestCommand.java b/src/main/java/com/simolzimol/levelcraft/command/TestSmithChestCommand.java index a773e06..966fb9d 100644 --- a/src/main/java/com/simolzimol/levelcraft/command/TestSmithChestCommand.java +++ b/src/main/java/com/simolzimol/levelcraft/command/TestSmithChestCommand.java @@ -15,7 +15,7 @@ public class TestSmithChestCommand implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (!(sender instanceof Player player)) { - sender.sendMessage("Nur Spieler können diesen Befehl nutzen."); + sender.sendMessage("Only players can use this command."); return true; } @@ -23,15 +23,15 @@ public class TestSmithChestCommand implements CommandExecutor { World world = loc.getWorld(); Block block = world.getBlockAt(loc); - // Setze Block zu Kiste + // Set block to chest block.setType(Material.CHEST); Chest chest = (Chest) block.getState(); - // Setze den Schmied-Lootpool + // Set weaponsmith loot table chest.setLootTable(LootTables.VILLAGE_WEAPONSMITH.getLootTable()); chest.update(); - player.sendMessage("Kiste mit Schmied-Loot an deiner Position gespawnt!"); + player.sendMessage("Weaponsmith chest spawned at your location!"); return true; } } \ No newline at end of file diff --git a/src/main/java/com/simolzimol/levelcraft/item/ItemUtil.java b/src/main/java/com/simolzimol/levelcraft/item/ItemUtil.java index 30c40b8..475f7c6 100644 --- a/src/main/java/com/simolzimol/levelcraft/item/ItemUtil.java +++ b/src/main/java/com/simolzimol/levelcraft/item/ItemUtil.java @@ -1,16 +1,12 @@ package com.simolzimol.levelcraft.item; import org.bukkit.NamespacedKey; -import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataType; import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.inventory.EquipmentSlot; -import java.util.List; import java.util.UUID; public class ItemUtil { @@ -25,10 +21,10 @@ public class ItemUtil { public static void setRarity(ItemStack item, Rarity rarity) { ItemMeta meta = item.getItemMeta(); meta.getPersistentDataContainer().set(rarityKey, PersistentDataType.INTEGER, rarity.getValue()); - // Lore aktualisieren (alte Zeile ersetzen) - java.util.List lore = meta.hasLore() ? meta.getLore() : new java.util.ArrayList<>(); - lore.add(rarity.getDisplayName() + "§7 Seltenheit"); - meta.setLore(lore); + // Update lore (replace old line) + java.util.List lore = meta.hasLore() ? meta.lore() : new java.util.ArrayList<>(); + lore.add(net.kyori.adventure.text.Component.text(rarity.getDisplayName() + "§7 Rarity")); + meta.lore(lore); item.setItemMeta(meta); } @@ -61,7 +57,7 @@ public class ItemUtil { public static void addRandomBonuses(ItemStack item, Rarity rarity, java.util.Random random) { ItemMeta meta = item.getItemMeta(); - java.util.List lore = meta.hasLore() ? meta.getLore() : new java.util.ArrayList<>(); + java.util.List lore = meta.hasLore() ? meta.lore() : new java.util.ArrayList<>(); int stats = switch (rarity) { case COMMON -> 1; @@ -95,8 +91,10 @@ public class ItemUtil { case "DURABILITY" -> { double percent = tier.getMinDurability() + (tier.getMaxDurability() - tier.getMinDurability()) * random.nextDouble(); int bonus = (int) Math.round(item.getType().getMaxDurability() * percent); - lore.add(tier.getDisplay() + ": +" + (int)(percent*100) + "% Haltbarkeit (" + bonus + " Punkte)"); - item.setDurability((short) 0); // Item ist voll repariert + lore.add(net.kyori.adventure.text.Component.text(tier.getDisplay() + ": +" + (int)(percent*100) + "% Durability (" + bonus + " points)")); + if (meta instanceof org.bukkit.inventory.meta.Damageable damageable) { + damageable.setDamage(0); // Item is fully repaired + } } case "DAMAGE" -> { double percent = tier.getMinDamage() + (tier.getMaxDamage() - tier.getMinDamage()) * random.nextDouble(); @@ -105,11 +103,11 @@ public class ItemUtil { double newDamage = base + bonus; meta.addAttributeModifier( org.bukkit.attribute.Attribute.GENERIC_ATTACK_DAMAGE, - new AttributeModifier(UUID.nameUUIDFromBytes("levelcraft_base_damage".getBytes()), "levelcraft_base_damage", base, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.HAND)); + new AttributeModifier(new NamespacedKey("levelcraft", "base_damage"), base, AttributeModifier.Operation.ADD_NUMBER)); meta.addAttributeModifier( org.bukkit.attribute.Attribute.GENERIC_ATTACK_DAMAGE, - new AttributeModifier(UUID.randomUUID(), "levelcraft_bonus_damage", bonus, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.HAND)); - lore.add(tier.getDisplay() + ": +" + String.format("%.2f", bonus) + " Angriffsschaden (gesamt: " + String.format("%.2f", newDamage) + ")"); + new AttributeModifier(new NamespacedKey("levelcraft", "bonus_damage"), bonus, AttributeModifier.Operation.ADD_NUMBER)); + lore.add(net.kyori.adventure.text.Component.text(tier.getDisplay() + ": +" + String.format("%.2f", bonus) + " Attack Damage (total: " + String.format("%.2f", newDamage) + ")")); } case "ARMOR" -> { double base = getBaseArmor(item); @@ -127,11 +125,11 @@ public class ItemUtil { double bonus = base * percent * 10; double newArmor = base + bonus; meta.getPersistentDataContainer().set(new NamespacedKey("levelcraft", "custom_armor"), PersistentDataType.DOUBLE, newArmor); - lore.add(tier.getDisplay() + ": +" + String.format("%.2f", bonus) + " Rüstung (Basis: " + String.format("%.2f", base) + ", gesamt: " + String.format("%.2f", newArmor) + " /100)"); + lore.add(net.kyori.adventure.text.Component.text(tier.getDisplay() + ": +" + String.format("%.2f", bonus) + " Armor (base: " + String.format("%.2f", base) + ", total: " + String.format("%.2f", newArmor) + " /100)")); } else { // CURSED: Nur Basiswert, keine Boni, keine Effekte, keine Skills meta.getPersistentDataContainer().set(new NamespacedKey("levelcraft", "custom_armor"), PersistentDataType.DOUBLE, base); - lore.add("§8Verflucht: Nur Basis-Rüstung (" + String.format("%.2f", base) + " /100)"); + lore.add(net.kyori.adventure.text.Component.text("§8Cursed: Base armor only (" + String.format("%.2f", base) + " /100)")); } } case "MINING_SPEED" -> { @@ -139,16 +137,16 @@ public class ItemUtil { double bonus = 4.0 * percent * 10; // Bonus x10 meta.addAttributeModifier( org.bukkit.attribute.Attribute.GENERIC_ATTACK_SPEED, - new AttributeModifier(UUID.randomUUID(), "levelcraft_bonus_mining_speed", bonus, AttributeModifier.Operation.ADD_NUMBER)); - lore.add(tier.getDisplay() + ": +" + String.format("%.2f", bonus) + " Abbausgeschwindigkeit"); + new AttributeModifier(new NamespacedKey("levelcraft", "mining_speed"), bonus, AttributeModifier.Operation.ADD_NUMBER)); + lore.add(net.kyori.adventure.text.Component.text(tier.getDisplay() + ": +" + String.format("%.2f", bonus) + " Mining Speed")); } case "LUCK" -> { double percent = tier.getMinLuck() + (tier.getMaxLuck() - tier.getMinLuck()) * random.nextDouble(); double bonus = 1.0 * percent * 10; // Bonus x10 meta.addAttributeModifier( org.bukkit.attribute.Attribute.GENERIC_LUCK, - new AttributeModifier(UUID.randomUUID(), "levelcraft_bonus_luck", bonus, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.HAND)); - lore.add(tier.getDisplay() + ": +" + String.format("%.2f", bonus) + " Glück"); + new AttributeModifier(new NamespacedKey("levelcraft", "bonus_luck"), bonus, AttributeModifier.Operation.ADD_NUMBER)); + lore.add(net.kyori.adventure.text.Component.text(tier.getDisplay() + ": +" + String.format("%.2f", bonus) + " Luck")); } case "ATTACK_SPEED" -> { double percent = tier.getMinAttackSpeed() + (tier.getMaxAttackSpeed() - tier.getMinAttackSpeed()) * random.nextDouble(); @@ -156,15 +154,15 @@ public class ItemUtil { double malus = base * percent; double newSpeed = base - malus; if (newSpeed < 0.1) newSpeed = 0.1; - // Basiswert als Modifier setzen + // Set base value as modifier meta.addAttributeModifier( org.bukkit.attribute.Attribute.GENERIC_ATTACK_SPEED, - new AttributeModifier(UUID.nameUUIDFromBytes("levelcraft_base_attackspeed".getBytes()), "levelcraft_base_attackspeed", base, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.HAND)); - // Bonus als Modifier setzen (negativ, weil niedriger besser) + new AttributeModifier(new NamespacedKey("levelcraft", "base_attack_speed"), base, AttributeModifier.Operation.ADD_NUMBER)); + // Set bonus as modifier (negative because lower is better) meta.addAttributeModifier( org.bukkit.attribute.Attribute.GENERIC_ATTACK_SPEED, - new AttributeModifier(UUID.randomUUID(), "levelcraft_bonus_attackspeed", -malus, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.HAND)); - lore.add(tier.getDisplay() + ": -" + String.format("%.2f", malus) + " Angriffsgeschwindigkeit (neu: " + String.format("%.2f", newSpeed) + ")"); + new AttributeModifier(new NamespacedKey("levelcraft", "bonus_attack_speed"), -malus, AttributeModifier.Operation.ADD_NUMBER)); + lore.add(net.kyori.adventure.text.Component.text(tier.getDisplay() + ": -" + String.format("%.2f", malus) + " Attack Speed (new: " + String.format("%.2f", newSpeed) + ")")); } } } @@ -175,17 +173,17 @@ public class ItemUtil { java.util.Collections.shuffle(effectsList, random); int effects = 1; for (int i = 0; i < effects && i < effectsList.size(); i++) { - lore.add(effectsList.get(i)); + lore.add(net.kyori.adventure.text.Component.text(effectsList.get(i))); } java.util.List skillsList = new java.util.ArrayList<>(ItemEffects.SKILLS); java.util.Collections.shuffle(skillsList, random); int skills = 1; for (int i = 0; i < skills && i < skillsList.size(); i++) { - lore.add(skillsList.get(i)); + lore.add(net.kyori.adventure.text.Component.text(skillsList.get(i))); } } - meta.setLore(lore); + meta.lore(lore); item.setItemMeta(meta); // --- Basiswert für Armor IMMER setzen, auch für CURSED --- @@ -195,9 +193,10 @@ public class ItemUtil { if (current == null) { meta.getPersistentDataContainer().set(new NamespacedKey("levelcraft", "custom_armor"), PersistentDataType.DOUBLE, base); // Basiswert auch in der Lore, falls noch nicht vorhanden - boolean found = lore.stream().anyMatch(s -> s.contains("Basis-Rüstung") || s.contains("Basis:")); - if (!found) lore.add("§7Basis-Rüstung: " + String.format("%.2f", base) + " /100"); - meta.setLore(lore); + boolean found = lore.stream().anyMatch(s -> net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer.plainText().serialize(s).contains("Base armor") || + net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer.plainText().serialize(s).contains("base:")); + if (!found) lore.add(net.kyori.adventure.text.Component.text("§7Base armor: " + String.format("%.2f", base) + " /100")); + meta.lore(lore); item.setItemMeta(meta); } } @@ -224,7 +223,7 @@ public class ItemUtil { if (armor > 0) stats += "§b" + String.format("%.2f", armor) + "🛡 "; if (speed > 0) stats += "§a" + String.format("%.2f", speed) + "⏩ "; if (luck > 0) stats += "§d" + String.format("%.2f", luck) + "☘ "; - player.sendActionBar(stats.trim()); + player.sendActionBar(net.kyori.adventure.text.Component.text(stats.trim())); } // Hilfsmethoden für Item-Typen: diff --git a/src/main/java/com/simolzimol/levelcraft/item/Rarity.java b/src/main/java/com/simolzimol/levelcraft/item/Rarity.java index ed7fbe8..7c98a80 100644 --- a/src/main/java/com/simolzimol/levelcraft/item/Rarity.java +++ b/src/main/java/com/simolzimol/levelcraft/item/Rarity.java @@ -1,15 +1,15 @@ package com.simolzimol.levelcraft.item; public enum Rarity { - CURSED(-1, "§8Verflucht", 0.02), // Sehr selten, negativ - COMMON(0, "§7Gewöhnlich", 0.50), // Am häufigsten (50%) - UNCOMMON(1, "§aUngewöhnlich", 0.20), // 20% - RARE(2, "§9Selten", 0.12), // 12% - EPIC(3, "§5Episch", 0.08), // 8% - LEGENDARY(4, "§6Legendär", 0.05), // 5% - MYTHIC(5, "§dMythisch", 0.025), // 2.5% - ANCIENT(6, "§eUralte", 0.012), // 1.2% - DIVINE(7, "§bGöttlich", 0.003); // 0.3% + CURSED(-1, "§8Cursed", 0.02), // Very rare, negative + COMMON(0, "§7Common", 0.50), // Most frequent (50%) + UNCOMMON(1, "§aUncommon", 0.20), // 20% + RARE(2, "§9Rare", 0.12), // 12% + EPIC(3, "§5Epic", 0.08), // 8% + LEGENDARY(4, "§6Legendary", 0.05), // 5% + MYTHIC(5, "§dMythic", 0.025), // 2.5% + ANCIENT(6, "§eAncient", 0.012), // 1.2% + DIVINE(7, "§bDivine", 0.003); // 0.3% private final int value; private final String displayName; @@ -40,7 +40,7 @@ public enum Rarity { return COMMON; } - // Zufällige Rarity nach Gewichtung (ohne CURSED) + // Random rarity by weight (without CURSED) public static Rarity getRandomRarity(java.util.Random random, boolean allowCursed, int maxRarity) { double roll = random.nextDouble(); double cumulative = 0.0; diff --git a/src/main/java/com/simolzimol/levelcraft/listener/CustomStatsListener.java b/src/main/java/com/simolzimol/levelcraft/listener/CustomStatsListener.java index 7cf61f4..17bb1c7 100644 --- a/src/main/java/com/simolzimol/levelcraft/listener/CustomStatsListener.java +++ b/src/main/java/com/simolzimol/levelcraft/listener/CustomStatsListener.java @@ -23,14 +23,14 @@ public class CustomStatsListener implements Listener { hp -= damage; PlayerStatsManager.setHP(player, hp); - // Nach 1 Sekunde wieder die Stats anzeigen + // Show stats again after 1 second org.bukkit.Bukkit.getScheduler().runTaskLater( - org.bukkit.Bukkit.getPluginManager().getPlugin("LevelCraft"), + com.simolzimol.levelcraft.LevelCraft.getInstance(), () -> PlayerStatsManager.showStats(player), - 20L // 1 Sekunde + 20L // 1 second ); - if (hp <= 0) player.setHealth(0); // Spieler töten + if (hp <= 0) player.setHealth(0); // Kill player } public static void updatePlayerArmor(Player player) { @@ -43,16 +43,16 @@ public class CustomStatsListener implements Listener { if (armor != null) totalArmor += armor; } PlayerStatsManager.setArmor(player, totalArmor); - // ActionBar sofort updaten + // Update ActionBar immediately PlayerStatsManager.showStats(player); } @EventHandler public void onInventoryClick(org.bukkit.event.inventory.InventoryClickEvent event) { if (!(event.getWhoClicked() instanceof Player player)) return; - // Verzögert ausführen, damit das Inventar schon aktualisiert ist + // Execute delayed so inventory is already updated org.bukkit.Bukkit.getScheduler().runTaskLater( - org.bukkit.Bukkit.getPluginManager().getPlugin("LevelCraft"), + com.simolzimol.levelcraft.LevelCraft.getInstance(), () -> updatePlayerArmor(player), 1L ); @@ -66,7 +66,7 @@ public class CustomStatsListener implements Listener { @EventHandler public void onRespawn(org.bukkit.event.player.PlayerRespawnEvent event) { org.bukkit.Bukkit.getScheduler().runTaskLater( - org.bukkit.Bukkit.getPluginManager().getPlugin("LevelCraft"), + com.simolzimol.levelcraft.LevelCraft.getInstance(), () -> updatePlayerArmor(event.getPlayer()), 1L ); diff --git a/src/main/java/com/simolzimol/levelcraft/system/PlayerStatsManager.java b/src/main/java/com/simolzimol/levelcraft/system/PlayerStatsManager.java index 5e74969..7b26dea 100644 --- a/src/main/java/com/simolzimol/levelcraft/system/PlayerStatsManager.java +++ b/src/main/java/com/simolzimol/levelcraft/system/PlayerStatsManager.java @@ -39,10 +39,10 @@ public class PlayerStatsManager { double hpVal = getHP(p); double armorVal = getArmor(p); double manaVal = getMana(p); - p.sendActionBar("§cHP: " + Math.round(hpVal*10)/10.0 + " §bRüstung: " + Math.round(armorVal*10)/10.0 + " §9Mana: " + Math.round(manaVal*10)/10.0); + p.sendActionBar(net.kyori.adventure.text.Component.text("§cHP: " + Math.round(hpVal*10)/10.0 + " §bArmor: " + Math.round(armorVal*10)/10.0 + " §9Mana: " + Math.round(manaVal*10)/10.0)); } } - }.runTaskTimer(plugin, 0L, 20L); // alle 20 Ticks = 1 Sekunde + }.runTaskTimer(plugin, 0L, 20L); // every 20 ticks = 1 second } public static void startRegenTask(org.bukkit.plugin.Plugin plugin) { @@ -52,17 +52,17 @@ public class PlayerStatsManager { for (Player p : Bukkit.getOnlinePlayers()) { double hp = getHP(p); if (hp < 20.0) { - setHP(p, Math.min(20.0, hp + 0.2)); // 0.2 HP pro Sekunde + setHP(p, Math.min(20.0, hp + 0.2)); // 0.2 HP per second } } } - }.runTaskTimer(plugin, 0L, 20L); // alle 20 Ticks = 1 Sekunde + }.runTaskTimer(plugin, 0L, 20L); // every 20 ticks = 1 second } public static void showStats(Player p) { double hpVal = getHP(p); double armorVal = getArmor(p); double manaVal = getMana(p); - p.sendActionBar("§cHP: " + Math.round(hpVal*10)/10.0 + " §bRüstung: " + Math.round(armorVal*10)/10.0 + " §9Mana: " + Math.round(manaVal*10)/10.0); + p.sendActionBar(net.kyori.adventure.text.Component.text("§cHP: " + Math.round(hpVal*10)/10.0 + " §bArmor: " + Math.round(armorVal*10)/10.0 + " §9Mana: " + Math.round(manaVal*10)/10.0)); } }